2

I want to read data from user (console). Example data user can give:

0 : [ 83, 42, 7 ]
21:[3, 6, 8, 12, 9, 3, 6, 8, 12]
63 : [ 8, 12, 9, 3, 6, 8 ]
0 : [ 20, 31, 70 ]

Input ends with EOF.

I don't know how long the arrays of integers are (the ones inside []) and how many rows of data there will be. I want to save the array in (integers in the brackets - []) with key which is the first number on the line.

Writing dynamic array is not a problem:

typedef struct {
  int *array;
  size_t used;
  size_t size;
} Array;

void initArray(Array *a, size_t initialSize) {
  a->array = (int *)malloc(initialSize * sizeof(int));
  a->used = 0;
  a->size = initialSize;
}

void insertArray(Array *a, int element) {
  if (a->used == a->size) {
    a->size *= 2;
    a->array = (int *)realloc(a->array, a->size * sizeof(int));
  }
  a->array[a->used++] = element;
}

void freeArray(Array *a) {
  free(a->array);
  a->array = NULL;
  a->used = a->size = 0;
}

and then in int main():

Array messages;
initArray(&messages, 10);    
insertArray(&messages, x); // x is the number we are reading

I can say that the key is the first element in the array.

However I am not sure how to parse the input and fill the messages array. (also would have to save the messages arrays into another array)

Also rows with the same key should be saved into the same array (but this is a detail).

Mykybo
  • 1,429
  • 1
  • 12
  • 24
  • 2
    1) Don't cast the result of `malloc` & friends or `void *` in general. 2) Too broad. What die you try, why did it fail? – too honest for this site Dec 11 '16 at 13:46
  • if `a->size == 0`, you has UB. – Stargateur Dec 11 '16 at 13:58
  • `realloc` can fail, check it against `NULL` – Inline Dec 11 '16 at 14:03
  • What is the maximum array length? No limit? --> Out of luck, as handling lines of a few quintillion or more will certainly be a problem. A sane limit like up to 100 entires --> Good. Step 1 read the line. Step 2 parse the line. – chux - Reinstate Monica Dec 11 '16 at 14:03
  • @chux what function would I use to read line which I don't know the length of? Also, you would read it as string and than parse the string? – Mykybo Dec 11 '16 at 14:04
  • 1
    Reasonable code works with an upper bound, yet generous line length. Allowing endless input opens code to hacker attacks of overwhelming a systems resources. Say up to 1000 numbers are readable, read a line using `char buffer[1000*40]; fgets(...)` and then parse the string `buffer`. Separate user input from string parsing. – chux - Reinstate Monica Dec 11 '16 at 14:07

1 Answers1

1

You can try this:

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

#define LINELEN 100
#define INITSIZE 10

typedef struct {
    int *array;
    int key;
    size_t used;
    size_t currsize;
} line_t;

typedef struct {
    line_t *lines;
    int numlines;
} array_t;

array_t *initialize_array(void);
void generate_line(array_t *A, int index);
void insert_into_array(array_t *A, int index, char *number);
void printfree_array(array_t *A);
void check_ptr(void *ptr, const char *msg);

int
main(int argc, char *argv[]) {
    char line[LINELEN];
    char *key;
    array_t *A;
    size_t arrsize = INITSIZE, count = 0;

    A = initialize_array();

    A->lines = malloc(arrsize * sizeof(line_t));
    check_ptr(A->lines, "Allocation");

    printf("Enter data into console:\n");
    while (fgets(line, LINELEN, stdin) != NULL && strlen(line) != 1) {

        if (arrsize == count) {
            arrsize *= 2;
            A->lines = realloc(A->lines, arrsize * sizeof(line_t));
            check_ptr(A->lines, "Reallocation");
        }

        generate_line(A, count);

        key = strtok(line, " :[],");

        A->lines[count].key = atoi(key);

        while ((key = strtok(NULL,  " :[],\n")) != NULL) {
            insert_into_array(A, count, key);
        }

        count++;
        A->numlines++;
    }

    printfree_array(A);

    return 0;
}

void
printfree_array(array_t *A) {
    int i, j;

    printf("Your array of structures:\n");
    for (i = 0; i < A->numlines; i++) {
        printf("key = %d, ", A->lines[i].key);

        printf("array = [");
        for (j = 0; j < A->lines[i].used; j++) {
            printf("%d", A->lines[i].array[j]);

            if (j != A->lines[i].used-1) {
                printf(", ");
            }
        }
        free(A->lines[i].array);
        printf("]\n");
    }
    free(A->lines);
    free(A);
}

void
insert_into_array(array_t *A, int index, char *number) {
    if (A->lines[index].currsize == A->lines[index].used) {
        A->lines[index].currsize *= 2;
        A->lines[index].array = realloc(A->lines[index].array, 
                                        A->lines[index].currsize * sizeof(int));
        check_ptr(A->lines[index].array, "Reallocation");
    }
    A->lines[index].array[A->lines[index].used++] = atoi(number);
}

void
generate_line(array_t *A, int index) {
    A->lines[index].currsize = INITSIZE;
    A->lines[index].used = 0;
    A->lines[index].key = 0;
    A->lines[index].array = malloc(A->lines[index].currsize * sizeof(int));
    check_ptr(A->lines[index].array, "Allocation");
}

array_t
*initialize_array(void) {
    array_t *A = malloc(sizeof(*A));
    check_ptr(A, "Allocation");

    A->lines = NULL;
    A->numlines = 0;

    return A;
}

void
check_ptr(void *ptr, const char *msg) {
    if (!ptr) {
        printf("Unexpected null pointer: %s\n", msg);
        exit(EXIT_FAILURE);
    }
}

Program output here.

RoadRunner
  • 25,803
  • 6
  • 42
  • 75