[英]fscanf on string causes segmentation fault
我有一个三行输入文件。 第一行是一个整数,第二行是带空格的整数,第三行是一个字符串。
我必须扫描它们而不是基于整数操作字符串。
我的问题是我可以扫描整数,但是扫描字符串会导致 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("%d\n", 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];
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.)
您的第一个问题出现在这里:
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[^\\t\\n]"
来定义你自己的分隔符,或者使用"%99c"
来定义一个固定长度的字符串。
GNU 编译器为所有这些情况提供修饰符"m"
(=分配内存)作为方便的非标准扩展:
char *string;
fscanf(in, "%ms", &string);
/* ... */
free(string);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.