与字符串终止相关的strtok分段故障

时间:2016-03-13 23:37:36

标签: c

我正在编写一个程序,逐行读取文本文件并删除每行中的特定单词,然后将新行打印到另一个文本文件。

我一直在Zeus中遇到分段错误,但我的代码在Visual Studio中运行得很好。我需要在Zeus上运行这个程序,所以我必须找出问题所在。我发现我的一行代码导致了这个问题。请在下面查看。

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

int main()
{
    FILE *myfile;
    FILE *des;              //store edited text file
    char buf[101];          //store line by line
    int pos;                //the position of the deleted word
    char deleted[100] = ""; //store deleted words
    char input[100] = "";   //take input file name
    char output[100] = "";  //take output file name

    printf("Enter the name of the input file: ");
//  scanf(" %s", &input);
    printf("Enter the name of the output file: ");
    //scanf(" %s", &output);

    myfile = fopen("Lab6_bad.txt", "r"); //read file
    des = fopen("Lab6_good.txt", "w");   //open a file for writing

                                //check if the text file exists
    if (myfile == NULL)
    {
        printf("The file does not exist.\n");
        exit(0);
    }

    //read text file line by line using fgets()
    while (fgets(buf, sizeof(buf), myfile) != NULL)
    {
        char newline[101] = ""; //store the new line

        printf("%s", buf);

buf [sizeof(buf)] ='\ 0'; //终止

                                 //prevent reading the line twice
        if (buf[0] == '\n')
        {
            break;
        }

        printf("%s", buf);
        printf("Enter position of word to delete (Start counting at 0). Enter -1 to skip deletion: ");
        scanf(" %d", &pos);
        printf("\n");

        //not edit a line
        if (pos == -1)
        {
            fprintf(des, "%s\n", buf);
            continue;
        }

        char *token;
        int count = 0; //record the current token's position

token = strtok(buf,“”); //获取第一个令牌。问题发生在这里!看起来Zeus不会自动添加'\ 0',所以我在上面添加一行(粗线),但它仍然不起作用

        while (token != NULL)
        {
            if (count == pos)
            {
                strcat(deleted, token);
                strcat(deleted, " ");
            }
            else
            {
                strcat(newline, token);
                strcat(newline, " ");
            }
            token = strtok(NULL, " ");
            count++;
        }
        fprintf(des, "%s\n", newline);
    }

    fclose(myfile);
    fclose(des);
    printf("%s", deleted);
}

1 个答案:

答案 0 :(得分:0)

fgets()将null终止存储行读取的缓冲区。

您的陈述:buf[sizeof(buf)] = '\0';实际上会调用未定义的行为!你将NUL字符存储在数组末尾之外。

相反,您不会测试scanf(" %d", &pos);的返回值。如果标准输入未解析为数字,则会返回0或可能EOF并且pos未初始化,从而导致行为不正确。

更重要的是:您将所有已删除的单词连接到该数组deleted,但从不检查缓冲区溢出。如果删除太多单词,缓冲区最终会变得太小,并且将调用未定义的行为。