Search code examples
cmatrixpointer-to-pointercop

Copying a pointer of a pointer (matrix) values in C


The problem is the following: I created a dynamic matrix, using pointer to pointer matrix1

I want to create a copy of this matrix into another, matrix2

I want to do that so I can mess with matrix2 without messing with matrix1 So I tried to do the following:

int main()
{
    int **matrix1, **matrix2, size1 = 10, size2 = 2;
    matrix1 = create_matrix(size1, size2);

    //I want to copy the value of matrix1 into matrixq2 and NOT the index
    **matrix2 = **matrix1
}

However the program breaks and show the following: Error

I understand that by the way it look, it would be easier to use the function create_matrix two times, for matrix1 and another for matrix2. But in the way that my original program is that would be too much work, since I do a lot of stuff to have the matrix done. Oh, and by the way, I want to avoid using C++, is there is a way to do it without using it? It would be better for me.

the code 'create_matrix' is the following:

//The program will read a file with the name of endereco, and create a matrix contPx3 out of it
int ** cria_matrix(char endereco[], int contP)
{
    FILE *fPointer;
    int i, contE, auxIndex, auxNum, **processos, cont_line = 0;
    char line[100];
    bool flag = true, flag2;

    fPointer = fopen(endereco, "r");

//Here the creation of the matrix
    processos = (int**)malloc(sizeof(int*) * contP);
    for (i = 0; i < contP; i++)
        processos[i] = malloc(sizeof(int) * 3);



//For now and on, is the rules of how the data will be placed on the matrix
    contP = 0;
    while (!feof(fPointer) && flag)
    {

        memset(&line[0], 'Ì', sizeof(line));
        fgets(line, 100 , fPointer);
//Bassicaly is that in each line there will be 3 numbers only, diveded but as many spaces you want. The numbeer will be placed on the matrix on the determined line they are.
        auxIndex = 0;
        flag2 = false;
        if(line[0] != '#')
            for (i = 0; i < 100; i++)
            {
                if (line[i] != ' ' && line[i] != '\n' && line[i] != '\0' && line[i] != 'Ì')//&&  line[i] != 'à'
                {
                    auxNum = line[i] - '0';
                    processos[contP][auxIndex] = auxNum;
                    auxIndex++;
                    flag2 = true;

                }
            }

        if (flag2)
            contP++;



        cont_line++;
        if (auxIndex != 3 && auxIndex != 0)
        {
            flag = false;
            printf("ERRO na linha: %d No processo: %d\nProvavelmente mais ou menos que 3 numeros separado por espacos\n", cont_line, contP);
        }

    }
    fclose(fPointer);
    if (!flag)
        system("PAUSE");
    return processos;
}

Solution

  • matrix1 points to the array of row pointers, *matrix1 is a pointer to an array holding the first row of actual data, and **matrix1 is the value of first element of the first row. matrix1 and each of its elements are all dynamically allocated arrays.

    matrix2 is an uninitialized (trash) pointer in the code you have displayed. It has neither the row pointer nor data buffers allocated.

    To achieve your desired result, you need to first allocate the elements of matrix2, then copy just the data portion of matrix1 over.

    int **copy_matrix(int **mat, int size1, int size1)
    {
        int row;
    
        int **res = malloc(size1 * sizeof(int *));
        for(row = 0; row < size1; row++) {
            res[row] = malloc(size2 * sizeof(int));
            memcpy(res[row], mat[row], size2 * sizeof(int));
        }
        return res;
    }
    
    ...
    
    matrix2 = copy_matrix(matrix1, size1, size2);
    

    An alternative would be to allocate a single buffer for the copy. While this is possibly a better way of storing matrices in general, it may not be as useful to you because you will not be able to free the memory of matrix2 the same way that you do for matrix1:

    int **copy_matrix(int **mat, int size1, int size2)
    {
        int row;
        int **res = malloc(size1 * sizeof(int *));
        res[0] = malloc(size1 * size2 * sizeof(int));
    
        for(row = 0; row < size1; row++) {
            res[row] = res[0] + row * size2;
            memcpy(res[row], mat[row], size2 * sizeof(int));
        }
        return res;
    }