Search code examples
cgetline

Using getline() to read lines from stdin repeatedly and storing them in an array of strings


I'm trying to use the function getline() that is embeded in another function that checks some siple conditions:

int scanItem( char ** list, size_t size ){
    int res = getline( list, &size, stdin );
    if ( res > 5 && res < 100 ){
        return 1;
    }
    return 0;
}

I would like to store every new line that is coming from the stdin stream into a new strings that is in an array of strings. There seems to be a problem though, every time I load the input, the one that was loaded before it is replaced with the new one.

int main(void){
    char ** inputList = (char**)malloc( sizeof(char) * 100 * 100 );
    size_t size = 100*100;

    int i = 0;
    while ( scanItem(&inputList[i], size) == 1 ){
        i++;
    }
    if ( ! feof(stdin) ){
        error();
    }
    return EXIT_SUCCESS;
}

Not sure if I'm using the function correctly...


Solution

  • In order for getline to allocate new pointer for each call, the pointer passed to it needs to point to a NULL. You have

    char ** inputList = (char**)malloc( sizeof(char) * 100 * 100 );
    

    which allocates space for 10000/sizeof(char *) pointers, but doesn't initialize them to anything, so you end up with undefined behavior when getline reads these uninitialized pointers. Instead you want something like

    char ** inputList = calloc(100, sizeof(char *));
    

    to allocate spaces for 100 pointers, and initialize them all to 0. Then for your loop, you want something like:

    int i = 0;
    while ( i < 100 && scanItem(&inputList[i], 0) == 1 ){
        i++;
    }
    

    This ensures you don't run off the end of your list. The size value is not really important as getline will ignore the input value if the pointer is NULL and scanItem will throw away the returned value.