C语言 为什么“%79[^\n]\n”会导致分段错误?

eanckbw9  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(107)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
        char line[80];
        FILE *in = fopen("spooky.csv", "r");
        FILE *file1 = fopen("ufos.csv", "w");
        FILE *file2 = fopen("disappearances.csv", "w");
        FILE *file3 = fopen("others.csv", "w");
        while (fscanf(in, "%79[^\n]\n", line) == 1) {
                if (strstr(line, "UFO"))
                        fprintf(file1, "%s\n", line);
                else if (strstr(line, "Disappearance"))
                        fprintf(file2, "%s\n", line);
                else
                        fprintf(file3, "%s\n", line);
        }
        fclose(file1);
        fclose(file2);
        fclose(file3);
        return 0;
}

此代码返回分段错误的运行时错误。

我在什么硬件上编译这个程序有关系吗?我正在使用Fedora 38(工作站)与英特尔酷睿i7(第7代)。

z9smfwbn

z9smfwbn1#

问题与fscanf无关:如错误消息所示,内部函数__vfscanf_internal的参数s具有值0x0,指示为FILE *参数传递的空指针。
您应该检查fopen是否无法打开文件,并使用有意义的错误消息报告此情况。
还要注意这些备注:

  • 关闭in
  • 您可以使用fgets()而不是fscanf()
  • fscanf将无法转换spooky.csv中的初始空行,如果它是一个实际的CSV文件,则不应发生这种情况。
  • 转换规范中的尾部\n将导致新行与下一行中的任何初始白色空格一起被沿着,这可能不是预期的。使用%79[^\n]%*[\n]来避免这种情况,但要消耗后续的空行。
  • CDE将静默地将长行分成79字节的块。为任意长的行修改代码并不容易,但是更大的缓冲区可能是一个不错的选择。
  • 如果第一行是包含字段名的标题行,则可能需要将第一行设置为特殊情况。

以下是修改后的版本:

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

FILE *fopen_check(const char *filename, const char *mode) {
    FILE *fp = fopen(filename, mode);
    if (fp == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
        exit(1);
    }
    return fp;
}

int main(void) {
    char line[80];

    FILE *in = fopen_check("spooky.csv", "r");
    FILE *file1 = fopen_check("ufos.csv", "w");
    FILE *file2 = fopen_check("disappearances.csv", "w");
    FILE *file3 = fopen_check("others.csv", "w");

    fscanf(in, "%*[\n]");  // skip initial empty lines

    while (fscanf(in, "%79[^\n]%*[\n]", line) == 1) {
        if (strstr(line, "UFO"))
            fprintf(file1, "%s\n", line);
        else
        if (strstr(line, "Disappearance"))
            fprintf(file2, "%s\n", line);
        else
            fprintf(file3, "%s\n", line);
    }
    fclose(in);
    fclose(file1);
    fclose(file2);
    fclose(file3);
    return 0;
}

相关问题