Read a string of arbitrary size from stdin?

I want to read a line from the console.

Using scanf or fgets, it seems to me that only a fixed maximum size string can be read. Worse, there seems to be no way to check how many characters have been entered in case the user is typing too much (in which case I could just reallocate the array so that the string fits into the array).

I read that I have to read one character at a time in the answer to this question , however I do not know how to read one character at a time when the user does not press enter after each character.

How can i do this?


source to share

5 answers

Try to run this.

#include <stdio.h>

int main(){
    char next;



then check the man page for getchar () to see what really is.



The GCC documentation says that:

The C standard has functions for this, but they are not very safe: empty characters and even (for gets

) long strings can confuse them. Thus, the GNU library provides a non-standard function getline

that makes it easy to read strings reliably.

So what

[ getline

] is a GNU extension, but it is recommended to read lines from the stream. Alternative standard functions are unreliable.

So, if you are using GCC I would say you should be using getline

. If you are not using GCC, you should see if your compiler has a similar feature. If this is not the case; or if you really prefer to use something standard, then you need to read one character at a time.

I don't know how to read one character at a time without pressing a button after each character.

Yes Yes. The user enters a sequence of characters and then presses Enter. Your first call fgetc

will block until the user hits Enter, but after that, subsequent calls fgetc

will return immediately until you read a new line. (It will then block again until the user hits Enter again.) Reading "one character at a time" does not mean that you have to read each character before the user types the next; it simply means that after the user has entered a line, you will read that line one character at a time.



char c = NULL;
while (c != 0x0D)
    scanf("%c", &c);
    // do stuffs with c




You can use fgets()

in a loop and realloc if the last character is not\n

char *buffer;
size_t bufsiz = 100;
size_t buflen = 100;
size_t bufcur = 0;
buffer = malloc(bufsiz);
for (;;) {
    fgets(buffer + bufcur, bufsiz, stdin);
    buflen = bufcur + strlen(buffer + bufcur);
    if (buffer[buflen - 1] == '\n') break;
    tmp = realloc(buffer, bufsiz * 2);
    if (tmp == NULL) /* deal with error */;
    buffer = tmp;
    bufcur = buflen - 1;
    bufsiz *= 2;
/* use buffer (and bufsiz and buflen) */




It should be noted in the accepted answer that getchar () returns an int. The char data type is not large enough to hold EOF.

We could read a given amount of text and then discard the rest of the input. This approach has more than its fair share of critics (how dare we suggest it needs to be discarded). Another option is to use getline or write a custom function. I thought I'd try the last one.

This does not prevent users from filling memory with a large cat file.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#define MAX 50
#define JUSTDO(a) if (!(a)) {perror(#a);exit(1);}
/** char *get_line  FILE *f
 * reads an arbitrarily long line of text or until EOF
 * caller must free the pointer returned after use
char *get_line (FILE *f) {
    int len=MAX;
    char buf[MAX],*e=NULL,*ret;JUSTDO (ret=calloc(MAX,1));
    while (fgets (buf,MAX,f)) {
        if (len-strlen(ret)<MAX) JUSTDO (ret=realloc(ret,len*=2));
        strcat (ret,buf) ;if ((e=strrchr (ret,'\n'))) break;
    } if (e) *e='\0';
    return ret;
/* main */
int main (void) {
    char *s;
    printf ("enter a line of text:\n");
    printf ("line was '%s'\n",s=get_line(stdin)) ;free (s);
    return 0;




All Articles