意外的输出,为什么?

问题描述 投票:0回答:2

这很简单,我正在使用函数分配动态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");
    }

  }
}
c arrays function dynamic-memory-allocation
2个回答
4
投票

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()是非标准且不可移植的。而且,您不需要使用它们中的任何一个。


2
投票

而不是使用越来越多的指针,我想用这种方式:-

#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是什么,但是它使代码变得模棱两可,所以我删除了该代码,并在程序中的任何地方(有需要的地方)将其替换为ROWCOLUMN

在通过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));

注意:另外,您应该在分配内存时检查是否有任何错误。

希望,会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.