在 C 中以某种格式从文件中读入会产生段错误
Reading in from file in a certain format in C produces seg fault
目前,我正在尝试从代表数独谜题解决方案的文件中读取数字。该文件应该被格式化为 9 个数字,中间没有空格,后跟一个换行符,在第 80 个数字之后结束。
在阅读时,我正在使用 fscanf,我可以让它处理一个有效的谜题,但不能处理一个无效格式的谜题;那些产生分段错误。我试图检查数组的长度,但由于在我声明 s 时将其设置为 10,因此无法捕获太短或太长的字符串。我会以错误的方式解决这个问题吗?我将 post 下面的代码。
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 个数字有一个换行符的拼图,以及一个全是数字但没有换行符的拼图。所有这些都会产生段错误。
您没有检查 puzzlefile
是否为 NULL
,您应该确保文件已打开,以防它不是 fopen()
returns NULL
,所以检查 fopen()
的 return 值是一件非常重要的事情。
您似乎没有检查是否 argv[1] != NULL
如果您忘记向程序传递参数会发生这种情况,后果将是程序出现故障并且您将没有任何线索为什么。
s
的大小太小,容易溢出,让fscanf()
知道目标字符串有多少space , 像这样
form = fscanf(puzzlefile, "%9s\n", s);
/* ^ 9 characters + '[=10=]' = 10 */
要防止读取到字符串末尾,请执行此操作
for (i = 0 ; s[i] != '[=11=]' ; ++i)
而不是
for (i=0; i<10; i++)
与内循环相同
如果你这样做就更好了
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')
你没有 post puzzle
的声明,如果你在它结束后写它也可能是问题,你应该非常小心在 c 中进行绑定检查,因为写过去缓冲区的末尾,没有定义的行为,在某些情况下,当你测试它时不会发生任何坏事,当然错误会静静地留在那里直到它爆发。
目前,我正在尝试从代表数独谜题解决方案的文件中读取数字。该文件应该被格式化为 9 个数字,中间没有空格,后跟一个换行符,在第 80 个数字之后结束。
在阅读时,我正在使用 fscanf,我可以让它处理一个有效的谜题,但不能处理一个无效格式的谜题;那些产生分段错误。我试图检查数组的长度,但由于在我声明 s 时将其设置为 10,因此无法捕获太短或太长的字符串。我会以错误的方式解决这个问题吗?我将 post 下面的代码。
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 个数字有一个换行符的拼图,以及一个全是数字但没有换行符的拼图。所有这些都会产生段错误。
您没有检查
puzzlefile
是否为NULL
,您应该确保文件已打开,以防它不是fopen()
returnsNULL
,所以检查fopen()
的 return 值是一件非常重要的事情。您似乎没有检查是否
argv[1] != NULL
如果您忘记向程序传递参数会发生这种情况,后果将是程序出现故障并且您将没有任何线索为什么。s
的大小太小,容易溢出,让fscanf()
知道目标字符串有多少space , 像这样form = fscanf(puzzlefile, "%9s\n", s); /* ^ 9 characters + '[=10=]' = 10 */
要防止读取到字符串末尾,请执行此操作
for (i = 0 ; s[i] != '[=11=]' ; ++i)
而不是
for (i=0; i<10; i++)
与内循环相同
如果你这样做就更好了
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')
你没有 post puzzle
的声明,如果你在它结束后写它也可能是问题,你应该非常小心在 c 中进行绑定检查,因为写过去缓冲区的末尾,没有定义的行为,在某些情况下,当你测试它时不会发生任何坏事,当然错误会静静地留在那里直到它爆发。