英文:
Resizing a 2D array of structures
问题
以下是您要翻译的代码部分:
我正在尝试编写一个名为`resizeArray`的函数,用于调整我的自定义类型`cell`的2D数组`array`的大小,如果无法分配足够的内存,则返回错误消息。但是,我的代码不起作用,但奇怪的是,我的编译器没有抛出警告。我怀疑`resizeArray`的返回指针类型不匹配。请告诉我我做错了什么?
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int variable_1;
int variable_2;
char character;
} cell;
unsigned long max(unsigned long a, unsigned long b)
{
if (a >= b)
return a;
else
return b;
}
void initialiseArray(unsigned long rows, unsigned long columns,
cell array[rows][columns])
{
for (unsigned long i = 0; i < rows; i = i + 1)
for (unsigned long j = 0; j < columns; j = j + 1)
{
array[i][j].variable_1 = 0;
array[i][j].variable_2 = 0;
array[i][j].character = ' ';
}
}
cell *resizeArray(unsigned long rows, unsigned long columns,
unsigned long *array_rows, unsigned long *array_columns,
cell array[*array_rows][*array_columns])
{
if (rows > *array_rows || columns > *array_columns)
{
unsigned long new_array_rows = max(rows, *array_rows);
unsigned long new_array_columns = max(columns, *array_columns);
cell (*new_array)[new_array_rows][new_array_columns] = malloc(sizeof *new_array);
if (new_array == NULL)
{
printf("Error in \"resize\": Memory could not be allocated.\n");
return NULL;
}
else
free(array);
*array_rows = new_array_rows;
*array_columns = new_array_columns;
return new_array;
}
}
int main(void)
{
unsigned long array_rows = 10;
unsigned long array_columns = 15;
cell (*array)[array_rows][array_columns] = malloc(sizeof *array);
if (array == NULL)
{
printf("Error in \"main\": Memory could not be allocated.\n");
return 3;
}
cell *new_array = resizeArray(15, 15, &array_rows, &array_columns, *array);
if (new_array == NULL)
printf("Memory error. We stop the program.\n");
return -1;
array = new_array;
initialiseArray(array_rows, array_columns, *array);
return 0;
}
请注意,代码中存在一些问题,您可能需要进一步检查和修复以确保其正确运行。
英文:
I am trying to write a function resizeArray
that resizes a 2D array array
of my custom type cell
and if not enough memory could be allocated returns an error message. However, my code does not work, but my compiler, strangely, does not throw a warning. It suspect that my returned pointer type of resizeArray
is not fitting. Could you please tell me what I am doing wrong?
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int variable_1;
int variable_2;
char character;
} cell;
unsigned long max(unsigned long a, unsigned long b)
{
if (a >= b)
return a;
else
return b;
}
void initialiseArray(unsigned long rows, unsigned long columns,
cell array[rows][columns])
{
for (unsigned long i = 0; i < rows; i = i + 1)
for (unsigned long j = 0; j < columns; j = j + 1)
{
array[i][j].variable_1 = 0;
array[i][j].variable_2 = 0;
array[i][j].character = ' ';
}
}
cell *resizeArray(unsigned long rows, unsigned long columns,
unsigned long *array_rows, unsigned long *array_columns,
cell array[*array_rows][*array_columns])
{
if (rows > *array_rows || columns > *array_columns)
{
unsigned long new_array_rows = max(rows, *array_rows);
unsigned long new_array_columns = max(columns, *array_columns);
cell (*new_array)[new_array_rows][new_array_columns] = malloc(sizeof *new_array);
if (new_array == NULL)
{
printf("Error in ""resize"": Memory could not be allocated.\n");
return NULL;
}
else
free(array);
*array_rows = new_array_rows;
*array_columns = new_array_columns;
return new_array;
}
}
int main(void)
{
unsigned long array_rows = 10;
unsigned long array_columns = 15;
cell (*array)[array_rows][array_columns] = malloc(sizeof *array);
if (array == NULL)
{
printf("Error in ""main"": Memory could not be allocated.\n");
return 3;
}
cell *new_array = resizeArray(15, 15, &array_rows, &array_columns, *array);
if (new_array == NULL)
printf("Memory error. We stop the program.\n");
return -1;
array = new_array;
initialiseArray(array_rows, array_columns, *array);
return 0;
}
答案1
得分: 3
以下是翻译好的部分:
在你的代码中存在多个问题:
- 在
main
函数中,在分配失败后缺少大括号,导致后续代码被忽略。请将其更改为:
if (new_array == NULL) {
printf("内存错误。我们停止程序。\n");
return 1;
}
-
函数
resizeArray
在数组不需要重新分配的情况下没有返回任何内容。你应该在函数末尾添加return &array[0][0];
。 -
在相同的函数中,
return new_array;
存在类型不匹配。你可以使用return (void *)new_array;
来消除警告,或者返回适当的类型return &(*new_array)[0][0];
。 -
在
main
函数中,存储array = new_array;
时存在相同的问题。你可以简单地写成array = (void *)new_array;
,因为没有一种简单的方法来表示适当的强制转换。
但请注意,你的方法仍然令人困惑且容易出错:最后一个调用initialiseArray(array_rows, array_columns, *array)
将*array
作为array_columns
列和array_rows
行的数组传递,这会导致它衰减为指向array_columns
个整数数组的指针,但这在技术上是类型不匹配的,编译器不会捕捉到这个问题:array
的类型仍然引用array_columns
和array_rows
的原始值,而不是当前修改后的值,因此在main
中使用*array
来引用重新分配数组的单元格将会失败。
以下是修改后的版本,显示了该问题:
// 此处为示例代码
你可以考虑使用2D间接寻址来操作动态大小的矩阵。以下是使用单个矩阵的单个分配的修改版本:
// 此处为示例代码
输出:
// 此处为示例输出
希望这能帮助你理解代码中的问题。如果你需要进一步的帮助,请随时提问。
英文:
There are multiple problems in your code:
-
in function
main
there are missing braces after the test for allocation failure, causing the rest of the code to be ignored. Write this:if (new_array == NULL) { printf("Memory error. We stop the program.\n"); return 1; }
-
function
resizeArray
does not return anything in case the array does not need to be reallocated. You should addreturn &array[0][0];
at the end of the function. -
in the same function,
return new_array;
is a type mismatch. You could silence the warning withreturn (void *)new_array;
or return the appropriate typereturn &(*new_array)[0][0];
-
in
main
, the same problem when storingarray = new_array;
. You can simply writearray = (void *)new_array;
as there is no easy way to express the appropriate cast.
Note however that your approach is confusing and error prone: the last call initialiseArray(array_rows, array_columns, *array)
passes *array
as an array of array_columns
columns and array_rows
rows, which decays to a pointer to arrays of array_columns
ints, but this is technically a type mismatch that is not caught by the compiler: the type of array
still refers to the original values of array_columns
and array_rows
, not the current modified ones, so using *array
inside main
to refer to the cells of the reallocated array will fail.
Here is a modified version displaying the problem:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int variable_1;
int variable_2;
char character;
} cell;
unsigned long max(unsigned long a, unsigned long b)
{
if (a >= b)
return a;
else
return b;
}
void initialiseArray(unsigned long rows, unsigned long columns,
cell array[rows][columns])
{
for (unsigned long i = 0; i < rows; i = i + 1)
for (unsigned long j = 0; j < columns; j = j + 1)
{
array[i][j].variable_1 = i;
array[i][j].variable_2 = j;
array[i][j].character = ' ';
}
}
cell *resizeArray(unsigned long rows, unsigned long columns,
unsigned long *array_rows, unsigned long *array_columns,
cell array[*array_rows][*array_columns])
{
if (rows > *array_rows || columns > *array_columns)
{
unsigned long new_array_rows = max(rows, *array_rows);
unsigned long new_array_columns = max(columns, *array_columns);
cell (*new_array)[new_array_rows][new_array_columns] = malloc(sizeof *new_array);
if (new_array == NULL)
{
printf("Error in ""resize"": Memory could not be allocated.\n");
return NULL;
}
else
{
free(array);
}
*array_rows = new_array_rows;
*array_columns = new_array_columns;
return &(*new_array)[0][0];
}
return &array[0][0];
}
void displayArray(unsigned long rows, unsigned long columns, cell array[rows][columns])
{
for (unsigned long row = 0; row < rows; row++) {
for (unsigned long col = 0; col < columns; col++) {
cell c = array[row][col];
printf(" {%d,%d,'%c'},", c.variable_1, c.variable_2, c.character);
}
printf("\n");
}
}
int main(void)
{
unsigned long array_rows = 3;
unsigned long array_columns = 3;
cell (*array)[array_rows][array_columns] = malloc(sizeof *array);
if (array == NULL)
{
printf("Error in ""main"": Memory could not be allocated.\n");
return 3;
}
cell *new_array = resizeArray(4, 5, &array_rows, &array_columns, *array);
if (new_array == NULL) {
printf("Memory error. We stop the program.\n");
return -1;
}
array = (void *)new_array;
initialiseArray(array_rows, array_columns, *array);
printf("Using displayArray:\n");
displayArray(array_rows, array_columns, *array);
printf("Same code from main:\n");
for (unsigned long row = 0; row < array_rows; row++) {
for (unsigned long col = 0; col < array_columns; col++) {
cell c = (*array)[row][col];
printf(" {%d,%d,'%c'},", c.variable_1, c.variable_2, c.character);
}
printf("\n");
}
return 0;
}
Output:
Using displayArray:
{0,0,' '}, {0,1,' '}, {0,2,' '}, {0,3,' '}, {0,4,' '},
{1,0,' '}, {1,1,' '}, {1,2,' '}, {1,3,' '}, {1,4,' '},
{2,0,' '}, {2,1,' '}, {2,2,' '}, {2,3,' '}, {2,4,' '},
{3,0,' '}, {3,1,' '}, {3,2,' '}, {3,3,' '}, {3,4,' '},
Same code from main:
{0,0,' '}, {0,1,' '}, {0,2,' '}, {0,3,' '}, {0,4,' '},
{0,3,' '}, {0,4,' '}, {1,0,' '}, {1,1,' '}, {1,2,' '},
{1,1,' '}, {1,2,' '}, {1,3,' '}, {1,4,' '}, {2,0,' '},
{1,4,' '}, {2,0,' '}, {2,1,' '}, {2,2,' '}, {2,3,' '},
You might consider using 2D indirect addressing to manipulate dynamically sized matrixes. Here is a modified version using a single allocation per matrix:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int variable_1;
int variable_2;
char character;
} cell;
size_t max(size_t a, size_t b)
{
if (a >= b)
return a;
else
return b;
}
cell **allocateArray(size_t rows, size_t cols)
{
/* allocate combined packed 2D matrix with an array of column pointers */
size_t head_size = (sizeof(cell **) * rows + sizeof(cell) - 1) / sizeof(cell);
cell **res = calloc(head_size + rows * cols, sizeof(cell));
if (res != NULL) {
for (size_t i = 0; i < rows; i++)
res[i] = (cell *)res + head_size + i * cols;
}
return res;
}
void initialiseArray(size_t rows, size_t columns, cell **array)
{
for (size_t i = 0; i < rows; i = i + 1) {
for (size_t j = 0; j < columns; j = j + 1) {
array[i][j].variable_1 = i;
array[i][j].variable_2 = j;
array[i][j].character = ' ';
}
}
}
cell **resizeArray(size_t rows, size_t columns,
size_t *array_rows, size_t *array_columns, cell ***arrayp)
{
cell **array = *arrayp;
if (rows > *array_rows || columns > *array_columns) {
size_t new_array_rows = max(rows, *array_rows);
size_t new_array_columns = max(columns, *array_columns);
cell **new_array = allocateArray(new_array_rows, new_array_columns);
if (new_array == NULL) {
printf("Error in ""resize"": Memory could not be allocated.\n");
return NULL;
} else {
for (size_t i = 0; i < *array_rows; i++) {
for (size_t j = 0; j < *array_columns; j++) {
new_array[i][j] = array[i][j];
}
}
free(array);
}
*array_rows = new_array_rows;
*array_columns = new_array_columns;
return *arrayp = new_array;
}
return array;
}
void displayArray(size_t rows, size_t columns, cell **array)
{
for (size_t row = 0; row < rows; row++) {
for (size_t col = 0; col < columns; col++) {
cell c = array[row][col];
printf(" {%d,%d,'%c'},", c.variable_1, c.variable_2, c.character);
}
printf("\n");
}
}
int main(void)
{
size_t array_rows = 3;
size_t array_columns = 3;
cell **array = allocateArray(array_rows, array_columns);
if (array == NULL) {
printf("Error in ""main"": Memory could not be allocated.\n");
return 3;
}
initialiseArray(array_rows, array_columns, array);
printf("before resize:\n");
displayArray(array_rows, array_columns, array);
if (!resizeArray(4, 5, &array_rows, &array_columns, &array)) {
printf("Memory error. We stop the program.\n");
return -1;
}
printf("after resize:\n");
displayArray(array_rows, array_columns, array);
free(array);
return 0;
}
Output:
before resize:
{0,0,' '}, {0,1,' '}, {0,2,' '},
{1,0,' '}, {1,1,' '}, {1,2,' '},
{2,0,' '}, {2,1,' '}, {2,2,' '},
after resize:
{0,0,' '}, {0,1,' '}, {0,2,' '}, {0,0,''}, {0,0,''},
{1,0,' '}, {1,1,' '}, {1,2,' '}, {0,0,''}, {0,0,''},
{2,0,' '}, {2,1,' '}, {2,2,' '}, {0,0,''}, {0,0,''},
{0,0,''}, {0,0,''}, {0,0,''}, {0,0,''}, {0,0,''},
答案2
得分: 3
请参考 @chqrlie 的答案,详细评估您的代码。我只想回应这一点:
"> 我的代码不起作用,但是奇怪的是,我的编译器没有发出警告。"
编译器无法检测到您可能犯的每个错误,而且它没有义务诊断除语言形式约束的违规之外的任何事情。(对于其他任何情况,它应该能够生成代码。)
但是,我对您的说法表示怀疑。如果编译器没有诊断以下事实:
- 您的
resizeArray()
函数可以在不返回值的情况下终止, - 您的
resizeArray()
函数可以返回其类型与函数声明的返回类型不匹配的值, - 您的
main()
包含不可访问的代码,以及 main
中的array = new_array
包含类型不匹配
那么要么您的编译器不太好,要么您已禁用(某些)警告,要么以某种方式丢弃或错过了它实际上正在发出的诊断信息。
事实上,您的
在运行时也会包含类型不匹配,但鉴于这涉及到可变修改的类型,我不会真的期望编译器对其进行诊断。
英文:
Refer to @chqrlie's answer for a detailed critique of your code. I just want to address this:
> my code does not work, but my compiler, strangely, does not throw a warning.
The compiler cannot detect every possible thing you could do wrong, and it is not obligated to diagnose anything other than violations of the language's formal constraints. (And for anything else, it should be able to generate code.)
However, I'm skeptical of your claim. If the compiler does not diagnose the facts that
-
your
resizeArray()
function can terminate without returning a value, -
your
resizeArray()
function can return a value whose type is mismatched with the function's declared return type, -
your
main()
contains unreachable code, and -
array = new_array
inmain
contains a type mismatch
then either your compiler isn't very good, or you've disabled (some) warnings, or you're some other way discarding or missing diagnostics that it is, in fact, emitting.
As it turns out, your
>
> initialiseArray(array_rows, array_columns, *array);
>
will also contain a type mismatch at runtime, but inasmuch as this involves variably-modified types, I wouldn't really expect the compiler to diagnose it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论