0

I'm trying to store table(stored in a file) into memory. I have here my edited code for simplicity. Im running into segmentation fault so I think it has to do something with that I try to store values without declaring the arrays actually. But I read it shouldn't be a problem as struct arrays are dynamic on their own? I don't really know. So in function addcelltoTable I tried some reallocating, but unsuccessfully. Can you help me understand memory allocating and maybe pointers a little more?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>
typedef struct Cells
{
    bool selected;
    char *Content;
} cell;

typedef struct Rows
{
    int someint;
    cell cells[];
} row;
typedef struct Tables
{
    int NumberOfColumns;
    int NumberOfRows;
    row rows[];

} table;
void addCellToTable(table *dataTable, char *cellContent, int row, int column)
{
    if (row > dataTable->NumberOfRows)
    {
        dataTable->NumberOfRows = row;
    }
    if (column > dataTable->NumberOfColumns)
    {
        dataTable->NumberOfColumns = column;
    }
    *dataTable->rows[row].cells = (cell*)realloc(dataTable->rows[row].cells, column*sizeof(char*)+1);  //here I'm trying to realloc array of cells , error: incompatible types when assigning to type ‘cell’ {aka ‘struct Cells’} from type ‘cell *’ {aka ‘struct Cells *’}
    //*dataTable->rows = (row*)realloc(dataTable->rows, (sizeof(dataTable->rows)*sizeof(char*))); //realloc array of rows ?
    *dataTable->rows[row].cells[column].Content = *cellContent;
    printf("%d : %d : %lu : %s\n", row, column, strlen(dataTable->rows[row].cells[column].Content), dataTable->rows[row].cells[column].Content);
}
int main()
{
    char numberitoa[10];
    table dataTable;
    /*dataTable.NumberOfColumns=0;
    dataTable.NumberOfRows=0;
    dataTable.rows[0].someint=0;
    dataTable.rows[0].cells[0].selected=false;
    dataTable.rows[0].cells[0].Content="";*/
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            sprintf(numberitoa, "%d", rand());
            addCellToTable(&dataTable, numberitoa, i, j);
        }
    }
    for (int i = 0; i < dataTable.NumberOfColumns + 1; i++)
    {
        for (int j = 0; j < dataTable.NumberOfRows + 1; j++)
        {
            printf("main: %d, %d, %s\n", i, j, dataTable.rows[i].cells[j].Content);
        }
        printf("\n");
    }
    return 0;
}
8
  • The structs can contain arrays but you have defined them as cells[] rows[] etc. inside your structs. Behaviour will be a bit standard dependent but you haven't actually allocated any memory to them. Either provide an array size in the typedef or initialise the array elements using calloc(). Commented Nov 27, 2020 at 18:15
  • Are you allocating memory to Content before writing to it? Commented Nov 27, 2020 at 18:36
  • Change cell cells[]; to cell *cells; and similar for rows. Don't you get compiler warnings? Commented Nov 27, 2020 at 18:38
  • @KamilCuk no, no errors or warnings regarding structs. Why should changing to *cells make sense ? i need to store multiple cells not one. or I can make that pointer point to array ? Commented Nov 27, 2020 at 19:52
  • @ryyker that's what I'm trying to do but I don't really know how. Commented Nov 27, 2020 at 19:53

1 Answer 1

1

An array declared with [] at the end of a structure is a flexible structure array, not a pointer to an array. Consequently you cannot reallocate it (instead you should reallocate the whole structure). Therefore it seems simpler to use a pointer to the allocated memory. This slightly changes the structures :

typedef struct Cell
{
    // You cannot use the same storage for each string as you did
    // instead we can use a fixed sized string (no allocation required)
    char Content[10]; 
    bool selected;

} cell;

typedef struct Rows
{
    int someint;
    cell * cells;
} row;
typedef struct Tables
{
    int NumberOfColumns;
    int NumberOfRows;
    row * rows;

} table;

There was a subtle issue in your allocation codes : when you allocate a row, the rows->cells array contains garbage, which makes any function called on it (including realloc) subject to crash. So these arrays must be set to NULL immediately after the rows have been allocated.

void addCellToTable(table *dataTable, char * cellContent, int row, int column)
{ 
    if (dataTable->NumberOfRows != row + 1) {
        dataTable->rows = realloc(dataTable->rows, (row + 1) * sizeof(struct Rows));
        for (int i=0; i <= row; i++) dataTable->rows[i].cells = NULL; //<== here
    }
    if (dataTable->NumberOfColumns != column + 1)
        dataTable->rows[row].cells = realloc(dataTable->rows[row].cells, (column + 1) * sizeof(struct Cell));
    
    // The fixed sized string must be set with memcpy
    memcpy(dataTable->rows[row].cells[column].Content, cellContent, strlen(cellContent) + 1);
    
    dataTable->NumberOfRows = row + 1;
    dataTable->NumberOfColumns = column + 1;
}

Finally your arrays are reallocated at each iteration so the print statement should be in the same loop than the allocations otherwise you cannot print all allocated cells.

int main()
{
    char numberitoa[10];
    table dataTable = {0};
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            sprintf(numberitoa, "%d", rand() % 1000);
            addCellToTable(&dataTable, numberitoa, i, j);

            printf("main: %d, %d, %s\n", i, j, dataTable.rows[i].cells[j].Content);
        }
    }
    return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.