1


in one of my C projects I need to read multiple lines. Let's say I expect some list of instructions, so the input might look like this (of course I don't know the maximal length):

1. First do this...
2. After that...
...
n. Finish doing this...

I want to store this data somewhere (in file,..), because afterwards I want to be able search in many similar lists, etc.

I came up with the idea of using cycle and reading one character at the time, and I made this piece of code(bit simplified):

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

int main(int argc, char **argv){

char *stream;
int i=0;

stream = (char *)malloc(sizeof(char)); 
do{
    stream = (char *)realloc(stream,(i+1)*sizeof(char)); // Reallocating memory for next character
    stream[i] = getc(stdin); // Reading from stdin

    if( i>0 && stream[i-1]=='\n' && stream[i]== '\n' ) // Stop reading after hitting ENTER twice in a row
        break;
    i++;
}while(1); // Danger of infinite cycle - might add additional condition for 'i', but for the sake of question unnecessary

printf("%s\n", stream); // Print the result
free(stream); // And finally free the memory
return 0;
}

This piece of code actually works, but it seems to me that this is quite messy solution (the user might want to add more blank lines '\n' to make the list more readable - but then, after changing the 'if' condition there would be the need of hitting the ENTER many times).

alk
  • 69,737
  • 10
  • 105
  • 255
quapka
  • 2,799
  • 4
  • 21
  • 35
  • 1
    If you want it to be cleaner, first write this code using `fgets` with some arbitrary limit. Then, replace `fgets` with your own version which performs dynamic-allocation. That way the loop control logic will be familiar and you'll also get a dynamic allocated version of `fgets` to use elsewhere – Brandin Jan 28 '14 at 19:14
  • 3
    You should also test the return value of `getc` for `EOF` to see whether the input stream has ended. As Brandin said, you can turn your read-and-allocate code into a separate function which you then can use to read and store the lines. It is also a bit expensive to call `realloc` for every char. A better method is to keep separate length and size variables and allocate chunks of a certain size when the length reaches the size. – M Oehm Jan 28 '14 at 20:13
  • 1
    Did you take a look a the `getline()` function: http://man7.org/linux/man-pages/man3/getline.3.html? – alk Jan 28 '14 at 21:18
  • Actually not, but it is getting late here, so I might save it for tomorrow, but thanks! – quapka Jan 28 '14 at 21:33
  • *nix users will be used to the fact that they terminate their input by pressing Ctrl+D. This will end the input stream, so your application would reach EOF on stdin. On Windows the combination is iirc Ctrl+Z, but its use is probably far less common. – MvG Jan 28 '14 at 22:20
  • IMHO, data input buffer size _should_ be limited. Suggest 2x a typical perceived maximum. Extraordinary long input is more often a sign of input error or nefarious users than a genuine limitation. I'd go with @Brandin idea. E. g. [A long name](http://en.wikipedia.org/wiki/Wolfe%2B585,_Senior) – chux - Reinstate Monica Jan 29 '14 at 02:02

0 Answers0