说我有一个未指定大小为双数字的numbers.txt
文件。
我需要将这些值动态地存储在double *note
指针中,以便以后使用。
我尝试了以下代码,但它给出了转储的核心:
FILE *ifile = fopen("numbers.txt", "r");
double *note;
int i = 1;
note = (double *) malloc( i * sizeof( double));
fscanf( ifile, "%lf", ¬e[0]);
while ( !feof( ifile)) {
i++;
note = (double *) realloc( note, i * sizeof( double));
fscanf( ifile, "%lf", ¬e[i]);
}
for (n=0; n < i; n++) {
printf( "%lfn", note[i]);
}
每次使用note[i]
时,您的代码都会访问超出其边界的数组。
在(错误的)while循环中,它总是比最后一个元素晚一个(例如,在第一次迭代中,i
变为2,分配了足够两个double
的空间,但您访问了第三个note[2]
)。
打印时,使用n
作为递增循环索引,但始终打印note[i]
而不是note[n]
。
检查所使用的所有库函数(如open
、new
、realloc
和scanf
)的返回值也是一种很好的做法。
这些问题的快速解决方案可以是以下片段。请注意,我(每次)都使用了与您相同的重新分配策略,但正如@Serge Ballesta所指出的,这可能效率低下。例如,看看@Jean-François Fabre回答中显示的备选方案。
#include <stdio.h>
#include <stdlib.h>
int main() {
double value,
*note = NULL,
*newptr = NULL;
int i,
size = 0;
char file_name[] = "numbers.txt";
FILE *ifile = fopen(file_name, "r");
if ( !ifile ) {
fprintf(stderr, "Error while opening file %s.n", file_name);
exit(EXIT_FAILURE);
}
while ( fscanf(ifile, "%lf", &value) == 1 ) {
size++;
newptr = realloc(note, size * sizeof(double));
if ( !newptr ) {
fprintf(stderr, "Error while reallocating memory.n");
free(note);
exit(EXIT_FAILURE);
}
note = newptr;
note[size - 1] = value;
}
for (i=0; i < size; i++) {
printf( "%lfn", note[i]);
}
free(note); // <-- don't leak memory!
fclose(ifile);
return EXIT_SUCCESS;
}
您的i从0传递到2,并且您的索引永久超出您的边界:您分配2个doubles,并写入索引2,这是第三个。另外,不要忘记关闭您的文件。最后的印刷品在应该使用n的地方使用了i。把通常的字母(i表示循环索引,n表示极限)混在一起是不好的,最后每个人都会感到困惑。
最好按照以下方式简化/分解代码,这样可以避免错误:
作为奖励,我添加了一个机制,可以避免每次重新分配,这在性能方面不是很好。
以下代码已经过测试,并且可以工作
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *ifile = fopen("numbers.txt", "r");
double v,*note=NULL;
int i = 0,n;
int alloc_step = 10;
int note_size = 0;
while ( !feof( ifile)) {
fscanf( ifile, "%lf", &v);
if ((i % alloc_step)==0)
{
note_size += alloc_step;
note = (double *) realloc( note, note_size * sizeof( double));
}
note[i++] = v;
}
for (n=0; n < i; n++) {
printf( "%lfn", note[n]);
}
fclose(ifile);
}