Сохранить элементы в двумерном массиве - PullRequest
1 голос
/ 26 апреля 2020

Как я могу сохранить числа в двухмерном массиве? Почему этот код не работает?

void input_arr(int *arr, int n, int m);

void print_arr(int *arr, int n, int m);

int main()
{
    int *arr;
    int n, m;

    printf("Insert line of array: ");
    scanf("%d", &n);

    printf("Insert column of array: ");
    scanf("%d", &m);

    arr = calloc(n * m, sizeof(int));

    input_arr(arr, n, m);

    return 0;
}

void input_arr(int *arr, int n, int m)
{
    int i;
    int j;
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < m; j++)
        {
            printf("Insert element in line %d and column %d: ", i, j);
            scanf("%d", (&arr[i][j]));
        }
    }
}

void print_arr(int *arr, int n, int m)
{
    int i, j;
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < m; j++)
        {
            printf("%d ", *arr[i][j]);
        }
    }
}

Ответы [ 5 ]

2 голосов
/ 26 апреля 2020

Замените ваши объявления функций следующим образом:

void input_arr(int *arr[], int n, int m)
void print_arr(int *arr[], int n, int m)

Где бы вы ни вызывали scanf и printf для элементов массива, используйте это:

scanf("%d", arr + i * m + j);
printf("%d", *(arr + i * m + j));

Для хорошей практики , освободи память, когда закончишь. Добавьте это в конце вашего main():

free(arr);

Кроме того, если у вас есть компилятор C99 или новее, вы можете использовать массивы переменной длины , чтобы выполнить работу и позволить индексировать массив с помощью arr[i][j] вместо уродливого arr + i * m + j.

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

//note that the arr parameter must be declared AFTER the m parameter since it uses its information
void input_arr(int n, int m, int arr[][m]);

void print_arr(int n, int m, int arr[][m]);

int main(void)
{
    int n, m;

    printf("Insert line of array: ");
    scanf("%d", &n);

    printf("Insert column of array: ");
    scanf("%d", &m);

    int arr[n][m];

    input_arr(n, m, arr);

    print_arr(n, m, arr); //I am assuming you also want to print the array

    //return 0; //not needed in C99
}

void input_arr(int n, int m, int arr[][m])
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            printf("Insert element in line %d and column %d: ", i, j);
            scanf("%d", &arr[i][j]);
        }
    }
}

void print_arr(int n, int m, int arr[][m])
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            printf("%d ", arr[i][j]);
        }
        //you probably want a new line here to display it as a matrix
        printf("\n");
    }
}
1 голос
/ 26 апреля 2020

Как сохранить числа в двумерном массиве?

Пример:

int twoD[2][3];
twoD[1][1] = 42;

Почему этот код не работает?

Код OP не использует двумерный массив, а указывает на int, а затем неправильно использует этот указатель.

int *arr;
// Allocate memory for a 1-D array of  n*m `int` 
arr = calloc(n * m, sizeof(int));

Код функции пытается отменить ссылку на int

void input_arr(int *arr, int n, int m) {
  ...
  scanf("%d", (&arr[i][j])); // bad

Здесь arr[i] является int. arr[i][j] не имеет смысла.


Для выделения памяти нужен указатель, но какого типа?

Хотите ли вы указатель на двумерный массив, ниже,
указатель на массив int [m] DarkAtom
или указатель на массив указателей на int @ anastaciu ?

int (*TwoD)[m][n] = malloc(sizeof *Two);
(*TwoD)[1][1] = 42;
....

Или использовать текущий код в 2D-стиле и получить доступ к распределению массива 1D с помощью вычисленного индекса.

// scanf("%d", (&arr[i][j]));
scanf("%d", &arr[i*m + j]);

// printf("%d ", *arr[i][j]);
printf("%d ", arr[i*m + j]);
1 голос
/ 26 апреля 2020

Код выделяет и инициализирует непрерывный кусок памяти и передает указатель на int для функций. Проблема заключается в том, что внутри этих функций этот указатель разыменовывается слишком много раз.

void input_arr(int *arr, int n, int m)
{
    // ...
    scanf("%d", (&arr[i][j]));
    //                  ^^^ 
}

void print_arr(int *arr, int n, int m)
{
    // ...
    printf("%d ", *arr[i][j]);
    //            ^      ^^^
}

Если вы можете использовать массивы переменной длины, то вариант, отличный от тех, которые уже размещены в других ответах, - объявить указатель VLA внутри этих функций:

void input_arr(int *arr, int n, int m)
{
    // ...
    scanf("%d", arr++);
    //          ^^^ Here you can just access to every element in order 
}

void print_arr(int *arr, int n, int m)
{
    // Declare a pointer to array of m elements
    int (*mat)[m] = (void *)arr;

    // ...
    printf("%d ", mat[i][j]);
    //            ^^^^^^^^^  Use it as if it's a 2D VLA
}

Также не забудьте освободить выделенную память в main.

1 голос
/ 26 апреля 2020

Вы передаете указатель на выделенное пространство, оно сохраняется, как если бы оно было линейным массивом, для выполнения того, что вы хотите, 2D-массив или что-то, что можно использовать таким же образом, вам нужно:

  1. Массив указателей на строки и выделение памяти для каждого из них, имитирующих столбцы.
  2. Двойной указатель и выделение памяти для хранения значений таким образом, чтобы эмулировать строки и столбцы.
  3. Вы также можете использовать линейный массив и сделать так, чтобы входы и выходы казались 2D-массивом.
  4. Или вы можете просто использовать обычный нормальный 2D-массив.

Поскольку вы вы используете выделение памяти вот возможная реализация с использованием двойного указателя:

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

void input_arr(int **arr, int n, int m); //double pointer to int parameter
void print_arr(int **arr, int n, int m); //same

int main() {

    int n, m;
    int **arr; //double pointer for 2D array like memory allocation

    printf("Insert line of array: ");

    if(scanf("%d", &n) != 1 || n < 1) {  //always check input
        puts("positive integer value expected!"); 
        return 1;
    }

    printf("Insert column of array: ");

    if(scanf("%d", &m) != 1 || m < 1) {  //always check input
        puts("positive integer value expected!");
        return 1;
    }

    if(!(arr = malloc(n * sizeof(*arr)))){ //allocate memory lines, check for errors
        perror("Memory allocation failed!");
        return 1;
    }

    for(int i = 0; i < n; i++)
        if(!(arr[i] = malloc(m * sizeof(**arr)))) { //allocate memory for columns, check for errors
            perror("Memory allocation failed");
            return 1;
        }

    input_arr(arr, n, m);
    print_arr(arr, n, m);

    return 0;
}

void input_arr(int **arr, int n, int m) {

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            printf("Insert element in line %d and column %d: ", i, j);
            scanf("%d", &arr[i][j]);
        }
    }
}

void print_arr(int **arr, int n, int m) {

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            printf("%d ", arr[i][j]); //no dereferencing
        }
        putchar('\n');
    }
}
0 голосов
/ 26 апреля 2020

Вам необходимо передать массив в виде двойного указателя (массив int ** или более простой массив int * array []).

Объяснение Передавая массив как массив int *, когда вы говорите & array [i] вы выводите скопированное значение массива, а не исходное значение. В частности, в функции, когда вы просто хотите прочитать (или / и распечатать) данные массива, вы можете просто использовать один указатель, но если вы хотите изменить его, вы должны использовать двойной указатель.

...