What is the simplest way to read a full line in a C console program The text entered might have a variable length and we can't make any assumption about its content.
14 Answers
You need dynamic memory management, and use the fgets
function to read your line. However, there seems to be no way to see how many characters it read. So you use fgetc()
:
char * getline(void) {
char * line = malloc(100), * linep = line;
size_t lenmax = 100, len = lenmax;
int c;
if(line == NULL)
return NULL;
for(;;) {
c = fgetc(stdin);
if(c == EOF)
break;
if(--len == 0) {
len = lenmax;
char * linen = realloc(linep, lenmax *= 2);
if(linen == NULL) {
free(linep);
return NULL;
}
line = linen + (line - linep);
linep = linen;
}
if((*line++ = c) == '\n')
break;
}
*line = '\0';
return linep;
}
Warning: Never use gets()
! It does not do bounds checking and can overflow your buffer.

- 10,486
- 9
- 18
- 34

- 496,577
- 130
- 894
- 1,212
-
Caveat - need to check result of realloc there. But if that fails, then there are worse problems most likely. – Tim Nov 24 '08 at 15:24
-
4You could probably improve the efficiency a bit by doing fgets with buffer, and checking if you have the newline character at the end. If you don't, realloc your accumulation buffer, copy into it, and fgets again. – Paul Tomblin Nov 24 '08 at 15:27
-
Paul, what guarantees me that there is a newline or '\0' at the end if fgets doesn't need more space? it could have read less than the buffer size. A wait. you mean using strlen to find the \0 and looking before it? Well wasn't sure what is faster. So i did go with this char-by-char way. – Johannes Schaub - litb Nov 24 '08 at 15:37
-
@litb: this is C, not C++. There are no exceptions (in the C++ sense) and no concept of exception-safety. – Adam Rosenfield Nov 24 '08 at 15:51
-
dammit. randomly looking at it again, i found there are silly mistakes in teh code. i hope it's fixed now. – Johannes Schaub - litb Nov 24 '08 at 16:42
-
Don't forget to make the "100" into a constant or a #DEFINE in actual use. – Paul Fisher Nov 24 '08 at 17:19
-
OMG, why do you want to reinvent the wheel? Especially if the result is square wheels. http://www.google.com/codesearch?q=function:getline+lang:c&hl=en&btnG=Search+Code – jfs Nov 24 '08 at 20:17
-
Sebastian, are you aware that is not a Standard C function? It's a GNU extension. – Johannes Schaub - litb Nov 24 '08 at 22:03
-
and, before i copy some random function from the internetz, i better write a function that works and whose caveats i know about. :) – Johannes Schaub - litb Nov 26 '08 at 17:20
-
3This function needs a correction: the line "len = lenmax;" after the realloc should either precede the realloc or should be "len = lenmax >> 1;" -- or some other equivalent that accounts for the fact that half the length is already used. – Matt Gallagher Jul 26 '10 at 07:41
-
1@Johannes, in answer to your question, @Paul's approach COULD be faster on most (i.e. reentrant) libc implementations, since your approach implicitly locks stdin for every character whereas his locks it once per buffer. You could use the less portable `fgetc_unlocked` if thread safety is not a concern but performance is. – vladr Apr 10 '12 at 16:02
-
Is it possible for `fgetc( stdin )` to get EOF value? – NGix Nov 22 '12 at 22:19
-
@NGix Apologies for the late response, which you've probably already found: Yep. `fgetc(stdin)` can return `EOF`, particularly when `stdin` is piped from a file or the user presses a key combination that closes `stdin` (e.g. CTRL+d on Linux or CTRL+z on Windows). – autistic Aug 11 '15 at 12:06
-
One thing I do wonder about is the efficiency of this vs. something like `fgets()`. The answer's highly upvoted, so are they roughly equivalent? – Panzercrisis Sep 29 '15 at 02:04
-
7Note that this `getline()` is different from the POSIX standard [`getline()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html) function. – Jonathan Leffler Apr 12 '17 at 05:42
-
@vladr: One option would be to add [`flockfile()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/flockfile.html) before the first I/O operation and then ensure that it calls `funlockfile()` before any return, while using `fgetc_unlocked()`. This uses the speed of the unlocked calls without sacrificing thread-safety. All the POSIX functions that use a `FILE *` must do the equivalent of this (`flockfile()` plus `funlockfile()`) anyway — see the referenced specification. – Jonathan Leffler Apr 12 '17 at 05:53
-
Hardly the simplest way. – MKaama Sep 27 '17 at 16:03
-
Why introduce linen without freeing it creating a memory leak? you could have just used `linep = realloc(linep,lenmax*2);` ? – rmoro Sep 27 '18 at 16:55
If you are using the GNU C library or another POSIX-compliant library, you can use getline()
and pass stdin
to it for the file stream.

- 730,956
- 141
- 904
- 1,278

- 4,390
- 23
- 18
A very simple but unsafe implementation to read line for static allocation:
char line[1024];
scanf("%[^\n]", line);
A safer implementation, without the possibility of buffer overflow, but with the possibility of not reading the whole line, is:
char line[1024];
scanf("%1023[^\n]", line);
Not the 'difference by one' between the length specified declaring the variable and the length specified in the format string. It is a historical artefact.

- 730,956
- 141
- 904
- 1,278
So, if you were looking for command arguments, take a look at Tim's answer. If you just want to read a line from console:
#include <stdio.h>
int main()
{
char string [256];
printf ("Insert your full address: ");
gets (string);
printf ("Your address is: %s\n",string);
return 0;
}
Yes, it is not secure, you can do buffer overrun, it does not check for end of file, it does not support encodings and a lot of other stuff. Actually I didn't even think whether it did ANY of this stuff. I agree I kinda screwed up :) But...when I see a question like "How to read a line from the console in C?", I assume a person needs something simple, like gets() and not 100 lines of code like above. Actually, I think, if you try to write those 100 lines of code in reality, you would do many more mistakes, than you would have done had you chosen gets ;)

- 3,297
- 5
- 35
- 45
-
1THis doesn't allow for long strings... - which I think is the crux of his question. – Tim Nov 24 '08 at 15:17
-
3
-
-
You should probably delete this answer or edit it before it kills your rep if you are concerned about that... – Tim Nov 24 '08 at 15:26
-
9On the other hand if you are writing a program for yourself and just need to read an input this is perfectly fine. How much security a program needs is par tof the spec - you don't HAVe to put it as a priority everytime. – Martin Beckett Nov 24 '08 at 15:56
-
4
-
7Downvoted. `gets` exists no more, thus this does not work in C11. – Antti Haapala -- Слава Україні Apr 01 '16 at 06:58
-
2If this even goes _anywhere near_ a production environment, end-users will get either cross or hacked. This is not a good function to ever use. – wizzwizz4 Feb 13 '17 at 20:33
getline
runnable example
getline
was mentioned on this answer but here is an example.
It is POSIX 7, allocates memory for us, and reuses the allocated buffer on a loop nicely.
Pointer newbs, read this: Why is the first argument of getline a pointer to pointer "char**" instead of "char*"?
main.c
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *line = NULL;
size_t len = 0;
ssize_t read = 0;
while (1) {
puts("enter a line");
read = getline(&line, &len, stdin);
if (read == -1)
break;
printf("line = %s", line);
printf("line length = %zu\n", read);
puts("");
}
free(line);
return 0;
}
Compile and run:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out
Outcome: this shows on therminal:
enter a line
Then if you type:
asdf
and press enter, this shows up:
line = asdf
line length = 5
followed by another:
enter a line
Or from a pipe to stdin:
printf 'asdf\nqwer\n' | ./main.out
gives:
enter a line
line = asdf
line length = 5
enter a line
line = qwer
line length = 5
enter a line
Tested on Ubuntu 20.04.
glibc implementation
No POSIX? Maybe you want to look at the glibc 2.23 implementation.
It resolves to getdelim
, which is a simple POSIX superset of getline
with an arbitrary line terminator.
It doubles the allocated memory whenever increase is needed, and looks thread-safe.
It requires some macro expansion, but you're unlikely to do much better.

- 347,512
- 102
- 1,199
- 985
-
What is the purpose of `len` in here, when read provides the length too – Honinbo Shusaku Mar 31 '17 at 19:32
-
1@Abdul see `man getline`. `len` is the length of the existing buffer, `0` is magic and tells it to allocate. Read is number of chars read. The buffer size could be larger than `read`. – Ciro Santilli OurBigBook.com Mar 31 '17 at 19:40
You might need to use a character by character (getc()) loop to ensure you have no buffer overflows and don't truncate the input.

- 20,184
- 24
- 117
- 214
As suggested, you can use getchar() to read from the console until an end-of-line or an EOF is returned, building your own buffer. Growing buffer dynamically can occur if you are unable to set a reasonable maximum line size.
You can use also use fgets as a safe way to obtain a line as a C null-terminated string:
#include <stdio.h>
char line[1024]; /* Generously large value for most situations */
char *eof;
line[0] = '\0'; /* Ensure empty line if no input delivered */
line[sizeof(line)-1] = ~'\0'; /* Ensure no false-null at end of buffer */
eof = fgets(line, sizeof(line), stdin);
If you have exhausted the console input or if the operation failed for some reason, eof == NULL is returned and the line buffer might be unchanged (which is why setting the first char to '\0' is handy).
fgets will not overfill line[] and it will ensure that there is a null after the last-accepted character on a successful return.
If end-of-line was reached, the character preceding the terminating '\0' will be a '\n'.
If there is no terminating '\n' before the ending '\0' it may be that there is more data or that the next request will report end-of-file. You'll have to do another fgets to determine which is which. (In this regard, looping with getchar() is easier.)
In the (updated) example code above, if line[sizeof(line)-1] == '\0' after successful fgets, you know that the buffer was filled completely. If that position is proceeded by a '\n' you know you were lucky. Otherwise, there is either more data or an end-of-file up ahead in stdin. (When the buffer is not filled completely, you could still be at an end-of-file and there also might not be a '\n' at the end of the current line. Since you have to scan the string to find and/or eliminate any '\n' before the end of the string (the first '\0' in the buffer), I am inclined to prefer using getchar() in the first place.)
Do what you need to do to deal with there still being more line than the amount you read as the first chunk. The examples of dynamically-growing a buffer can be made to work with either getchar or fgets. There are some tricky edge cases to watch out for (like remembering to have the next input start storing at the position of the '\0' that ended the previous input before the buffer was extended).

- 2,618
- 19
- 20
How to read a line from the console in C?
Building your own function, is one of the ways that would help you to achieve reading a line from console
I'm using dynamic memory allocation to allocate the required amount of memory required
When we are about to exhaust the allocated memory, we try to double the size of memory
And here I'm using a loop to scan each character of the string one by one using the
getchar()
function until the user enters'\n'
orEOF
characterfinally we remove any additionally allocated memory before returning the line
//the function to read lines of variable length
char* scan_line(char *line)
{
int ch; // as getchar() returns `int`
long capacity = 0; // capacity of the buffer
long length = 0; // maintains the length of the string
char *temp = NULL; // use additional pointer to perform allocations in order to avoid memory leaks
while ( ((ch = getchar()) != '\n') && (ch != EOF) )
{
if((length + 1) >= capacity)
{
// resetting capacity
if (capacity == 0)
capacity = 2; // some initial fixed length
else
capacity *= 2; // double the size
// try reallocating the memory
if( (temp = realloc(line, capacity * sizeof(char))) == NULL ) //allocating memory
{
printf("ERROR: unsuccessful allocation");
// return line; or you can exit
exit(1);
}
line = temp;
}
line[length] = (char) ch; //type casting `int` to `char`
length++;
}
line[length + 1] = '\0'; //inserting null character at the end
// remove additionally allocated memory
if( (temp = realloc(line, (length + 1) * sizeof(char))) == NULL )
{
printf("ERROR: unsuccessful allocation");
// return line; or you can exit
exit(1);
}
line = temp;
return line;
}
Now you could read a full line this way :
char *line = NULL; line = scan_line(line);
Here's an example program using the scan_line()
function :
#include <stdio.h>
#include <stdlib.h> //for dynamic allocation functions
char* scan_line(char *line)
{
..........
}
int main(void)
{
char *a = NULL;
a = scan_line(a); //function call to scan the line
printf("%s\n",a); //printing the scanned line
free(a); //don't forget to free the malloc'd pointer
}
sample input :
Twinkle Twinkle little star.... in the sky!
sample output :
Twinkle Twinkle little star.... in the sky!

- 5,287
- 3
- 20
- 37
-
Unlike other answers, works on GCC , windows 10, compiled as C11 , 64bit. – KANJICODER May 17 '21 at 03:54
I came across the same problem some time ago, this was my solutuion, hope it helps.
/*
* Initial size of the read buffer
*/
#define DEFAULT_BUFFER 1024
/*
* Standard boolean type definition
*/
typedef enum{ false = 0, true = 1 }bool;
/*
* Flags errors in pointer returning functions
*/
bool has_err = false;
/*
* Reads the next line of text from file and returns it.
* The line must be free()d afterwards.
*
* This function will segfault on binary data.
*/
char *readLine(FILE *file){
char *buffer = NULL;
char *tmp_buf = NULL;
bool line_read = false;
int iteration = 0;
int offset = 0;
if(file == NULL){
fprintf(stderr, "readLine: NULL file pointer passed!\n");
has_err = true;
return NULL;
}
while(!line_read){
if((tmp_buf = malloc(DEFAULT_BUFFER)) == NULL){
fprintf(stderr, "readLine: Unable to allocate temporary buffer!\n");
if(buffer != NULL)
free(buffer);
has_err = true;
return NULL;
}
if(fgets(tmp_buf, DEFAULT_BUFFER, file) == NULL){
free(tmp_buf);
break;
}
if(tmp_buf[strlen(tmp_buf) - 1] == '\n') /* we have an end of line */
line_read = true;
offset = DEFAULT_BUFFER * (iteration + 1);
if((buffer = realloc(buffer, offset)) == NULL){
fprintf(stderr, "readLine: Unable to reallocate buffer!\n");
free(tmp_buf);
has_err = true;
return NULL;
}
offset = DEFAULT_BUFFER * iteration - iteration;
if(memcpy(buffer + offset, tmp_buf, DEFAULT_BUFFER) == NULL){
fprintf(stderr, "readLine: Cannot copy to buffer\n");
free(tmp_buf);
if(buffer != NULL)
free(buffer);
has_err = true;
return NULL;
}
free(tmp_buf);
iteration++;
}
return buffer;
}

- 10,263
- 1
- 38
- 72
-
1Your code would become MUCH simpler if you use `goto` to handle the error case. Nevertheless, don't you think you could reuse `tmp_buf`, instead of `malloc`ing it with the same size over and over in the loop? – Shahbaz Jul 19 '12 at 08:50
-
Using a single global variable `has_err` to report errors makes this function thread-unsafe and less than comfortable to use. Don't do it that way. You already indicate an error by returning NULL. There is also room to think that the printed error messages are not a good idea in a general-purpose library function. – Jonathan Leffler Apr 30 '18 at 17:30
There is a simple regex like syntax that can be used inside scanf to take whole line as input
scanf("%[^\n]%*c", str);
^\n tells to take input until newline doesn't get encountered. Then, with %*c, it reads newline character and here used * indicates that this newline character is discarded.
Sample code
#include <stdio.h>
int main()
{
char S[101];
scanf("%[^\n]%*c", S);
printf("%s", S);
return 0;
}

- 521
- 5
- 21
-
1+1. What an elegant answer! Small extra: if one needs to use `scanf_s()` instead of `scanf()`, then a third argument is required. The safest command would be `scanf_s("%[^\n]%*c", S, (unsigned)_countof(S));` – Ronald Souza Jan 09 '23 at 16:17
On BSD systems and Android you can also use fgetln
:
#include <stdio.h>
char *
fgetln(FILE *stream, size_t *len);
Like so:
size_t line_len;
const char *line = fgetln(stdin, &line_len);
The line
is not null terminated and contains \n
(or whatever your platform is using) in the end. It becomes invalid after the next I/O operation on stream.

- 7,227
- 3
- 36
- 39
-
Yes, the function exists. The caveat that it does not provide a null-terminated string is sufficiently large and problematic that it is probably better not to use it — it's dangerous. – Jonathan Leffler Apr 30 '18 at 17:28
Something like this:
unsigned int getConsoleInput(char **pStrBfr) //pass in pointer to char pointer, returns size of buffer
{
char * strbfr;
int c;
unsigned int i;
i = 0;
strbfr = (char*)malloc(sizeof(char));
if(strbfr==NULL) goto error;
while( (c = getchar()) != '\n' && c != EOF )
{
strbfr[i] = (char)c;
i++;
strbfr = (void*)realloc((void*)strbfr,sizeof(char)*(i+1));
//on realloc error, NULL is returned but original buffer is unchanged
//NOTE: the buffer WILL NOT be NULL terminated since last
//chracter came from console
if(strbfr==NULL) goto error;
}
strbfr[i] = '\0';
*pStrBfr = strbfr; //successfully returns pointer to NULL terminated buffer
return i + 1;
error:
*pStrBfr = strbfr;
return i + 1;
}
The best and simplest way to read a line from a console is using the getchar() function, whereby you will store one character at a time in an array.
{
char message[N]; /* character array for the message, you can always change the character length */
int i = 0; /* loop counter */
printf( "Enter a message: " );
message[i] = getchar(); /* get the first character */
while( message[i] != '\n' ){
message[++i] = getchar(); /* gets the next character */
}
printf( "Entered message is:" );
for( i = 0; i < N; i++ )
printf( "%c", message[i] );
return ( 0 );
}

- 17
- 5
Here is a minimal implementation to do it, the nice thing is that it will not keep the '\n', however you have to give it a size to read for security:
#include <stdio.h>
#include <errno.h>
int sc_gets(char *buf, int n)
{
int count = 0;
char c;
if (__glibc_unlikely(n <= 0))
return -1;
while (--n && (c = fgetc(stdin)) != '\n')
buf[count++] = c;
buf[count] = '\0';
return (count != 0 || errno != EAGAIN) ? count : -1;
}
Test with:
#define BUFF_SIZE 10
int main (void) {
char buff[BUFF_SIZE];
sc_gets(buff, sizeof(buff));
printf ("%s\n", buff);
return 0;
}
NB: You are limited to INT_MAX to find your line return, which is more than enough.

- 9,682
- 8
- 54
- 81