我有一个三行输入文件。 第一行是 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.)