C - 字符串上的 FSANF 导致分段错误



我有一个三行输入文件。 第一行是 int,第二行是带空格的整数,第三行是字符串。

我必须扫描它们,而不是根据整数操作字符串。

我的问题是我可以扫描整数,但扫描字符串会导致 fclose 的分段错误。

我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h> 
int main()
{
FILE* in = fopen("be.txt", "r");
FILE* out = fopen("ki.txt", "w");
if(in==NULL){
printf("Error opening in!n");
return -1;
}
if(out==NULL){
printf("Error opening out!n");
return -1;
}
int brknglength, i;
fscanf(in, "%d", &brknglength);
printf("%dn", brknglength);
int* seed[brknglength];
seed[brknglength] = malloc(sizeof(int[brknglength]));
for(i = 0; i < brknglength; i++){
if (fscanf(in, "%d", &seed[i]) != 1) {
printf("%d", i);
}
printf("%d.: %d n", i, seed[i]);
}
char string;
fscanf(in, "%s", &string);

free(seed[brknglength]);
fclose(in);
fclose(out);
return 0;
}

分段错误的原因是什么?

您的第一个问题出现在这里:

int* seed[brknglength];

这定义了堆栈上的int指针数组。

seed[brknglength] = malloc(sizeof(int[brknglength]));

这将初始化数组后面的元素并覆盖堆栈。 要修复此问题,请使用以下任一方法:

int seed[brknglength]; /* use without free(seed) */

或:

int *seed = malloc(sizeof(int[brknglength]));
/* ... */
free(seed);

后者也适用于不支持可变长度数组的编译器。


第二个问题是将字符串读入单个char变量,该变量也会覆盖堆栈。尝试类似操作:

char string[100];
fscanf(in, "%99s", &string);

请注意,"%s"止步于空格。使用"%99[^tn]"之类的内容来定义自己的分隔符,或者使用"%99c"来定义固定长度的字符串。

GNU 编译器提供了修饰符"m"(=分配内存( 作为所有这些情况的方便的非标准扩展:

char *string;
fscanf(in, "%ms", &string);
/* ... */
free(string);

int* seed[brknglength];
seed[brknglength] = malloc(sizeof(int[brknglength]));

看起来您在这里尝试做的是将seed设置为指向int数组的指针并为其分配空间。但是,这是错误的语法。因为[ ]的优先级高于*,所以int* seed[brknglength];定义了一个指向int的指针数组。此外,对象的名称是seed,而不是seed[brknglength],因此您将使用seed = …而不是seed[brknglength] = …为其赋值。

要创建指向数组的指针并为其分配空间,请使用:

int (*seed)[brknglength];
seed = malloc(sizeof *seed);

这些可以组合(这并不违反上面关于使用seed =进行赋值的说明 - 初始化有一个特殊的语法(:

int (*seed)[brknglength] = malloc(sizeof *seed);

但是,您可能不希望这样。如果size是指向数组的指针,则必须在要引用数组的任何位置使用*seed。所以fscanf(in, "%d", &seed[i])必须fscanf(in, "%d", &(*seed)[i]).

不要seed成为指向数组的指针,而只需将其设置为指向int的指针,并为任意数量的int分配空间:

int *seed = malloc(brknglength * sizeof *seed);

然后,您可以将seed[i]用于数组的元素i,而不必使用(*seed)[i]

char string;

这将string定义为单个char。但是fscanf(in, "%s", &string);读取的字符数与输入的字符数一样多,直到出现空格字符。因此,您需要fscanf传递指向许多char中的第一个的指针。您可以将string声明为数组:

char string[100];

或指向已分配空间的指针:

char *string = malloc(100 * sizeof *string);

然后你可以使用fscanf(in, "%s", string);.请注意,您不想传递&string.这是数组或指针的地址,具体取决于您定义string的方式。您希望传递第一个字符的地址,即&string[0],或者等效地传递string。(如果string是一个数组,则在此表达式中它会自动转换为指向其第一个元素的指针,因此它等效于&string[0]

请注意,fscanf将读取输入包含的字符数,直到出现空格字符。这可能会超过您为string提供的任何大小。因此,您需要确保输入没有太多字符或告诉fscanf限制其读取量,您可以使用:

fscanf(in, "%99s", string);

或:

int n = 99;
fscanf(in, "%*s", n, string);

请注意,应告知fscanf最多读取比string中的空格少一个字符,因为它需要添加一个终止空字符。

要释放这些对象,请使用:

free(seed);
free(string); // (If defined as a pointer, not an array.)

相关内容

  • 没有找到相关文章

最新更新