【问题标题】:Punctuation causing errors when reading a string with whitespace using sscanf in C在 C 中使用 sscanf 读取带有空格的字符串时导致错误的标点符号
【发布时间】:2012-01-14 17:17:00
【问题描述】:

更新:用char string[sizeof buffer - 1]正确初始化字符串已经解决了崩溃问题,但我仍然很好奇有多个标点符号与它有什么关系!

我正在尝试从“一些文本”形式的文件中读取字符串。到目前为止,将sscanf\"%[^\"]\" 模式一起使用对我来说非常有效,但是一旦我开始在字符串中添加标点符号,程序就开始崩溃了。

似乎只有在使用多个标点符号时才会出现错误,无论它是什么标点符号或标记的位置。无论文件中带有标点符号的行的位置如何,它也会发生(即,即使最后一行没有标点符号,错误仍然会发生)。

不管怎样,下面是我目前的代码:

char* func(char* f_name);
    FILE* file = get_file(f_name,"r"); // a short function I wrote to get the
                                       // file pointer from the current
                                       // directory. The error is almost
                                       // certainly not here.
    if (file == 0) {
        print("Unable to load file\nExiting...");
        exit(-1);
    }

    char* pattern = "\"%[^\"]\"";
    int read_args = -1;
    char* string; //  string size is unknown until read
    char buffer[1200]; // i expect very long line of data in the file

    while ( fgets( buffer, sizeof(buffer), file ) != NULL ) {
        printf("found line: %s\n",buffer);
        read_args = sscanf(buffer, pattern, string);
        printf("num args: %d\n",read_args);
        printf("read value: %s\n", string);
    }

    fclose(file);
    return string;
}

以下是我尝试过的一些数据。在标记为“不成功”的地方,程序将编译、运行所有内容,并在退出前崩溃。

"test test test" // successful
"test, test test" // successful
"test test; test" // successful

"test, test, test" // unsuccessful
"test; test. test," // unsuccessful

如果此问题得到解决,我计划使用更复杂的模式,并且在发生此错误之前已成功读取模式 %d \"%[^\"]\" \"%[^\"]\" 的数据。提前感谢您的任何回答。

【问题讨论】:

    标签: c whitespace scanf punctuation


    【解决方案1】:

    您的代码调用了未定义的行为,因为您正在扫描到随机内存。

    string 变量从未初始化,因此sscanf() 写入的字符串的目的地是未定义的。

    你需要例如

    char string[sizeof buffer - 1];
    

    它并不总是崩溃的事实只是运气,代码一直在调用未定义的行为。根据您的示例,可能只是标点符号,扫描的文本更长,因此覆盖了更多的内存,一旦碰到足够重要的东西,最终就会触发崩溃。

    【讨论】:

    • 谢谢,这似乎已经解决了问题。我仍然很好奇标点符号与它有什么关系......
    • 一旦你调用未定义的行为,任何事情都可能发生,根据标准是可以的。函数可以行为或行为不端 - 这一切都很好,因为行为是未定义的。因此,不惜一切代价避免未定义的行为。而且,当你发现你在使用未定义的行为时,不要花太多时间担心它为什么会出现这种行为不端。但是,如果您真的很好奇,您可以执行“尝试在旧版本中打印 string”之类的操作,以查看它实际处理的内容,而不是您认为可能正在处理的内容。但这可能不值得付出努力。
    猜你喜欢
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 2020-07-09
    相关资源
    最近更新 更多