Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 当从文件读取并使用strtok时,While循环只打印每行的第一个字_C_Readfile_Fgets_Strtok - Fatal编程技术网

C 当从文件读取并使用strtok时,While循环只打印每行的第一个字

C 当从文件读取并使用strtok时,While循环只打印每行的第一个字,c,readfile,fgets,strtok,C,Readfile,Fgets,Strtok,我是一名Java程序员,在C语言中测试我的运气。我试图逐行读取一个文件,然后计算每个单词。到目前为止,我还没有幸运地把每一行分成几个字。我能够看到每一行并正确地循环文件,但我的输出只是每一行的第一个字。 我做错了什么 char printword[1024]= ""; void print() { printf("%s", printword); } main() { FILE* f; errno_t err; err = fopen_s(&f,

我是一名Java程序员,在C语言中测试我的运气。我试图逐行读取一个文件,然后计算每个单词。到目前为止,我还没有幸运地把每一行分成几个字。我能够看到每一行并正确地循环文件,但我的输出只是每一行的第一个字。 我做错了什么

char printword[1024]= "";

void print() {
    printf("%s", printword);    
}
main()
{
    FILE* f;
    errno_t err;
    err = fopen_s(&f, FILE_NAME, "r");
    if (&f == NULL) {
    exit(EXIT_FAILURE);
    }
    char line[1024];
    while (fgets(line, 1024, f) != NULL) {
        char * word;
        char *context = " ";
        word = strtok(line, " ");
        while (word != NULL) {
        strcpy(printword, strcat(word," "));
        print();
        word = strtok(NULL, " ");
        }
        printf("\n", NULL);
    }
    //}
    fclose(f);
    printf("Press any key to continue");
    getchar();
    exit(0);
}

我认为BlueStrat是对的。尝试先将word复制到printword,然后将cat复制到printword

strcpy(printword, word);
strcat(printword, " ");

@BlueStrat的评论似乎已经将矛头指向了这个问题

在使用strtok时,您必须始终记住它不分配任何内存,而是返回指向原始字符串的指针,插入终止符代替分隔符,并维护指向下一个标记开始的内部静态指针。那么,假设输入文件的第一行包含

one two three
fgets会将其读入线阵列:

第一个strtok调用返回指向偏移量0处字符的指针,将偏移量3处的字符设置为终止符,并将其内部状态变量设置为指向偏移量4处的字符:

       0         1
offset 012 3456789012 3
line   one\0two three\0
       ^    ^
       |    |
       |    +-- (next)
       +------- word 
然后在单词的末尾加上一个字符,生成:

       0         1
offset 0123 456789012 3
line   one \0wo three\0
       ^    ^
       |    |
       |    +-- (next)
       +------- word 
现在研究一下。您不仅破坏了第一个标记后面的数据,而且还以内部状态指针指向字符串终止符的方式进行了破坏。然后,当您下次调用strtok时,该函数会看到它在字符串的末尾是一个字符串,并返回NULL以表示不再有令牌


与其操纵令牌(这很危险),不如将其内容连接到打印字缓冲区,然后将额外的空间连接到该缓冲区。

我认为最内部循环中的strcat调用可能会损害操作。strtok必须小心处理,因为它会在每次连续调用期间修改要标记的字符串。我打赌它不希望在调用之间修改源缓冲区字。您打算如何处理strcat函数调用?printf\n,NULL?如果你只是想让tom在单词后面加一个空格,那就别再考虑那些抄袭和拼凑了。C的字符串与其他语言中的字符串不同;与他们合作有些棘手。如果您想要一个空格,请将其置于printf的格式字符串中。在使用printf%s,word;触发strtok行之前,请重新安装打印函数和循环中的所有内容;。
       0         1
offset 0123 456789012 3
line   one \0wo three\0
       ^    ^
       |    |
       |    +-- (next)
       +------- word