0

I'm trying to make a code that adds a row to a 2D array, then assign values to it. However it is giving wrong results in a specific array cell. Here is the code:

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

void add_one_row_2Dvector(double ***attrac, int *rows) {
    // Realloc matrix
    (*rows)++;
    double **tmp = realloc(*attrac, (*rows) * sizeof ***attrac);
    for (int i = (*rows) - 1; i < (*rows); i++) {
        tmp[i] = malloc((*rows) * sizeof ***attrac);
    }
    if (tmp == NULL) {
        // Check if reallocation failed, If so, return...
        printf("Couldn't realloc 2D vector...\n");
        return;
    } 
    else {
        (*attrac) = tmp;
    }
}

void assign_values_to_new_row(double ***attrac, int rows, double *X, int indexX, int indexY, double **count) {
    (**count)++;
    X[indexX]++; X[indexY]++;
    (*attrac)[rows - 1][0] = X[indexY];
    (*attrac)[rows - 1][1] = X[indexX];
    (*attrac)[rows - 1][2] = (**count);
}

void print_matrix(double **attrac, int rows, int cols) {
    printf("Matrix (rows = %d):\n", rows);
    for (int i = 0; i < rows; ++i) { 
        for (int j = 0; j < cols; ++j) { 
            printf("%4.1lf ", attrac[i][j]); 
        } 
        printf("\n"); 
    }
}

void do_everything(double ***attrac, int *rows, int cols, double *count, double *X, int indexX, int indexY) {
    add_one_row_2Dvector(attrac, rows); 
    assign_values_to_new_row(attrac, (*rows), X, indexX, indexY, &count);
    print_matrix((*attrac), (*rows), cols);
}



int main(void) {
    // Declare Scalars
    int rows = 1, cols = 3;
    double count = 0;
    int indexX = 0, indexY = 1;
    //Declare Vectors
    double **attrac = malloc(rows * sizeof **attrac);
    for (int i = 0; i < rows; i++) {
        attrac[i] = malloc(cols * sizeof **attrac);
    }
    double *X = malloc(2 * sizeof *X);
    // Assign Values to X
    X[indexX] = 0.1;
    X[indexY] = 1.2; 

    // Assign values to matrix
    count++;
    attrac[0][0] = X[indexY];
    attrac[0][1] = X[indexX];
    attrac[0][2] = count;
    // Print initial matrix
    print_matrix(attrac, rows, cols);
    printf("count = %.1lf\n", count);
    
    for (int i = 0; i < 4; i++) {
        // Add row and make calc
        printf("\ni = %d\n", i);
        do_everything(&attrac, &rows, cols, &count, X, indexX, indexY);
        printf("count = %.1lf\n", count);
    }
    
    // Free Memory
    for (int i = 0; i < rows; i++) {
        free(attrac[i]);
    }
    free(attrac);
    free(X);
    return 0;
}

Here is the result:

Matrix (rows = 1):
 1.2  0.1  1.0 
count = 1.0

i = 0
Matrix (rows = 2):
 1.2  0.1  1.0 
 2.2  1.1  2.0 
count = 2.0

i = 1
Matrix (rows = 3):
 1.2  0.1  1.0 
 2.2  1.1  0.0 
 3.2  2.1  3.0 
count = 3.0

i = 2
Matrix (rows = 4):
 1.2  0.1  1.0 
 2.2  1.1  0.0 
 3.2  2.1  3.0 
 4.2  3.1  4.0 
count = 4.0

i = 3
Matrix (rows = 5):
 1.2  0.1  1.0 
 2.2  1.1  0.0 
 3.2  2.1  3.0 
 4.2  3.1  4.0 
 5.2  4.1  5.0 
count = 5.0

The value of attrac[1][2] should be 2.0, however in iterations i >= 1, its value changes to 0.0. I don't understand why this is happening. What am I missing here?

Thanks in advance!

Lgcos
  • 91
  • 7
  • 1
    Do you need this to have individually sized rows/columns or is it a true mathematical matrix? In case of the latter, you should definitely get rid of this painful "three star programming" in favour of correctly allocated 2D arrays: https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays – Lundin Aug 19 '22 at 13:59
  • `double **tmp = realloc(*attrac, (*rows) * sizeof ***attrac);` That should be `**attrac` I think. – Gerhardh Aug 19 '22 at 14:14
  • `if (tmp == NULL)` That would make more sense if you did that before assigning values to `tmp[i]`. BTW: That loop is only executed once. Why do you use a loop? – Gerhardh Aug 19 '22 at 14:17

2 Answers2

2
  1. You do not have 2d matrix only array of pointers 2D array is something completely different.
  2. Rather use return values instead of side effects.
  3. use the correct type for sizes (size_t)

Real 2D matrix example:

void *addRow(size_t *rows, size_t cols, double (*arr)[cols], ...)
{
    va_list va;
    va_start(va, arr);


    arr = realloc(arr, sizeof(*arr) * (*rows + 1));
    if(arr)
    {
        for(size_t col = 0; col < cols; col++)
            arr[*rows][col] = va_arg(va, double);
        *rows += 1;
    }
    va_end(va);
    return arr;
}

void printArray(size_t rows, size_t cols, double (*arr)[cols])
{
    for(size_t row = 0; row < rows; row++)
    {
        for(size_t col = 0; col < cols; col++)
            printf("%6.2f\t", arr[row][col]);
        printf("\n");
    }
}

int main(void)
{
    double (*arr)[5] = NULL;
    void *tmp;
    size_t rows = 0;
    
    for(int x = 0; x < 5; x++)
    {
        tmp = addRow(&rows, 5, arr, 1.0 + x * 1000.0, 2.0 + x * 1000.0, 3.0 + x * 1000.0, 4.0 + x * 1000.0, 5.0 + x * 1000.0);
        
        if(tmp) printf("%zu\n", rows);arr = tmp;
    }
    printArray(rows, 5, arr);
}
0___________
  • 60,014
  • 4
  • 34
  • 74
0

After a while I managed to find the error. It is located in add_one_row_2Dvector funcion. The correct version should be:

void add_one_row_2Dvector(double ***attrac, size_t *rows, size_t cols) {
    // Realloc matrix
    (*rows)++;
    double **tmp = realloc(*attrac, (*rows) * sizeof **attrac);
    for (int i = (*rows) - 1; i < (*rows); i++) {
        tmp[i] = malloc((*cols) * sizeof **attrac);
    }
    if (tmp == NULL) {
        // Check if reallocation failed, If so, return...
        printf("reallocation failed...\n");
        return;
    }
    else {
        (*attrac) = tmp;
    }
}

as the number of cols needs to be considered.

Lgcos
  • 91
  • 7