interesting behaviour when using scanf on string with space in a loop - c

I was fiddling with C and happen to wrote code below. When I input a string with spaces, program receives all of the input but outputs them as if they were inputted as single words at different times. I thought scanf stopped when first whitespace character is encounterd and ignored the rest. But that seems, is not the case.
I included the output when I enter "inputWithNoSpaces" and "input with spaces", below.
I tried to look into stdin. It receives all the input. But I could not figure out what scanf was doing. I would like to learn what is happening.
Code:
#include <stdio.h>
int main()
{
int i=0;
char word[64]="";
while(1)
{
printf("enter string:");
scanf("%s",word);
i++;
printf("%d:%s\n\n",i,word);
}
return 0;
}
Output:
enter string:inputWithNoSpaces
1:inputWithNoSpaces
enter string:input with spaces
2:input
enter string:3:with
enter string:4:spaces
enter string:

In scanf(), "%s" means "skip whitespace characters then read a sequence of non-whitespace characters". So when you give it the input input with spaces it will return "input", "with" and "spaces" in three sequential calls. That is the expected behavior. For more information read the manual page.
input with spaces
^^^^^ First scanf("%s", s) reads this
^ Second scanf("%s", s) skips over this whitespace
^^^^ Second scanf("%s", s) reads this
^ Third scanf("%s", s) skips over this whitespace
^^^^^^ Third scanf("%s", s) reads this

Related

Scanning Only the First Character in C

I know that adding a space in front of %c in scanf() will scan my second character; however, if two letters were inputted in the first character, it will input the second letter into the second character. How do I scan a single character only?
#include <stdio.h>
int main(void)
{
char firstch, secondch;
printf("Enter your first character: ");
scanf("%c", &firstch);
printf("Enter your second character: ");
scanf(" %c", &secondch);
printf("\n Fisrt character : %c \n Second character : %c \n", firstch, secondch);
return 0;
}
This is my result after running:
Enter your first character: ab
Enter your second character:
First character : a
Second character : b
I only want to read the first character 'a', but the second letter 'b' was inputted right away before I enter my second character.
When you are reading a line of user-input, use a line-oriented input function like fgets() or POSIX getline(). That way the entire line of input is read at once and you can simply take the first character from the line. Say you read a line into the array used as buffer called buf, e.g.
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (void) {
char buf[MAXC]; /* buffer to read each line into */
You can simply access the first character as buf[0], or since buf[0] is equivalent to *(but + 0) in pointer notation, you can simply use *buf to get the first character.
As a benefit, since all line-oriented functions read and include the '\n' generated by the user pressing Enter after the input, you can simply check if the first character is '\n' as a way of indicating end-of-input. The user simply presses Enter alone as input to indicate they are done.
Using a line-oriented approach is the recommended way to take user input because it consumes and entire line of input each time and what remains in stdin unread doesn't depend on the scanf conversion specifier or whether a matching failure occurs.
Using " %c%*[^\n]" is not a fix-all. It leaves the '\n' in stdin unread. That's why you need the space before " %c". Where it is insidious is if your next input uses a line-oriented function after your code reading characters is done. Unless you manually empty the '\n' from stdin, before your next attempted line-oriented input, that input will fail because it will see the '\n' as the first character remaining in stdin.
A short example using fgets() for a line-oriented approach would be:
#include <stdio.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
int main (void) {
char buf[MAXC]; /* buffer to read each line into */
for (;;) { /* loop continually */
fputs ("enter char: ", stdout); /* prompt for input */
/* read/validate line, break on EOF or [Enter] alone */
if (!fgets (buf, sizeof buf, stdin) || *buf == '\n')
break;
printf (" got: %c\n\n", *buf); /* output character read */
}
}
Where you simply take input continually isolating the first character as the value you want until the user presses Enter alone to break the read-loop.
Example Use/Output
$ ./bin/fgetschar
enter char: a
got: a
enter char: ab
got: a
enter char: a whole lot of stuff you don't have to deal with using fgets()
got: a
enter char: banannas
got: b
enter char: cantelopes
got: c
enter char:
Look things over and let me know if you have further questions.
Using a space before the %c will skip whitespace before scanning the next non-whitespace character. %c itself just scans a single character -- the next character in the input after whatever else was scanned or skipped previously.
So the question is, what do you want to do? Do you want to skip over all extraneous input on the line after the first character (up to newline?) fgets or scanf("%*[^\n]"); scanf("%c"); will do that (but be careful -- if firstch was itself a newline, this will skip the next line.) Do you want to check the input and make sure it is exactly one character on a line? If so, use fgets (not scanf) and check that the line read is exactly two characters (a character and a newline). Or perhaps you really want to read keystrokes without having the user hit Enter after esch one? That requires changing the input source setup, which is OS dependent.
I'm still new to C coding, and I've found a suitable answer to my problem by using scanf("%*[^\n]");
#include <stdio.h>
int main(void)
{
char firstch, secondch;
printf("Enter your first character: ");
scanf(" %c%*[^\n]", &firstch);
printf("Enter your second character: ");
scanf(" %c%*[^\n]", &secondch);
printf("\n First character : %c \n Second character : %c \n", firstch,
secondch);
return 0;
}
Results after running:
Enter your first character: ab
Enter your second character: c
First character : a
Second character : c
Thanks to #Eraklon #Chris Dodd #David C. Rankin

How do I allow spaces to be read during execution?

The program is to compare the string but however there's a problem with the spacing when I execute it. As I input the first string with spacing, the program just jump to comparing the strings, not allowing me to input the second string as follows:
>>"Enter first string":
"Hello Hey"
">>Enter second string:"
">>First string is more than the second string."
Here is my code:
#include<stdio.h>
#include<string.h>
int main (void) {
int result; //store results
char input1[50];
char input2[50];
printf("Enter first string:\n");
scanf("%[^\n]s",input1);
printf("Enter second string:\n");
scanf("%[^\n]s",input2);
result = strcmp(input1, input2);
if (result==0)
printf("First string is equal to second string\n");
if (result>0)
printf("First string is greater than second string\n");
if (result<0)
printf("First string is less than the second string\n");
return 0;
}
Add spaces:
scanf(" %[^\n]s",input1);
scanf(" %[^\n]s",input2);
It will consume all the white spaces encountered in previous inputs.
When you enter any input, you also enter a new line character (white space) with your input. And that newline character is being read by second scanf in your code.
The Question:
How do I allow spaces to be read during execution? (the question)
You are already doing it using [^\n] in scanf("%[^\n]s",input1); which means to read the input until a new line (\n) is encountered. Also, not that \n itself doesn't get read in this way.
Output:
Enter first string:
Strings in C
Enter second string:
Strings in C
First string is equal to second string
I think you can do it with the stdlib.h with this function:
gets(input1);
gets(input2);
For sure, the POSIX way will work, you can use read to get the line from stdin:
read(STDIN_FILENO, input1, 50)

unexpected output of the following c program

the following code as expected should accept two char values from user. but it just accepts one value of ch1 and then prints "hello".
#include<stdio.h>
int main()
{
char ch1, ch2;
printf("Enter a char: ");
scanf("%c",&ch1);
printf("Enter second char: ");
scanf("%c",&ch2);
printf("Hello");
return 0;
}
it is not accepting the second value for ch2..what can be the possible reason?
As far as i think, it should accept 2 characters.
It just accepts only one char because the the first call to scanf() left a newline in the input stream.
You can ignore it with:
scanf(" %c",&ch2); // note the leading space.
This will ensure the newline from the previous input will be ignored. A white-space in the format string tells scanf() to ignore any number of white-space characters. You might also want to check the return value of scanf() calls in case it failed.
From scanf():
. A sequence of white-space characters (space, tab, newline,
etc.; see isspace(3)). This directive matches any amount of
white space, including none, in the input.

Reading newline from previous input when reading from keyboard with scanf()

This was supposed to be very simple, but I'm having trouble to read successive inputs from the keyboard.
Here's the code:
#include <string.h>
#include <stdio.h>
int main()
{
char string[200];
char character;
printf ("write something: ");
scanf ("%s", string);
printf ("%s", string);
printf ("\nwrite a character: ");
scanf ("%c", &character);
printf ("\nCharacter %c Correspondent number: %d\n", character, character);
return 0;
}
What is happening
When I enter a string (e.g.: computer), the program reads the newline ('\n') and puts it in character. Here is how the display looks like:
write something: computer
computer
Character:
Correspondent number: 10
Moreover, the program does not work for strings with more than one word.
How could I overcome these problems?
First scanf read the entered string and left behind \n in the input buffer. Next call to scanf read that \n and store it to character.
Try this
scanf (" %c", &characte);
// ^A space before %c in scanf can skip any number of white space characters.
Program will not work for strings more than one character because scanf stops reading once find a white space character. You can use fgets instead
fgets(string, 200, stdin);
OP's first problem is typically solved by prepending a space to the format. This will consume white-space including the previous line's '\n'.
// scanf("%c", &character);
scanf(" %c", &character);
Moreover, the program does not work for strings with more than one word. How could I overcome these problems?
For the the 2nd issue, let us go for a more precise understanding of "string" and what "%s" does.
A string is a contiguous sequence of characters terminated by and including the first null character. 7.1.1 1
OP is not entering a string even though "I enter a string (e.g.: computer)," is reported. OP is entering a line of text. 8 characters "computer" followed by Enter. There is no "null character" here. Instead 9 char "computer\n".
"%s" in scanf("%s", string); does 3 things:
1) Scan, but not save any leading white-space.
2) Scan and save into string any number of non-white-space.
3) Stop scanning when white-space or EOF reached. That char is but back into stdin. A '\0' is appended to string making that char array a C string.
To read a line including spaces, do not use scanf("%s",.... Consider fgets().
fgets(string, sizeof string, stdin);
// remove potential trailing \r\n as needed
string[strcspn(string, "\n")] = 0;
Mixing scanf() and fgets() is a problem as calls like scanf("%s", string); fgets(...) leave the '\n' in stdin for fgets() to read as a line consisting of only "\n". Recommend instead to read all user input using fgets() (or getline() on *nix system). Then parse the line read.
fgets(string, sizeof string, stdin);
scanf(string, "%c", &character);
If code must user scanf() to read user input including spaces:
scanf("%*[\n]"); // read any number of \n and not save.
// Read up to 199 `char`, none of which are \n
if (scanf("%199[^\n]", string) != 1) Handle_EOF();
Lastly, code should employ error checking and input width limitations. Test the return values of all input functions.
What you're seeing is the correct behavior of the functions you call:
scanf will read one word from the input, and leave the input pointer immediately after the word it reads. If you type computer<RETURN>, the next character to be read is the newline.
To read a whole line, including the final newline, use fgets. Read the documentation carefully: fgets returns a string that includes the final newline it read. (gets, which shouldn't be used anyway for a number of reasons, reads and discards the final newline.)
I should add that while scanf has its uses, using it interactively leads to very confusing behavior, as I think you discovered. Even in cases where you want to read word by word, use another method if the intended use is interactive.
You can make use of %*c:
#include <string.h>
#include <stdio.h>
int main()
{
char string[200];
char character;
printf ("write something: ");
scanf ("%s%*c", string);
printf ("%s", string);
printf ("\nwrite a character: ");
scanf ("%c%*c", &character);
printf ("\nCharacter %c Correspondent number: %d\n", character, character);
return 0;
}
%*c will accept and ignore the newline or any white-spaces
You cal also put getchar() after the scanf line. It will do the job :)
The streams need to be flushed. When performing successive inputs, the standard input stream, stdin, buffers every key press on the keyboard. So, when you typed "computer" and pressed the enter key, the input stream absorbed the linefeed too, even though only the string "computer" was assigned to string. Hence when you scanned for a character later, the already loaded new line character was the one scanned and assigned to character.
Also the stdout streams need to be flushed. Consider this:
...
printf("foo");
while(1)
{}
...
If one tries to execute something like this then nothing is displayed on the console. The system buffered the stdout stream, the standard output stream, unaware of the fact it would be encounter an infinite loop next and once that happens, it never gets a chance to unload the stream to the console.
Apparently, in a similar manner whenever scanf blocks the program and waits on stdin, the standard input stream, it affects the other streams that are buffering. Anyway, whatsoever may be the case it's best to flush the streams properly if things start jumbling up.
The following modifications to your code seem to produce the desired output
#include <string.h>
#include <stdio.h>
int main()
{
char string[200];
char character;
printf ("write something: ");
fflush(stdout);
scanf ("%s", string);
fflush(stdin);
printf ("%s", string);
printf ("\nwrite a character: ");
fflush(stdout);
scanf ("%c", &character);
printf ("\nCharacter %c Correspondent number: %d\n", character, character);
return 0;
}
Output:
write something: computer
computer
write a character: a
Character a Correspondent number: 97

char Input in C by scanf

Help me Please.
I want to know why it happen.
This code is not give right answer:
#include < stdio.h>
int main()
{
char c,ch;
int i;
printf("Welcome buddy!\n\nPlease input first character of your name: ");
scanf("%c",&c);
printf("\nPlease input first character of your lovers name: ");
scanf("%c",&ch);
printf("\nHow many children do you want? ");
scanf("%d",&i);
printf("\n\n%c loves %c and %c want %d children",c,ch,c,i);
return 0;
}
but this code give right answer.
#include < stdio.h>
int main()
{
char c,ch;
int i;
printf("Welcome buddy!\n\nPlease input first character of your name: ");
scanf(" %c",&c);
printf("\nPlease input first character of your lovers name: ");
scanf(" %c",&ch);
printf("\nHow many children do you want? ");
scanf("%d",&i);
printf("\n\n%c loves %c and %c want %d children",c,ch,c,i);
return 0;
}
Why?
and How?
Please help me anyone who know this why it happend.
While you are giving like this, It will not ignore the white spaces.
scanf("%c",&ch);
When you are giving the input to the first scanf then you will give the enter('\n'). It is one character so it will take that as input to the second scanf. So second input will not get input from the user.
scanf(" %c",&ch);
If you give like this, then it will ignore that white space character, then it will ask for the input from the user.
The first program doesn't work properly, because the scanf function when checking for input doesn't remove automatically whitespaces when trying to parse characters.
So in the first program the value of c will be a char and the value of ch will be the '\n' (newline) char.
Using scanf("\n%c", &varname); or scanf(" %c", &varname); will parse the newline inserted while pressing enter.
The scanf function reads data from standard input stream stdin.
int scanf(const char *format, …);
The white-space characters in format, such as blanks and new-line characters, causes scanf to read, but not store, all consecutive white-space characters in the input up to the next character that is not a white-space character.
Now, when you press, by example, "a" and "return", you have two chars in the stdin stream: a and the \n char.
That is why the second call to scanf assign the \n char to ch var.
your scanf() function takes input from stdin. Now when you hit any character from keyboard and hit enter, character entered by you is scanned by scanf() but still enter is present in stdin which will be scanned by scanf() below it. To ignore white spaces you have to use scanf() with " %c".

Resources