0

Objective

To create an array of an array of structs, the dimensions based on a file. Then store that into a Linked List.

I am reading from a file formatted like this:

Read a file that is in the form:

name (string)  country (string)  age (int)
john           USA               54
Sam            Aus               18
ect

I dont know how many rows and columns the file will have , nor do I know what varible type each column will be

So in theory the first array of struct will contain [NUMBER OF COLUMNS] strucs that will store each variable (using a void pointer and typecasting) along the line( so strucArrayCol[0] = john , structArrayCol[1] = USA ect).

Each of these array of strucs will be stored into another array of strucs which will have [NUMBER OF ROWS] elements so strucArray2Row[0] = strucArrayCol (which contains john , USA and 54) and strucArrayRow[1] will contain another strucArrayCol which contains (sam Aus 18).

So right now I can read the file, and find the number or rows, columns and the variable type of each column.

This is where i start having trouble as im not sure how to go about

1. How to create this array within array ( I know i need to use Malloc)
2.How I would store the variables in the first array of struc, if I
  wanted to store age could I just do

    void *data = malloc(sizeof(int));
    *((int*)data) = TEMP_AGE;

void data being a struc in StrucArrayCol ( in the case of the example if I wanted to store the age of John void* data would be in StrucArrayCol[3] which is inside StucArrayRow[0], as its the 3rd col in the first line)

Sorry if this dosent make sense Thanks

14
  • 1
    If you don't know the prototype for the struct like (there is always a name, country, age) there is no need to use a struct at all. You could just do a one dimensional array of each column because they have the same type. and then create a new array that contains the addresses to every array. Commented Oct 20, 2016 at 6:13
  • Sorry im not great at explaining , the issue is that I wont know what each column will be and also I have to put it in a "Generic Linked List" so I thought this would be the best way to deal with unknown types of variables Commented Oct 20, 2016 at 6:22
  • Yeah but why use structs when you can parse the data type of each coloum you can use an array of this data type. A struct would be useful if all list would have the same variables in it (maybe in different order but the name/type don't change) then you could use a struct and fill it with the parsed values of the list got to the next struct in the array and to the next row in the list and do it again. Commented Oct 20, 2016 at 6:24
  • So question is do you know the types of the struct members beforehand or not? Lets say does it always have two strings and one int or does this change everytime? Commented Oct 20, 2016 at 6:27
  • 1
    Why do you want to use a struct? A struct would only work if you know what members should go into that struct. You don't need a struct just for a string. Commented Oct 20, 2016 at 6:33

2 Answers 2

1

You can create a linked-list within a linked-list, assuming there is aversion to anything which is not a linked-list! Declare two linked-list node structures, one for rows in the file, and one for columns within each row:

struct column
{
    char *buf;
    struct column *next;
};

struct row
{
    struct column *head;
    struct row *next;
};

Read the file one line at a time, add one row node for each line. Each row will have its own link-lists, it will parse the line in to columns.

struct column* column_create(struct column* cursor, char *line)
{
    struct column *node = malloc(sizeof(struct column));
    node->next = 0;
    node->buf = malloc(strlen(line) + 1);
    strcpy(node->buf, line);
    if (cursor)
        cursor->next = node;
    return node;
}

struct row* row_create(struct row* cursor, char *line)
{
    struct row *node = malloc(sizeof(struct row));
    node->next = 0;
    node->head = 0;

    //parse the line in to columns
    struct column *col = 0;
    char *token = strtok(line, " \n");
    while (token)
    {
        col = column_create(col, token);
        if (!node->head)
            node->head = col;
        token = strtok(NULL, " \n");
    }

    if (cursor)
        cursor->next = node;
    return node;
}

Or you can do this with a 2-dimensional array of text (which would be 3-dimensional array of characters). Or use an array of strings to hold all the lines in the file, then parse each line in to column. From there, you can test each column to see if it is integer or not.

If you don't know the number of lines in the file, use realloc to allocate as much memory is needed during run time. This example reads all the lines in file, and copies it to an array of lines:

int main()
{
    FILE *f = fopen("test.txt", "r");
    char **lines = 0;
    int lines_size = 0;
    int lines_capacity = 0;
    char buf[1024];
    while (fgets(buf, sizeof(buf), f))
    {
        int len = strlen(buf);
        if (!len) continue;
        if (lines_size == lines_capacity)
        {
            lines_capacity += 16;
            lines = realloc(lines, lines_capacity * sizeof(char*));
        }

        lines[lines_size] = malloc(len + 1);
        strcpy(lines[lines_size], buf);
        lines_size++;
    }

    int i;
    for (i = 0; i < lines_size; i++)
        printf("%s", lines[i]);
    printf("\n");

    for (i = 0; i < lines_size; i++)
        free(lines[i]);
    free(lines);
    return 0;
}

This will work as long as line length in the file never exceeds 1024. Separately, you can parse each line using strtok

void parseline(char *line)
{
    char copy[1024];
    strcpy(copy, line);
    char *token = strtok(copy, " \n");
    while (token)
    {
        printf("[%s], ", token);
        token = strtok(NULL, " \n");
    }
    printf("\n");
}
Sign up to request clarification or add additional context in comments.

4 Comments

@KamiKaze The asker mentions arrays in another section. I should have asked if this is for homework with specific linked list requirements. Linked lists are complicated to work with and slow compared to vector-style memory management.
yes it is my bad, thats why im so hell bent on using a linked list
Still regardless thankyou for the suggestion of the 2D array it should be useful
@BarmakShemirani It is also not really usefull to do this with a linked list, but I guess getting the arrays straight is the first part of it and this should work.
1

You need a linked list in a linked list. Barmak wrote how to get the data. So here is how to get the linked list.

struct sString{ 
char* str;
void* next_hor;
void* next_ver;
};
struct sInt{ 
char* Int;
void* next_hor;
void* next_ver;
};

in first column
if ( check  type of column)
    {for each row
      {
       generate corresponding struct and link it to previous element (add-function) 

      }
    }
for other columns
{
  ( check  type of column)
    {for each row
      {
       generate corresponding struct and link it to previous element (add-function) 
       also iterate though linked list and insert the horizontal link

      }
    }
}

Its very clustered, has tons of overhead and is hard to manage but it should work.

The vertical pointer could also be of the right type as the types don't change in a column.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.