这很简单,我正在使用函数分配动态2D数组。我限制了scanf()
len,我的问题是,当输入的值超出限制时,会发生一些奇怪的事情。
示例输入:111,222,333,444预期产出:11,22,33,44实际输出:11、12、33、34
#include <stdio.h>
#include <stdlib.h>
#define gd 2
void get_mem(int ***arr);
void get_data(int **arr);
int main(){
int **arr;
arr = NULL;
get_mem(&arr);
get_data(arr);
free(*arr);
return 0;
}
void get_mem(int ***arr){
int i;
*arr = (int**)malloc(gd*sizeof(int*));
for(i=0;i<5;i++){
(*arr)[i] = (int*)malloc(gd*sizeof(int));
}
printf("oki\n");
}
void get_data(int **arr){
int c,f;
for(c=0;c<gd;c++){
for(f=0;f<gd;f++){
scanf("%2d",&*(*arr+c)+f);
fpurge(stdin);
fflush(stdin);
}
}
for(c=0;c<gd;c++){
for(f=0;f<gd;f++){
printf("%d ",*(*arr+c)+f);
printf("\n");
}
}
}
宏gd
的值为2
。在get_mem()
中,为2
int *
分配内存:
*arr = (int**)malloc(gd*sizeof(int*));
及其下方,访问超出其大小的arr
:
for(i=0;i<5;i++){ //allocating memory to 5 int pointers
^^
(*arr)[i] = (int*)malloc(gd*sizeof(int));
}
访问未分配的内存是未定义的行为。
而不是在循环条件下使用幻数5
,您应该用i
检查gd
,像这样
for(i=0;i<gd;i++){
在get_data()
中,您访问arr
的元素进行输入的方式错误
scanf("%2d",&*(*arr+c)+f);
^^^^^^^^^^^^
因为
&arr[c][f] --> &(*(arr[c] + f) --> &(*(*(arr + c) + f)) --> &*(*(arr + c) + f) --> (*(arr + c) + f)
注:运算符&
用于获取地址,运算符*
用于取消引用。这些运算符相继使用时会相互抵消。因此,&(*(arr + i))
等效于arr + i
。
这意味着&arr[c][f]
等效于(*(arr + c) + f)
,您应该使用&arr[c][f]
,它不易出错,更易读:
for(f = 0; f < gd; f++) {
scanf("%2d", &arr[c][f]);
您在第二个arr
循环中打印for
元素时犯了同样的错误:
for(f=0;f<gd;f++){
printf("%d ",*(*arr+c)+f);
^^^^^^^^^^^
应该为*(*(arr + c) + f)
。更具可读性的形式是arr[c][f]
:
for(f = 0; f < gd; f++){
printf("%d ", arr[c][f]);
您不应该将fflush()
用于input
流。这是未定义的行为。来自C Standards#7.21.5.2p2-
如果流指向未输入最新操作的输出流或更新流,则fflush函数会使该流的任何未写入数据都将传递到主机环境中,并写入该文件中;否则,行为未定义。
此外,fpurge()
是非标准且不可移植的。而且,您不需要使用它们中的任何一个。
而不是使用越来越多的指针,我想用这种方式:-
#include <stdio.h>
#include <stdlib.h>
//#define gd 2
#define ROW 2
#define COLUMN 2
void get_mem(int ***arr);
void get_data(int **arr);
int main(){
int **arr = NULL;
get_mem(&arr);
printf("Enter 4 int values: ");
get_data(arr);
free(*arr);
return 0;
}
void get_mem(int ***arr)
{
int i;
*arr = ( int ** )malloc( ROW * sizeof(int *) );
for(i = 0; i < COLUMN; i++)
{
(*arr)[i] = ( int * )malloc( COLUMN * sizeof(int) );
}
printf("Okay!\n");
}
void get_data(int **arr)
{
int c, f;
for(c = 0; c < ROW; c++)
{
for(f = 0; f < COLUMN; f++)
{
scanf("%2d", &arr[c][f]); //*(*arr+c)+f)
}
}
for(c = 0; c < ROW; c++)
{
for(f = 0; f < COLUMN; f++)
{
printf("%d ", arr[c][f]); //*(*arr+c)+f)
}
putchar('\n');
}
}
[我不知道gd
是什么,但是它使代码变得模棱两可,所以我删除了该代码,并在程序中的任何地方(有需要的地方)将其替换为ROW
和COLUMN
。
在通过int **arr
函数向get_mem()
分配空间之后,至少要求用户输入值并使用适当的间距和缩进。
不需要fflush or fpurge
,所以我删除了它们。现在,在这里,如果您以这种方式访问数组,则需要非常注意在适当的位置使用括号。您应该使用*(*(arr+c)+f)
而不是*(*arr+c)+f)
(这是一个错误。)。但是我选择像在2D数组中那样访问元素或存储值。这样更容易。
如果您仅想使用指针访问此数组,而不是arr[c][f]
,则可以通过以下方式进行:-
scanf("%2d", &(*(*(arr+c)+f)));
&
printf("%d ", *(*(arr+c)+f));
注意:另外,您应该在分配内存时检查是否有任何错误。
希望,会有所帮助。