How to read white spaces with scanf - c

Even though I use this condition in scanf("[^\n]s", x), or "%34[^\n]", or %127s, I'm unable to get answers correctly. Is there any problem with the scanf area or in some other part....
#include <stdio.h>
int main()
{
int i = 4;
double d = 4.0;
char s[] = "hello ";
int a;
double b;
unsigned char string_2[100];
scanf("%d",&a);
scanf("%lf",&b);
scanf("%[^\n]s",string_2);
printf("%d",a+i);
printf("\n%lf",d+b);
printf("\n%s",s);
printf("%s",string_2);
return(0);
}

Don't use scanf like that.
In this:
scanf("%lf",&b);
scanf("%[^\n]s",string_2);
The first scanf reads a number from the input, but has to wait for your terminal to give the program a complete line of input first. Assume the user 123, so the program reads 123\n from the OS.
scanf sees the newline that is not part of the number any more, and stops at that leaving the newline in the input buffer (within stdio). The second scanf tries to read something that is not newlines, but can't do that, since the first thing it sees is a newline. If you check the return value of the scanf calls, you'll see that the second scanf returns a zero, i.e. it couldn't complete the conversion you asked for.
Instead, read full lines at a time, with fgets or getline:
#include <stdio.h>
int main(void)
{
char *buf = NULL;
size_t n = 0;
double f;
getline(&buf, &n, stdin);
if (sscanf(buf, "%lf", &f) == 1) {
printf("you gave the number %lf\n", f);
}
getline(&buf, &n, stdin);
printf("you entered the string: %s\n", buf);
return 0;
}
For a longer discussion, see: http://c-faq.com/stdio/scanfprobs.html

Related

2D character array in C [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 3 years ago.
In C:
I'm trying to get char from the user with scanf and when I run it the program don't wait for the user to type anything...
This is the code:
char ch;
printf("Enter one char");
scanf("%c", &ch);
printf("%c\n",ch);
Why is not working?
The %c conversion specifier won't automatically skip any leading whitespace, so if there's a stray newline in the input stream (from a previous entry, for example) the scanf call will consume it immediately.
One way around the problem is to put a blank space before the conversion specifier in the format string:
scanf(" %c", &c);
The blank in the format string tells scanf to skip leading whitespace, and the first non-whitespace character will be read with the %c conversion specifier.
First of all, avoid scanf(). Using it is not worth the pain.
See: Why does everyone say not to use scanf? What should I use instead?
Using a whitespace character in scanf() would ignore any number of whitespace characters left in the input stream, what if you need to read more inputs? Consider:
#include <stdio.h>
int main(void)
{
char ch1, ch2;
scanf("%c", &ch1); /* Leaves the newline in the input */
scanf(" %c", &ch2); /* The leading whitespace ensures it's the
previous newline is ignored */
printf("ch1: %c, ch2: %c\n", ch1, ch2);
/* All good so far */
char ch3;
scanf("%c", &ch3); /* Doesn't read input due to the same problem */
printf("ch3: %c\n", ch3);
return 0;
}
While the 3rd scanf() can be fixed in the same way using a leading whitespace, it's not always going to that simple as above.
Another major problem is, scanf() will not discard any input in the input stream if it doesn't match the format. For example, if you input abc for an int such as: scanf("%d", &int_var); then abc will have to read and discarded. Consider:
#include <stdio.h>
int main(void)
{
int i;
while(1) {
if (scanf("%d", &i) != 1) { /* Input "abc" */
printf("Invalid input. Try again\n");
} else {
break;
}
}
printf("Int read: %d\n", i);
return 0;
}
Another common problem is mixing scanf() and fgets(). Consider:
#include <stdio.h>
int main(void)
{
int age;
char name[256];
printf("Input your age:");
scanf("%d", &age); /* Input 10 */
printf("Input your full name [firstname lastname]");
fgets(name, sizeof name, stdin); /* Doesn't read! */
return 0;
}
The call to fgets() doesn't wait for input because the newline left by the previous scanf() call is read and fgets() terminates input reading when it encounters a newline.
There are many other similar problems associated with scanf(). That's why it's generally recommended to avoid it.
So, what's the alternative? Use fgets() function instead in the following fashion to read a single character:
#include <stdio.h>
int main(void)
{
char line[256];
char ch;
if (fgets(line, sizeof line, stdin) == NULL) {
printf("Input error.\n");
exit(1);
}
ch = line[0];
printf("Character read: %c\n", ch);
return 0;
}
One detail to be aware of when using fgets() will read in the newline character if there's enough room in the inut buffer. If it's not desirable then you can remove it:
char line[256];
if (fgets(line, sizeof line, stdin) == NULL) {
printf("Input error.\n");
exit(1);
}
line[strcpsn(line, "\n")] = 0; /* removes the trailing newline, if present */
This works for me try it out
int main(){
char c;
scanf(" %c",&c);
printf("%c",c);
return 0;
}
Here is a similiar thing that I would like to share,
while you're working on Visual Studio you could get an error like:
'scanf': function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS
To prevent this, you should write it in the following format
A single character may be read as follows:
char c;
scanf_s("%c", &c, 1);
When multiple characters for non-null terminated strings are read, integers are used as the width specification and the buffer size.
char c[4];
scanf_s("%4c", &c, _countof(c));
neither fgets nor getchar works to solve the problem.
the only workaround is keeping a space before %c while using scanf
scanf(" %c",ch); // will only work
In the follwing fgets also not work..
char line[256];
char ch;
int i;
printf("Enter a num : ");
scanf("%d",&i);
printf("Enter a char : ");
if (fgets(line, sizeof line, stdin) == NULL) {
printf("Input error.\n");
exit(1);
}
ch = line[0];
printf("Character read: %c\n", ch);
try using getchar(); instead
syntax:
void main() {
char ch;
ch = getchar();
}
Before the scanf put fflush(stdin); to clear buffer.
The only code that worked for me is:
scanf(" %c",&c);
I was having the same problem, and only with single characters. After an hour of random testing I can not report an issue yet. One would think that C would have by now a bullet-proof function to retrieve single characters from the keyboard, and not an array of possible hackarounds... Just saying...
Use string instead of char
like
char c[10];
scanf ("%s", c);
I belive it works nice.
Provides a space before %c conversion specifier so that compiler will ignore white spaces. The program may be written as below:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char ch;
printf("Enter one char");
scanf(" %c", &ch); /*Space is given before %c*/
printf("%c\n",ch);
return 0;
}
You have to use a valid variable. ch is not a valid variable for this program. Use char Aaa;
char aaa;
scanf("%c",&Aaa);
Tested and it works.

How can I use the "gets" function many times in my C program?

My code:
#include <stdio.h>
#include <math.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char a[10],b[10];
puts("enter");
gets(a);
puts("enter");
gets(b);
puts("enter");
puts(a);
puts(b);
}
return 0;
}
Output:
1
enter
enter
surya (string entered by user)
enter
surya (last puts function worked)
How can I use “gets” function many times in C program?
You should never ever use gets() in your program. It is deprecated because it is dangerous for causing buffer overflow as it has no possibility to stop consuming at a specific amount of characters - f.e. and mainly important - the amount of characters the buffer, a or b with each 10 characters, is capable to hold.
Also explained here:
Why is the gets function so dangerous that it should not be used?
Specially, in this answer from Jonathan Leffler.
Use fgets() instead.
Also the defintion of a and b inside of the while loop doesn´t make any sense, even tough this is just a toy program and for learning purposes.
Furthermore note, that scanf() leaves the newline character, made by the press to return from the scanf() call in stdin. You have to catch this one, else the first fgets() thereafter will consume this character.
Here is the corrected program:
#include <stdio.h>
int main()
{
int t;
char a[10],b[10];
if(scanf("%d",&t) != 1)
{
printf("Error at scanning!");
return 1;
}
getchar(); // For catching the left newline from scanf().
while(t--)
{
puts("Enter string A: ");
fgets(a,sizeof a, stdin);
puts("Enter string B: ");
fgets(b,sizeof b, stdin);
printf("\n");
puts(a);
puts(b);
printf("\n\n");
}
return 0;
}
Execution:
$PATH/a.out
2
Enter string A:
hello
Enter string B:
world
hello
world
Enter string A:
apple
Enter string B:
banana
apple
banana
The most important message for you is:
Never use gets - it can't protect against buffer overflow. Your buffer can hold 9 characters and the termination character but gets will allow the user to typing in more characters and thereby overwrite other parts of the programs memory. Attackers can utilize that. So no gets in any program.
Use fgets instead!
That said - what goes wrong for you?
The scanf leaves a newline (aka a '\n') in the input stream. So the first gets simply reads an empty string. And the second gets then reads "surya".
Test it like this:
#include <stdio.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char a[10],b[10];
puts("enter");
gets(a); // !!! Use fgets instead
puts("enter");
gets(b); // !!! Use fgets instead
puts("enter");
printf("|%s| %zu", a, strlen(a));
printf("|%s| %zu", b, strlen(b));
}
return 0;
}
Input:
1
surya
whatever
Output:
enter
enter
enter
|| 0|surya| 5
So here you see that a is just an empty string (length zero) and that b contains the word "surya" (length 5).
If you use fgets you can protect yourself against user-initiated buffer overflow - and that is important.
But fgets will not remove the '\n' left over from the scanf. You'll still have to get rid of that your self.
For that I recommend dropping scanf as well. Use fgets followed by sscanf. Like:
if (fgets(a,sizeof a, stdin) == NULL)
{
// Error
exit(1);
}
if (sscanf(a, "%d", &t) != 1)
{
// Error
exit(1);
}
So the above code will automatically remove '\n' from the input stream when inputtin t and the subsequent fgets will start with the next word.
Putting it all together:
#include <stdio.h>
int main()
{
int t;
char a[10],b[10];
if (fgets(a,sizeof a, stdin) == NULL)
{
// Error
exit(1);
}
if (sscanf(a, "%d", &t) != 1)
{
// Error
exit(1);
}
while(t--)
{
puts("enter");
if (fgets(a,sizeof a, stdin) == NULL)
{
// Error
exit(1);
}
puts("enter");
if (fgets(b,sizeof b, stdin) == NULL)
{
// Error
exit(1);
}
puts("enter");
printf("%s", a);
printf("%s", b);
}
return 0;
}
Input:
1
surya
whatever
Output:
enter
enter
enter
surya
whatever
Final note:
fgets will - unlike gets - also save the '\n' into the destination buffer. Depending on what you want to do, you may have to remove that '\n' from the buffer.

Return Value of sscanf

I was reading about sscanf and i came across this:
Return Value
Each of these functions [including s_sscanf()] returns the number of fields that are successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of 0 indicates that no fields were assigned. The return value is EOF for an error or if the end of the string is reached before the first conversion.
I am doing error checking for my input file and i wanna make sure i get a valid line so i tried using sscanf but how do i make sure there are no more fields in the line than i expect. So if i have 3 values in a line but i only need two then that is an invalid line for me but when i use sscanf i only read in 2 variables and the rest are ignored. How do i check the entire line making sure there is no garbage in the line but im not sure what to expect so its not like i can add another variable cause the user can input anything. Someone mentioned to me that you can use * in your sscanf function but im not really sure how i haven't been able to find it anywhere where it is being implemented in code.
The scanf() family of functions returns the number of successful assignments made. If code is expecting three input items there is no way to tell from the value returned by sscanf() alone whether three or more input items were provided.
The scanf() functions operate by reading a character, attempting to match that character, making an assignment if applicable, then moving to the next character or returning from the function call. There is a conversion specifier, %n, that stores the number of characters read in this process so far (without incrementing the number of characters read). This conversion specifier can be used to determine if the input has been exhausted by the call to sscanf().
The code below provides a demonstration. Lines of input gathered by fgets() contain a newline, unless the input is too large to fit in the buffer array. Here buffer[] is large enough to store reasonably-sized inputs, but more robust code would handle oversized inputs more carefully. When sscanf() scans the input string, each character is read in turn until a failing match occurs or the end of the string is reached, so the number of read characters expected after matching "%d %d %d %n" is the same as the length of the input string, including any trailing whitespace characters.
#include <stdio.h>
#include <string.h>
#define BUF_SZ 1024
int main(void)
{
char buffer[BUF_SZ];
int x, y, z;
int pos;
printf("Enter three integers: ");
fflush(stdout);
// get user input
if (fgets(buffer, sizeof buffer, stdin) != NULL) {
// first check: does input match 3 integers?
if (sscanf(buffer, "%d %d %d %n", &x, &y, &z, &pos) != 3) {
puts("Incorrectly formatted input");
} else {
// second check: did sscanf() finish at the end of the buffer?
int expected = strlen(buffer);
if (pos != expected) {
puts("Extra input in buffer");
printf("expected = %d, pos = %d\n", expected, pos);
} else {
// everything OK
printf("You entered: %d, %d, %d\n", x, y, z);
}
}
}
return 0;
}
Sample interactions:
>$ ./a.out
Enter three integers: 1 2 3
You entered: 1, 2, 3
>$ ./a.out
Enter three integers: 1 2
Incorrectly formatted input
>$ ./a.out
Enter three integers: 1 2 3 4
Extra input in buffer
expected = 8, pos = 6
If it is desired to disallow even trailing whitespace characters, "%d %d %d%n" can be used instead. Note that in order for this to work, the newline character must be removed from buffer[] so that it is not counted as extra input. One typical way to do this is by using buffer[strcspn(buffer, "\r\n")] = '\0':
int main(void)
{
char buffer[BUF_SZ];
int x, y, z;
int pos;
printf("Enter three integers: ");
fflush(stdout);
// get user input
if (fgets(buffer, sizeof buffer, stdin) != NULL) {
// first check: does input match 3 integers?
if (sscanf(buffer, "%d %d %d%n", &x, &y, &z, &pos) != 3) {
puts("Incorrectly formatted input");
} else {
// remove trailing newline character
buffer[strcspn(buffer, "\r\n")] = '\0';
// second check: did sscanf() finish at the end of the buffer?
int expected = strlen(buffer);
if (pos != expected) {
puts("Extra input in buffer");
printf("expected = %d, pos = %d\n", expected, pos);
} else {
// everything OK
printf("You entered: %d, %d, %d\n", x, y, z);
}
}
}
return 0;
}
You may, first of all, give the conversion specifiers for the values that you are sure must be present, and then add an "assignment-allocation modifier" to capture any remaining input. I am not sure whether you are talking about sscanf, fscanf or scanf; I will just use scanf to illustrate.
The following program reads 2 integers, and places any remaining input in a string variable, the size of which is dynamically allocated:
Update: Using sscanf instead of scanf.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
int a,b;
char *s;
int n;
char src[]="1 2 This is the remainder";
n=sscanf(src,"%d %d %m[^\n]",&a,&b,&s);
if(n>2)
printf("s=%s\n", s), free(s);
return 0;
}
$ ./a.out
s=This is the remainder

fgets() doesn't work as expected in C

Given the following code:
#include <stdio.h>
int main()
{
int testcase;
char arr[30];
int f,F,m;
scanf("%d",&testcase);
while(testcase--)
{
printf("Enter the string\n");
fgets(arr,20,stdin);
printf("Enter a character\n");
F=getchar();
while((f=getchar())!=EOF && f!='\n')
;
putchar(F);
printf("\n");
printf("Enter a number\n");
scanf("%d",&m);
}
return 0;
}
I want a user to enter a string, a character and a number until the testcase becomes zero.
My doubts / questions:
1.User is unable to enter a string. It seems fgets is not working. Why?
2.If i use scanf instead of fgets,then getchar is not working properly, i.e whatever character I input in it just putchar as a new line. Why?
Thanks for the help.
Mixing functions like fgets(), scanf(), and getchar() is error-prone. The scanf() function usually leaves a \n character behind in the input stream, while fgets() usually does not, meaning that the next call to an I/O function may or may not need to cope with what the previous call has left in the input stream.
A better solution is to use one style of I/O function for all user input. fgets() used in conjunction with sscanf() works well for this. Return values from functions should be checked, and fgets() returns a null pointer in the event of an error; sscanf() returns the number of successful assignments made, which can be used to validate that input is as expected.
Here is a modified version of the posted code. fgets() stores input in a generously allocated buffer; note that this function stores input up to and including the \n character if there is enough room. If the input string is not expected to contain spaces, sscanf() can be used to extract the string, leaving no need to worry about the newline character; similarly, using sscanf() to extract character or numeric input relieves code of the burden of further handling of the \n.
#include <stdio.h>
int main(void)
{
int testcase;
char arr[30];
char F;
int m;
char buffer[1000];
do {
puts("Enter number of test cases:");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* handle error */
}
} while (sscanf(buffer, "%d", &testcase) != 1 || testcase < 0);
while(testcase--)
{
puts("Enter the string");
/* if string should not contain spaces... */
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* handle error */
}
sscanf(buffer, "%29s", arr);
printf("You entered: %s\n", arr);
putchar('\n');
puts("Enter a character");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* handle error */
}
sscanf(buffer, "%c", &F);
printf("You entered: %c\n", F);
putchar('\n');
do {
puts("Enter a number");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* handle error */
}
} while (sscanf(buffer, "%d", &m) != 1);
printf("You entered: %d\n", m);
putchar('\n');
}
return 0;
}
On the other hand, if the input string may contain spaces, fgets() can read input directly into arr, but then the stored string will contain a \n character, which should probably be removed. One way of doing this is to use the strcspn() function to find the index of the \n:
#include <string.h> // for strcspn()
/* ... */
puts("Enter the string");
/* or, if string may contain spaces */
if (fgets(arr, sizeof arr, stdin) == NULL) {
/* handle error */
}
/* replace newline */
arr[strcspn(arr, "\r\n")] = '\0';
printf("You entered: %s\n", arr);
putchar('\n');
/* ... */
Note that a maximum width should always be specified when using %s with the scanf() functions to avoid buffer overflow. Here, it is %29s when reading into arr, since arr can hold 30 chars, and space must be reserved for the null terminator (\0). Return values from sscanf() are checked to see if user input is invalid, in which case the input is asked for again. If the number of test cases is less than 0, input must be entered again.
Finally got the solution how can we use scanf and fgets together safely.
#include <stdio.h>
int main()
{
int testcase,f,F,m;
char arr[30];
scanf("%d",&testcase);
while((f=getchar())!=EOF && f!='\n')
;
while(testcase--)
{
printf("Enter the string\n");
fgets(arr,30,stdin);
printf("Enter a character\n");
F=getchar();
while((f=getchar())!=EOF && f!='\n')
;
putchar(F);
printf("\n");
printf("Enter a number\n");
scanf("%d",&m);
while((f=getchar())!=EOF && f!='\n')
;
}
}
We need to make sure that before fgets read anything,flushout the buffer with simple while loop.
Thanks to all for the help.
A simple hack is to write a function to interpret the newline character. Call clear() after each scanf's
void clear (void){
int c = 0;
while ((c = getchar()) != '\n' && c != EOF);
}
Refer to this question for further explaination: C: Multiple scanf's, when I enter in a value for one scanf it skips the second scanf

How to read a integer followed by a string in C? [duplicate]

This question already has an answer here:
How to read / parse input in C? The FAQ
(1 answer)
Closed 6 years ago.
I am trying to write a simple program which will read two input lines, an integer followed by a string. However, it doesn't seem to work for me.
int main()
{
int i;
char str[1024];
scanf("%d", &i);
scanf("%[^\n]", str);
printf("%d\n", i);
printf("%s\n", str);
return 0;
}
Immediately after entering the integer and pressing "Enter", the program prints the integer. It doesn't wait for me to enter the string. Whats wrong? Whats the correct way to program this?
What you need to know
The problem with %[^\n] is that it fails when the first character to be read is the newline character, and pushes it back into the stdin.
The Problem
After you enter a number for the first scanf, you press Enter. %d in the first scanf consumes the number, leaving the newline character ('\n'), generated by the Enter keypress, in the standard input stream (stdin). %[^\n] in the next scanf sees this \n and fails for the reason given in the first paragraph of this answer.
Fixes
Solutions include:
Changing scanf("%d", &i); to scanf("%d%*c", &i);. What %*c does is, it scans and discards a character.
I wouldn't recommend this way because an evil user could trick the scanf by inputting something like <number><a character>\n, ex: 2j\n and you'll face the same problem again.
Adding a space (any whitespace character will do) before %[^\n], i.e, changing scanf("%[^\n]", str); to scanf(" %[^\n]", str); as #Bathsheba mentioned in a comment.
What the whitespace character does is, it scans and discards any number of whitespace characters, including none, until the first non-whitespace character.
This means that any leading whitespace characters will be skipped when inputting for the second scanf.
This is my recommendation: Clear the stdin after every scanf. Create a function:
void flushstdin(void)
{
int c;
while((c = getchar()) != '\n' && c != EOF);
}
and call it after every scanf using flushstdin();.
Other issues:
Issues unrelated to your problem include:
You don't deal with the case if scanf fails. This can be due to a variety of reasons, say, malformed input, like inputting an alphabet for %d.
To do this, check the return value of scanf. It returns the number of items successfully scanned and assigned or -1 if EOF was encountered.
You don't check for buffer overflows. You need to prevent scanning in more than 1023 characters (+1 for the NUL-terminator) into str.
This can be acheived by using a length specifier in scanf.
The standards require main to be declared using either int main(void) or int main(int argc, char* argv[]), not int main().
You forgot to include stdio.h (for printf and scanf)
Fixed, Complete Program
#include <stdio.h>
void flushstdin(void)
{
int c;
while((c = getchar()) != '\n' && c != EOF);
}
int main(void)
{
int i;
char str[1024];
int retVal;
while((retVal = scanf("%d", &i)) != 1)
{
if(retVal == 0)
{
fputs("Invalid input; Try again", stderr);
flushstdin();
}
else
{
fputs("EOF detected; Bailing out!", stderr);
return -1;
}
}
flushstdin();
while((retVal = scanf("%1023[^\n]", str)) != 1)
{
if(retVal == 0)
{
fputs("Empty input; Try again", stderr);
flushstdin();
}
else
{
fputs("EOF detected; Bailing out!", stderr);
return -1;
}
}
flushstdin();
printf("%d\n", i);
printf("%s\n", str);
return 0;
}
This simply, will work:
scanf("%d %[^\n]s", &i, str);
Instaed of scanf() use fgets() followed by sscanf().
Check return values of almost all functions with a prototype in <stdio.h>.
#include <stdio.h>
int main(void) {
int i;
char test[1024]; // I try to avoid identifiers starting with "str"
char tmp[10000]; // input buffer
// first line
if (fgets(tmp, sizeof tmp, stdin)) {
if (sscanf(tmp, "%d", &i) != 1) {
/* conversion error */;
}
} else {
/* input error */;
}
// second line: read directly into test
if (fgets(test, sizeof test, stdin)) {
size_t len = strlen(test);
if (test[len - 1] == '\n') test[--len] = 0; // remove trailing ENTER
// use i and test
printf("i is %d\n", i);
printf("test is \"%s\" (len: %d)\n", test, (int)len);
} else {
/* input error */;
}
return 0;
}

Resources