二维动态数组(c中的realloc)
我试图从输入加载两个双数字动态地由每个用户输入重新定位的二维数组。
#include #include int main(int argc, char** argv) { int count; double number1, number2, **numbers; while (scanf("%lf,%lf", number1, number2) != EOF) { count++; numbers = (double**) realloc(numbers, count * 2 * sizeof (double)); if (numbers == NULL) { exit(1); } numbers[count][0] = number1; numbers[count][1] = number2; } return 0; }
每次我尝试将值保存到数组(可能是内存问题)时程序失败。 它编译没有问题。
任何人都可以告诉我如何正确地重新分配新arrays?
谢谢你的帮助。
你有几个问题。
- 你没有初始化
numbers = 0;
或count = 0
因此在开始第一次realloc()
调用之前,变量中有一个不确定的值。 那是个坏消息。 - 更主要的问题是您误解了模拟2Darrays所需的内存分配。
- 您的
scanf()
调用不正确; 你没有传递指针。
ASCII艺术
+---------+ | numbers | +---------+ | v +------------+ +---------------+---------------+ | numbers[0] |---->| numbers[0][0] | numbers[0][1] | +------------+ +---------------+---------------+ | numbers[1] |---->| numbers[1][0] | numbers[1][1] | +------------+ +---------------+---------------+ | numbers[2] |---->| numbers[2][0] | numbers[2][1] | +------------+ +---------------+---------------+
实际上你需要存储在numbers
的指针,指针数组和double
数组。 目前,您没有为指针数组分配空间,这是您遇到麻烦的原因。 双精度数组可以是连续的或非连续的(也就是说,每行可以单独分配,但在一行内,分配当然必须是连续的)。
工作代码:
#include #include int main(void) { int count = 0; double number1, number2; double **numbers = 0; while (scanf("%lf,%lf", &number1, &number2) != EOF) { numbers = (double **) realloc(numbers, (count + 1) * sizeof(*numbers)); if (numbers == NULL) exit(1); numbers[count] = (double *)malloc(2 * sizeof(double)); if (numbers[count] == 0) exit(1); numbers[count][0] = number1; numbers[count][1] = number2; count++; } for (int i = 0; i < count; i++) printf("(%8.2f, %8.2f)\n", numbers[i][0], numbers[i][1]); for (int i = 0; i < count; i++) free(numbers[i]); free(numbers); return 0; }
注意:这仍然不是很好的代码。 特别是,每次使用的逐个增量机制都很糟糕。 meme pointer = realloc(pointer, newsize);
也很糟糕; 如果分配失败,则无法释放先前分配的内存。 你应该使用newptr = realloc(pointer, newsize);
然后在pointer = newptr;
之前进行内存检查pointer = newptr;
。
输入文件:
12.34,23.45 34.56,45.67 56.78,67.89 78.90,89.01
输出数据:
( 12.34, 23.45) ( 34.56, 45.67) ( 56.78, 67.89) ( 78.90, 89.01)
没有正式在valgrind
下运行,但我相信它会没问题。
在不知道我必须存储多少输入的情况下,将输入保存到arrays中的最佳解决方案是什么? 或者,与Java或PHP相比,它可能只是复杂的C?
除了'一个一个'部分,这是关于它必须在C中工作的方式,至少如果你想使用两个索引索引结果: numbers[i][0]
等。
另一种方法是按照您的方式分配空间(除非“递增1”除外),然后使用表达式索引数组: double *numbers = ...;
在你的情况下, numbers[i*2+0]
和numbers[i*2+1]
,但在具有ncols
列的数组的更一般情况下,使用numbers[i*ncols + j]
访问第i
行和第j
列。 您将numbers[i][j]
的符号方便与内存分配的复杂性增加进行交换。 (另请注意,对于此机制,数组的类型是double *numbers;
而不是double **numbers;
因为它在您的代码中。)
避免“逐一增加”的替代方案通常使用每次分配的空间量的两倍。 您可以决定使用malloc()
进行初始分配,然后使用realloc()
来增加空间,或者您可以使用realloc()
知道如果传入的指针是NULL,那么它将执行相当于malloc()
。 (事实上, realloc()
是一个函数中的完整内存分配管理包;如果你用大小0调用它,它将free()
内存而不是分配。)人们争论是否(ab)使用realloc()
这样是不是一个好主意。 由于它是由C89 / C90及更高版本的C标准保证的,它足够安全,并且它会切断一个函数调用,所以我倾向于只使用realloc()
:
#include #include static void free_numbers(double **array, size_t size) { for (size_t i = 0; i < size; i++) free(array[i]); free(array); } int main(void) { int count = 0; double number1, number2; double **numbers = 0; double maxnum = 0; while (scanf("%lf,%lf", &number1, &number2) != EOF) { if (count == maxnum) { size_t newnum = (maxnum + 2) * 2; /* 4, 12, 28, 60, ... */ double **newptr = (double **)realloc(numbers, newnum * sizeof(*numbers)); if (newptr == NULL) { free_numbers(numbers, count); exit(1); } maxnum = newnum; numbers = newptr; } numbers[count] = (double *)malloc(2 * sizeof(double)); if (numbers[count] == 0) { free_numbers(numbers, count); exit(1); } numbers[count][0] = number1; numbers[count][1] = number2; count++; } for (int i = 0; i < count; i++) printf("(%8.2f, %8.2f)\n", numbers[i][0], numbers[i][1]); free_numbers(numbers, count); return 0; }
这个代码用valgrind
检查没有问题; 分配的所有代码都被释放。 注意使用函数free_numbers()
来释放错误路径中的内存。 当它在像这里的main()
函数中运行时并不重要,但是当工作在可能被许多程序使用的函数中完成时,这绝对是重要的。
你过早地增加计数变量。 它将索引到数组中的第一个值是1,但是数组索引从零开始。
在分配新值并将计数初始化为零后得到count ++应该有效。 但是,阅读其他用户发布的评论,你真的想要一个更好的方法来解决这个问题。
#include #include void agregar_int(int **,int); void agregar_char(char **,int); char **tz=NULL; int **tr=0; int a; int main(void){ a=2; for (a=1;a<100;a++) { agregar_int(tr,a); } for (a=1;a<100;a++) { agregar_char(tz,a); } } agregar_int (int **tr,int a) { printf ("%d----------------------------------------------\n",a); tr = (int**) realloc (tr, (a+1) * sizeof(*tr)); tr[a] = (int *) malloc (5 * sizeof(int)); tr[a][0]=a; tr[a][1]=a;tr[a][2]=a;tr[a][3]=a;tr[a][4]=a; printf("%d \t %d \t %d \t %d \t %d \n",tr[a][0],tr[a][1],tr[a][2],tr[a][3],tr[a][4]); } agregar_char (char **tz,int a) { printf ("%d----------------------------------------------\n",a); tz = (char**) realloc (tz, (a+1) * sizeof(*tz)); tz[a] = (char *) malloc (7 * sizeof(char)); tz[a][0]='E'; tz[a][1]='s';tz[a][2]='t';tz[a][3]='e';tz[a][4]='b',tz[a][5]='a',tz[a][6]='n'; printf("%c%c%c%c%c%c%c \n",tz[a][0],tz[a][1],tz[a][2],tz[a][3],tz[a][4],tz[a][5],tz[a][6]); }