Search code examples
cstringmallocc-stringsgets

How to read multiple strings in C one in a line, each containing spaces?


I allocated a 2D array of characters, and while reading strings with no whitespaces between, the code is working fine. When I read them with whitespaces, I'm facing a bug. How do I read all N number of Strings, each in a single line, each one containing whitespaces.

Example input:

Enter total number of Strings : 3

Enter all the 3 Strings :

John Doe

Jane Doe

Trad Braversy

My code:

// Code to enter the total number of Strings : 
int N;
printf("\n\tEnter the total number of Strings : ");
scanf("%d", &N);

// Code for allocating initial memory to them :
char** strings = (char**)malloc(N * sizeof(char*));
for (int i = 0; i < N; ++i) {
    strings[i] = (char*)malloc(1024 * sizeof(char));
}

// Code for entering all the N strings :
printf("\n\tEnter all the %d Strings :\n", N);
for (int i = 0; i < N; ++i) {
    gets(strings[i]);
}

// Code to reallocate the memory according to the entered length :
for (int i = 0; i < N; ++i) {
    strings[i] = (char*)realloc(strings[i], strlen(strings[i]) + 1);
}

Solution

  • A few observations:

    It's safer to read a full line of text, then parse out the integer from that, rather than doing scanf() for a single integer. This is because the latter leaves the newline in the stream, which can confuse later reads.

    There's no real point in using malloc() to do dynamic memory allocation for this, you can use a VLA:

    char strings[N][1024];
    

    Note that using a capital-only symbol for a runtime variable is stylistically strange in C.

    Then, it's much better to use fgets(), it's safer and just better:

    for (int i = 0; i < N; ++i)
    {
      if (fgets(strings[i], sizeof strings[i], stdin) == NULL)
      {
        fprintf(stderr, "**Read error on string %d\n", i);
        exit(1);
      }
    }
    

    And as always, be prepared that I/O can fail, and try to handle that.