What is the most accurate way to read strings from the keyboard in C, when the string contains spaces in between words? When I use scanf for that purpose then it doesn't read a string with spaces.The second option is to use gets but it is supposed to be harmful(I also want to know why?).Another thing is that I don't want to use any file handling concept like fgets.
-
2How is the string input into the system? By the user? From a file? From TTY? Over a socket? This is too broad... – RedX Jan 09 '17 at 10:28
-
By user through keyboard – Nirmal_stack Jan 09 '17 at 10:30
-
3You probably want `fgets`. – Jabberwocky Jan 09 '17 at 10:30
-
1Why don't you "want to use any file handling concept like fgets"? Do you know [getline](https://linux.die.net/man/3/getline)? – Bob__ Jan 09 '17 at 10:31
-
1Concerning `gets`: Read [this So article](http://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) – Jabberwocky Jan 09 '17 at 10:31
-
31. If you don't want to use `fgets` you will have to reimplement it, poorly. 2. There is no keyboard in the C language. – n. m. could be an AI Jan 09 '17 at 10:35
-
It is never safe to use scanf and gets function to read a string. Please use fgets to read from the standard input(Keyboard). – Vimal Bhaskar Jan 09 '17 at 10:59
-
@VimalBhaskar "It is never safe to use scanf" --- not true. "and gets" --- **there's no gets**. It is removed from the language precisely because it is never safe. The scanf family will remain a part of the language. – n. m. could be an AI Jan 09 '17 at 12:20
-
@n.m scanf has its own demerits. Please read the following reference documents and earlier stackoverlow issues ..http://c-faq.com/stdio/scanfprobs.html – Vimal Bhaskar Jan 09 '17 at 12:30
-
@VimalBhaskar scanf may be inconvenient or inappropriate for some tasks, but it's far from never being safe. – n. m. could be an AI Jan 09 '17 at 12:40
-
Buffer overflow maybe a serious issue for the above case. If you think buffer overflow is not a serious issue then i will rephrase my answer to "scanf() is inappropriate for some scenarios and gets() is unsafe". Thank you. – Vimal Bhaskar Jan 09 '17 at 12:47
4 Answers
These are 2 ways to read strings containing spaces that don't use gets
or fgets
You can use
getline
(POSIX 2008 may not exist in your system) that conveniently manages allocation of the buffer with adequate size to capture the whole line.char *line = NULL; size_t bufsize = 0; size_t n_read; // number of characters read including delimiter while ((n_read = getline(&line, &bufsize, stdin)) > 1 && line != NULL) { // do something with line }
If you absolutely want
scanf
, in this example it reads to the end of line unless the line has more than the specified number of chars minus 1 for the delimiter. In the later case the line is truncated and you'll get the remaining chars in the nextscanf
invocation.char line[1024]; while (scanf("%1023[^\n]\n", line) == 1) { // do something with line }
I should also point out that when you read strings from the keyboard with scanf
for example, you are actually reading from a file with file pointer stdin
. So you can't really avoid "any file handling concept"

- 21,608
- 12
- 74
- 82
-
The size in the format doesn't include the terminating null byte. The number in the format should be 1023. – Jonathan Leffler Jan 09 '17 at 11:57
@user3623265,
Please find a sample program which Uses fgets to read string from standard input.
Please refer some sample C documents as to how fgets can be used to get strings from a keyboard and what is the purpose of stdin.
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[80];
int i;
printf("Enter a string: ");
fgets(str, sizeof(str), stdin);
i = strlen(str) - 1;
if (str[i] == '\n')
str[i] = '\0';
printf("This is your string: %s", str);
return 0;
}

- 748
- 1
- 5
- 17
-
1What happens if I *immediately* press `^D` on your prompt? (I am on a Linux-like system, so "you get a string containing `^D`" is not a valid answer.) – Jongware Jan 09 '17 at 11:13
-
I have given him a basic example as to how to read from keyboard instead of using scanf() and gets function. Basically there are multiple ways to avoid the display of EOF(Ctrl+D). The question asked was regarding the effectiveness of using scanf() or gets or some other function. Hence out of these two my opinion/i preferred fgets() . If what I have expressed/explained is wrong then please do correct me as i am open to learn here. That is why i have joined this community. – Vimal Bhaskar Jan 09 '17 at 11:26
-
2I mentioned it because it will lead to an input string with a length of **0**, and `strlen(str)-1` will attempt to access memory it's not allowed to. You should always check the return result of `fgets`, which *specifically* checks for [end of input with no characters entered](https://linux.die.net/man/3/fgets). – Jongware Jan 09 '17 at 11:43
-
Check with this: `i = strlen(str); if ( i > 0) { if (str[i-1] == '\n'.........`. If that `if` statement is not true, then buffer overflow has occurred. – RoadRunner Jan 09 '17 at 16:28
There is a third option, you can read the raw data from stdin
with the read()
call:
#include <unistd.h>
int main(void) {
char buf[1024];
ssize_t n_bytes_read;
n_bytes_read = read(STDIN_FILENO, buf, sizeof(buf) - 1);
if (n_bytes_read < 0) {
// error occured
}
buf[n_bytes_read] = '\0'; // terminte string
printf("\'%s\'", buf);
return 0;
}
Please not that every input is copied raw to buf
including the trailing return. That is, if you enter Hello World
you will get
'Hello World
'
as output. Try online.

- 1,424
- 1
- 15
- 10
If you insist on not having a FILE * in scope, use getchar().
char buff[1024];
int ch;
int i = 0;
while( (ch = getchar()) != '\n' )
if(i < 1023)
buff[i++] = ch;
buff[i] = 0;
/* now move string into a smaller buffer */
Generally however it's accepted that stdout and stdin and FILE * are available. Your requirement is a bit odd and, since you are obviously not an advanced C programmer who has an unusual need to suppress the FILE * symbol, I suspect your understanding of C IO is shaky.

- 6,258
- 1
- 17
- 18