C 从文件中的一行读取任意数量的空格分隔字符

C 从文件中的一行读取任意数量的空格分隔字符,c,fgets,strtok,C,Fgets,Strtok,我有一个文件,在一行中有任意数量的数字可以作为整数读取。在一个最小的、可复制的示例中,我创建了一个仅包含以下行的文件test.dat: 1 2 3 4 然后我尝试使用fgets和strtok来实现这一点: #include <stdio.h> #include <string.h> #include <stdlib.h> int main(){ FILE* fileptr; fileptr = fopen("test.dat","r"); char

我有一个文件,在一行中有任意数量的数字可以作为整数读取。在一个最小的、可复制的示例中,我创建了一个仅包含以下行的文件
test.dat

 1 2 3 4
然后我尝试使用
fgets
strtok
来实现这一点:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(){

FILE* fileptr;

fileptr = fopen("test.dat","r");
char line[500];
char *token;

int array[20];
int i = 0;

fgets(line,300,fileptr);

token = strtok(line," ");
array[i] = atoi(token);
printf("%d\n", array[i]);
i++;

while(token != NULL){
    token = strtok(line," ");
    array[i] = atoi(token);
    printf("%d\n", array[i]);
    i++;
}

return 0;
}
#包括
#包括
#包括
int main(){
文件*fileptr;
fileptr=fopen(“test.dat”,“r”);
字符行[500];
字符*令牌;
int数组[20];
int i=0;
fgets(线路,300,文件处理器);
令牌=strtok(第行“”);
数组[i]=atoi(令牌);
printf(“%d\n”,数组[i]);
i++;
while(令牌!=NULL){
令牌=strtok(第行“”);
数组[i]=atoi(令牌);
printf(“%d\n”,数组[i]);
i++;
}
返回0;
}
但这会导致打印21行
1
,然后是632行
0
。最后它给出了一个分段错误,因为
i
增长大于20,即
数组的分配空间。我不明白的是为什么要打印600多行,为什么我永远无法读取文件中的数字
1
。我错过了什么

注意:我更喜欢使用
fgets
继续读取文件,因为这将是对读取整个文件的现有子例程的简单修改。

以下几点:

  • 您没有将循环限制为
    array
  • 您的循环结构不正确。所有存储应在环路内完成;离群值先验不必存在
  • 在循环中调用strtok
是错误的。
strtok
初始值的延续应指定
NULL
作为第一个参数。有关更多信息和用法示例,请参阅文档 解决这些问题的示例如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    FILE* fileptr = fopen("test.dat","r");
    if (fileptr == NULL)
    {
        perror("Failed to open file: ");
        return EXIT_FAILURE;
    }

    char line[500];
    int array[20];
    const size_t max_size = sizeof array / sizeof *array;
    size_t i = 0;

    if (fgets(line,300,fileptr))
    {
        char *token = strtok(line," ");
        while (i < max_size && token != NULL)
        {
            array[i] = atoi(token);
            printf("%d\n", array[i]);
            ++i;
            token = strtok(NULL, " ");
        }

        // use array and i for whatever you needed
    }

    return EXIT_SUCCESS;
}

嗯,不清楚为什么300英寸
fgets(行,300,文件管理器)。我希望
fgets(line,sizeof line,fileptr)
@chux没有什么好的理由——我没有在这行代码的出处编写原始代码。我会修好的。谢谢。如果目标是获得“空间分隔字符”,那么
strtok()
就可以了。然而,由于该令牌会立即在
atoi()
中运行,因此使用
strtol()
而不是
strtok()/atoi()
更有意义,因为感谢您提供了详细的答案。第一次调用后将
NULL
传递到
strtok
的逻辑是什么?@sodiumnitrate请参阅。它将比我更好地解释它的用途,并为您提供一个很好的网站,供您在这个过程中为将来的查询添加书签。
1
2
3
4