简体   繁体   中英

Scanf into multidimensional Array, allocated with malloc

I am trying to allocate a new "multidimensional" array based on the user input and then populate the array with the values provided by user. After that the contents should be printed. The array seems to be allocated correctly, but the internal cycle can write only one value to the newly allocated array before crash.

If I get it correctly, all the values in multidimensional array are stored in a row. That is why I have chosen that way of accessing the cells of the array.

Could someone please explain why the code does not work as expected? And what are the right ways/best practices to achieve the same target?

I assume that I could do that in a "classical" way - allocate an array of pointers and than allocate an array for each pointer. That could work, but does not answer the question why the sequential accessing is not a viable option.

#include <stdio.h>
#include <stdlib.h>

int input(int **arr, int *len_x, int *len_y);
int output(int *arr, int *len_x, int *len_y);

int main()
{
    int *array;
    int length_x;
    int length_y;
    input(&array, &length_x, &length_y);
    output(array, &length_x, &length_y);
    return 0;
}

int input(int **arr, int *len_x, int *len_y) {
    scanf("%d %d", len_x, len_y);
    *arr = malloc(*len_y * *len_x * sizeof(int));
    
    for(int x = 0; x < *len_x; x++){
        for(int y = 0; y < *len_y; y++) {
            scanf("%d", arr[x * *len_y + y]);
        }
    }
}

int output(int *arr, int *len_x, int *len_y) {
    for(int x = 0; x < *len_x; x++){
        for(int y = 0; y < *len_y; y++) {
            printf("%d", arr[x * *len_y + y]);
        }
        printf("\n");
    }
}

Indexing

In input() , int **arr ... arr[x * *len_y + y] is indexing an array of int * . Code needs to index an array of int . See also @kaylum

Clearer to get the data and then assigned via the 3 parameter pointers.

Missing return value

int input() does not return a value. This implies compilation was not done with all warnings enabled. Save time, enable all warnings.

Sizing

Allocate to the size of the referenced object. Easier to code right, review and maintain.

Error checks missing

Check scanf() and malloc() success.

Alternate output()

Recommended alternative - easier to understand.

// int output(int *arr, int *len_x, int *len_y) {
void output(const int *arr, int len_x, int len_y) {
//                          ^^^        ^^^ --- pass length, not pointer to length
//          ^^^^^  --------------------------- referenced data does not changed

// Return 0 on success
int input(int **arr, int *len_x, int *len_y) {
  int x,y;
  if (scanf("%d %d", &x, &y) != 2) {
    return 1;
  }

  int *a = malloc(sizeof *a * x * y);
  if (a == NULL) {
    return 1;
  }

  for(int xi = 0; xi < x; xi++) {
    for(int yi = 0; yi < y; yi++) {
      if (scanf("%d", &a[xi * y + yi]) != 1) {
        free(a);
        return 1;
      }
    }
  }

  *arr = a;
  *len_x = x;
  *len_y = y;
  return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM