【问题标题】:Reading in from file in a certain format in C produces seg fault在 C 中以某种格式从文件中读取会产生段错误
【发布时间】:2015-04-21 19:33:46
【问题描述】:

目前,我正在尝试从代表数独谜题解决方案的文件中读取数字。该文件应该被格式化为 9 个数字,中间没有空格,后跟一个换行符,在第 80 个数字之后结束。

在阅读时,我正在使用 fscanf,我可以让它与一个有效的谜题一起工作,但不能与一个不是有效格式的谜题一起工作;那些会产生分段错误。我试图检查数组的长度,但是由于在我声明 s 时它设置为 10,所以它不会捕获太短或太长的字符串。我会以错误的方式解决这个问题吗?我将在下面发布代码。

FILE* puzzlefile;
char s[10];
int i=0, j=0, skip;
int form;

//opens the file so we can access the puzzle
puzzlefile = fopen(argv[1], "r");

for (i=0; i<9; i++){
    form = fscanf(puzzlefile, "%s\n",s);
    for (j=0; j<10; j++){
        if (form == 0){
            printf("Invalid format on input. Bad newline.\n");
            return 1;
        }
        if(j<9){
            if(s[j] == '1' || s[j] == '2' || s[j] == '3' || s[j] == '4' || s[j] == '5' || s[j] == '6' || s[j] == '7' || s[j] == '8' || s[j] == '9'){
                puzzle[i][j] = (int)(s[j]-'0');
            }
            else{
                printf("Invalid format on input.\n");
                return 1;
            }
        }
    }
}

我是不是走错了路?如果是这样,我只是在滥用 fscanf() 吗?或者我应该使用其他类型的输入函数?我正在测试的文件包括一些遵循格式但使用字母而不是数字的文件,一个在第一行带有额外数字的拼图,一个每 5 个数字有换行符的拼图,以及一个全是数字而没有换行符的拼图。所有这些都会产生段错误。

【问题讨论】:

  • 对于需要验证的输入,您可以手动进行,例如coliru.stacked-crooked.com/a/e00103b3fa514696
  • @sp2danny 不幸的是,这个特定程序的要求是它必须从这种特定格式的文件中读取,否则我会考虑这一点。不过感谢您的建议!

标签: c segmentation-fault


【解决方案1】:
  1. NULL不检查puzzlefile,要确保文件已经打开,万一不是fopen()返回NULL,所以检查@987654325的返回值@ 是一件非常重要的事情。

  2. 您似乎没有检查argv[1] != NULL,如果您忘记将参数传递给程序会发生这种情况,后果将是程序出现故障,您将不知道原因。

  3. s的大小太小,容易溢出,让fscanf()知道目标字符串还有多少空间,像这样

    form = fscanf(puzzlefile, "%9s\n", s);
    /*                          ^ 9 characters + '\0' = 10 */
    
  4. 为了防止读取超出字符串的末尾,请执行此操作

    for (i = 0 ; s[i] != '\0' ; ++i)
    

    而不是

    for (i=0; i<10; i++)
    

    和内循环一样。

  5. 如果你这样做会更好

    if ((s[j] > '0') && (s[j] < 1 + '9'))
    

    而不是

    if(s[j] == '1' || s[j] == '2' || s[j] == '3' || s[j] == '4' || s[j] == '5' || s[j] == '6' || s[j] == '7' || s[j] == '8' || s[j] == '9')
    

你没有发布puzzle的声明,如果你在它结束后写,也可能是问题,你应该非常小心c中的绑定检查,因为写超过缓冲区的末尾,不会有一个明确的行为,在某些情况下,当你测试它时不会发生任何不好的事情,当然,这个 bug 会一直静静地呆在那里,直到它爆炸。

【讨论】:

  • 感谢有关 %9s 的建议。我不知道你能做到这一点!但是,在听从您的建议后,我仍然会在无效拼图上遇到段错误。
  • @RobertCrawford 请发布整个main(),您的代码缺少内容。
  • 为了解决您的编辑问题,“puzzle”是一个全局变量,声明为“int puzzle[9][9];”我没有包含其余主要功能的唯一原因是因为该项目是线程练习。这几乎是 main 函数中的所有内容。只要数据被正确读入,那么剩下的就可以了;它已经过测试。代码的唯一问题是格式处理不正确,我打算在阅读时这样做。
  • 不要使用全局变量,特别是在线程程序中,全局变量很重要,是的,有时它们可​​以是一个简单的解决方案,但可能会导致很多问题。而且你从不检查i &lt; 9,因此你确实溢出了puzzle。此外,检查argc 以防止访问argv 中不可用的参数。
  • 好的,所以今天我学到了宝贵的一课,即不要在您希望使用命令行读取的文件名中包含空格。但是,我的程序正在按照您的建议工作,但在一种情况下除外:如果所有数字都在一行中且没有换行符。知道为什么会这样吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 2017-12-12
相关资源
最近更新 更多