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

#define BUF_SIZE 1024

int main ()
{
    char buffer[BUF_SIZE];
    int contentSize = 1; 

    char* content = (char*)malloc(sizeof(char) * BUF_SIZE);
    content[0] = '\0';

    while(fgets(buffer, BUF_SIZE, stdin))
    {
        contentSize = contentSize + strlen(buffer);
        content = (char*)realloc(content, contentSize);
        strcat(content, buffer);
    }

    return 0;
 }

im trying to read in everything entered by the user (even whitespace characters) and i am pretty close to getting it to work but the loop never ends. fgets() just keeps asking for more input, how do i fix this please.

Noam M
  • 3,156
  • 5
  • 26
  • 41
user2756746
  • 11
  • 1
  • 4
  • As you said in a comment below, you are using Windows (that information would be worth putting into the question :-). - Did you try the "F6" key for EOF? Compare http://stackoverflow.com/questions/10589637/having-troubles-with-eof-on-windows-7. – Martin R Sep 08 '13 at 09:16
  • yes that worked! interesting, thanks – user2756746 Sep 08 '13 at 09:27
  • Possible duplicate of [Having troubles with EOF on Windows 7](http://stackoverflow.com/questions/10589637/having-troubles-with-eof-on-windows-7) – Martin R Sep 08 '13 at 09:42

3 Answers3

3

fgets() returns the pointer to the buffer (which is desirably not a NULL pointer) that you passed to it, until it can't read more lines from the file.

Of course, if reading from the standard input, it will always wait for another line, so you have to explicitly send an EOF to the terminal so that it reports end-of-file. You can do it by pressing <ctrl> + <D>, for example.

  • 3
    + in most *nixes i've seen; + in Windows. – cHao Sep 08 '13 at 08:43
  • I just tried that, i put [Control]+D at the end of some random characters and it still asks for more input. im using windows 8. ctrl+z also doesnt work. – user2756746 Sep 08 '13 at 08:44
  • 2
    @user2756746: You may have to make sure it's on a line by itself. – cHao Sep 08 '13 at 08:47
  • that didn't work either. I think the best approach is what Manoj Pandey said. – user2756746 Sep 08 '13 at 08:50
  • @user2756746 You are surely missing something. There's a facility to send EOF in the terminal of every modern operating system. Even in that of Windows. Manoj's approach is acceptable if you can come up with such a magic "exit" word, but if your input is potentially going to be arbitrary, then it isn't correct. –  Sep 08 '13 at 09:07
  • If I remember correctly, the F6 key simulates EOF in the Windows terminal application, compare http://stackoverflow.com/questions/10589637/having-troubles-with-eof-on-windows-7. – Martin R Sep 08 '13 at 09:13
  • im using microsoft visual studio terminal, maybe that is why ? – user2756746 Sep 08 '13 at 09:19
  • but getting the user to type ctrl+z is more confusing then getting them to type 'quit' after they entered their arbitrary input. – user2756746 Sep 08 '13 at 09:21
0

One way would be to have the user input certain keyword (like quit or quit()) and then break out of the while loop.

while(fgets(buffer, BUF_SIZE, stdin)) {
           contentSize = contentSize + strlen(buffer);
           content = (char*)realloc(content, contentSize);
           strcat(content, buffer);
           if (strncmp(buffer, "quit", strlen("quit")) == 0) {
               break;
           }
}
Manoj Pandey
  • 4,528
  • 1
  • 17
  • 18
  • 1
    For a program that expects to run interactively (ie: expects stdin to be a terminal), this is a little less ugly (once the quit-in-the-buffer thing is fixed) than requiring the user to key in an EOF character. One can easily conceive of a situation where you'd *want* to have a line saying "quit", though. You'd need to provide some way to do that. – cHao Sep 08 '13 at 08:39
  • The quit being in the buffer can be fixed by doing the comparison before you realloc and copy. – cHao Sep 08 '13 at 08:45
  • this is more difficult than i imagined. what if i just use a for loop? would that work – user2756746 Sep 08 '13 at 08:47
  • It is certainly tricky.. But some of the interactive programs do run this way. For example, in Python, you can type "quit()" to exit. Likewise, gdb prompt (iirc) also can be exited using quit keyword. Now, you would need to check if given your use-case, would it be common for the user to input a keyword like "quit()" as a normal input data? If that is not very common, then you can specify in the beinning that the user can enter "quit()" in one line to end the program. – Manoj Pandey Sep 08 '13 at 08:56
0

The loop never ends because OP did not close stdin. Once stdin is closed and all data is read, fgets() will return NULL.

@H2CO3 solution is on target, but OP may have missed some windows subtleties.

A <Ctrl>+<Z> will signal an EOF if the input buffer is empty AND it is followed by Enter. Example A, B, C, Enter, now an empty buffer, <Ctrl>+<Z>, Enter.

If the input buffer all ready has data in it, a <Ctrl>+<Z> is read as <Ctrl>+<Z>(ASCII 26).

The "quit" idea, has merits, but a user could still enter <Ctrl>+<Z>, Enter. The code should be ready for that. (The posted "quit" answer does that.) I suggest avoiding magic words - unless its "relinquo codicem".

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256