scanf - program waits for another like? - c++

In the following program, I expect that after entering a word and hitting the enter key I should immediately see the message printfed out. However, it doesn't happen until I enter some other random word. Why is that?
#include <cstdio>
#include <cstdlib>
using namespace std;
char tictac[17];
int main()
{
scanf("%s\n", tictac);
printf("%s\n", tictac);
return 0;
}

tl;dr: with scanf("%s\n", tictac); you are asking to read a string, ignore all blank characters after it and then a read a new line. The problem is since all blanks are ignored by the first one there should be a at least one non blank character between the first Enter and the second Enter (hence the need for some garbage non-blank input before the second Enter is accepted.).
Here is an example usage of \n with scanf.
char x, y;
scanf("%c", &x);
scanf("%c", &y);
printf("%c %c", x,y);
with this code you will see that entering one character and pressing Enter will directly go to the printf statement. This is because the second scanf reads the carriage return (which itself is a character) in to y.
scanf("\n%c", &y); // This is recommended to do if you have a sequence of scanfs (but not on the first one).
With this one the stray carriage return will be ignored (or matched) with \n. And the correct character will be read to y.
Now when we come to your code
scanf("%s\n", tictac);
%s tells scanf to read until it finds a blank character (space, tab or new line) and then here is the catch ignore all blank spaces till a non blank space character is met. So your scanf will ignore the Enter you pressed when you entered the string. And any blank character that follows it (try entering spaces on the second line and press enter.)
Which means this will work just fine (unlike the char version)
scanf("%s", tictac);
scanf("%s", tictac2);
Actually on Windows
Because "%s" causes the library to read the input string until it
finds some white space, the equivalent format specifier is
"%[^\0x20\t\n]", which instructs the library to read the string until
it encounters a space character (\0x20), a tab character (\t), or a
newline character (\n).
However since you have explicitly asked scanf to match \n
scanf("%s\n", tictac);
^^
it will wait until it gets another \n (after a non blank character) because the first one one was used by %s.

Drop the \n from your scanf call.

There's a good explanation of scanf here. In your case, you should remove the \n from your scanf function.

Related

how scanf handles standard input vs pipelined input

In the following code:
#include <cstdio>
using namespace std;
int N;
char x[110];
int main() {
scanf("%d\n", &N);
while (N--) {
scanf("0.%[0-9]...\n", x);
printf("the digits are 0.%s\n", x);
}
}
when I enter the input through file using command
./a.out < "INPUTFILE"
It works as expected but when I enter the input through std input it delay the printf function.
Why is that?
Input
3
0.1227...
0.517611738...
0.7341231223444344389923899277...
Output through file
the digits are 0.1227
the digits are 0.517611738
the digits are 0.7341231223444344389923899277
output through standard input
the digits are 0.1227
the digits are 0.517611738
The code is from a book, commpetitive programing 3 ch1_02_scanf.cpp.
Because there's an extra \n in your scanf format string, it will read and discard ALL whitespaces (spaces, newlines and tabs, if present). There needs to be an indication of the end of a whitespace sequence, so you should either hit Ctrl-D for EOF, or enter another non-WS character that lets scanf stop.
As Sid S suggests, you cam alternatively change your format string like this:
scanf(" 0.%[0-9]...", x);
The program works because when you redirect its stdin to a file, scanf will know if it reaches EOF and terminates the last input. You need to manually give an EOF when you type from console. That's the difference.
Change the second scanf() line to
scanf(" 0.%[0-9]...", x);

I cant use two scanf function to Enter the letters

Why I cant use two scanf function to Enter the characters
for example
char a;
char b;
printf("a");
scanf("%c", &a);
printf("%c", a);
scanf("%c", &b);
printf("%c", b);
There are many solutions, but I want to know what is the reason why the2 scanf function does not work in characters
When you enter in a single character you're actually sending two characters to the program: the character you pressed and a newline character from when you pressed the Enter key.
Suppose you pressed "s" then Enter. The first scanf would read only the "s", leaving the newline in the input buffer. The second scanf will then immediately read the newline, which is then printed by the second printf.
If you entered two or more characters and pressed Enter, for example "abc" then Enter, the first scanf will read the "a" and the second scanf will immediately read the "b". The "c" and the newline will be left in the buffer when the program exits.
The procedure code of scanf is like that
scanf()
int readCount = 0;
copy data to buffer until newline
clear the keyboard buffer until newline
match the pattern and write to the vargs
for every pattern matched, readCount ++
return readCount;
Since every scanf will try to parse and clear the keyboard buffer until newline. so you cannot type 2 chars in the same line.
You can 2 easy solution for this.
1) scanf( "%c%c", &a, &b )
which is not general purpose
2) std::cin >> a >> b;
which is general purpose, but from my experience, this method is a bit slower than scanf.

skip a specific set of characters scanf is not defined?

I was reading the documentation of scanf function in this page http://en.cppreference.com/w/cpp/io/c/fscanf and I thought I understood it well until I try this
int main(){
char p[100],t[100];
scanf("%s : %s", p, t);
printf("%s %s", p, t);
}
for my input I used test : scanf for me, the result should be test : but I get test scanf where the scanf function skip the : I don't understand why, I think that nowhere explain, can someone explain me?
thanks
From cplusplus.com,
scanf reads data from stdin and stores them according to the parameter format which can only contain a white space character,a non-white space character and format specifier.
Whitespace character: the function will read and ignore any whitespace characters encountered before the next non-whitespace
character (whitespace characters include tab, space and newline).
Non-whitespace character, except format specifier (%): Any character that is not either a whitespace character (blank, newline or tab) or part of a format specifier (which begin with a %
character) causes the function to read the next character from the
stream.
Format specifiers: A sequence formed by an initial percentage sign (%) indicates a format specifier, which is used to specify the
type and format of the data to be retrieved from the stream and stored
into the locations pointed by the additional arguments.
So when you claim,
for my input I used test : scanf for me, the result should be
test : but I get test scanf where the scanf function skip the :
you are interpreting it wrong. scanf should skip the :(colon) or any character that you mention as its parameter. So when you provide an input like test CharachtersToSkip me with following code,
int main()
{
char p[100],t[100];
scanf("%s CharachtersToSkip %s", p, t);
printf("%s %s", p, t);
}
scanf will skip the characters and output only test me
Hope its clear.
if wants the out put "s=>test" only, then why you are print "t=>scanf"
just modify the code like that.
int main()
{
char p[100],t[100];
scanf("%s : %s", p, t);
printf("%s", p);
}
From the man page of scanf()
Matches a sequence of non-white-space characters;
The input string stops at white space or at the maximum field
width, whichever occurs first.
In this case, first %s will get the input until the white space character is occur. So your input is test : scanf. It will get the test for first input. Then it will skip the leading spaces, you are mentioning the : in scanf, so it will skip the colon :. Then get the next string.
For more example , try this code
int main()
{
int a;
scanf("%d ",&a);
printf("a:%d",a);
return 0;
}
In this code, scanf() don't end when you are giving the '\n' after the input.
It will wait for other than white space character occurs.

scanf() doesn't accept whitespace

I need a scanf() call to accept whitespace (no tabs or newlines, just ' ' space glyphs).
char buffer[2048];
scanf(" %2048[0-9a-zA-Z ]s", buffer);
This format specifier I got from the answer to this question:
how-do-you-allow-spaces-to-be-entered-using-scanf
While it accepts the first sequence of input just fine, it terminates where the first whitespace character is, with a null character. What's going on? Am I perhaps using the wrong format?
I should say, I'm using scanf() here because safety isn't a concern; I'm the only person who'll ever use this particular program, and the input is rigidly formatted.
Use scanf("%[^\n]",buffer);. It will accept white space.
Sample program-
int main()
{
char buffer[2048];
printf("Enter the string\n");
scanf("%[^\n]",buffer);
printf("%s\n", buffer);
return 0;
}
output-
root#sathish1:~/My Docs/Programs# ./a.out
Enter the string
abc def ghi ijk
abc def ghi ijk
root#sathish1:~/My Docs/Programs#
Scanf isn't good for dealing with format that you're expecting to have a particular amount of whitespace. From the scanf man page:
White space (such as blanks, tabs, or newlines) in the format string match any amount of white space, including none, in the input.
And:
[
Matches a nonempty sequence of characters from the specified set of
accepted characters; the next pointer must be a pointer to char, and
there must be enough room for all the characters in the string, plus a
terminating NUL character. The usual skip of leading white space is suppressed.
This means you can do something like
scanf("%[^\n]",buffer);
which says: "Read everything but the newline at the end of the string".
Or, if you're wanting to skip the first space, you can do:
scanf("%*[ ]%[^\n]",buffer);
This says "Read but ignore a space character, then read everything else into buffer".
While you can use scanf, if you are reading lines of text, getline is preferred and provides the advantage of dynamic memory allocation (when line = NULL). getline does read/save the newline character, so if that isn't desired, it can be easily stripped. The following example illustrates the point:
#include <stdio.h>
int main (void) {
char *line = NULL;
ssize_t read = 0;
size_t n = 0;
printf ("\nEnter a line of text: ");
read = getline (&line, &n, stdin);
line [read - 1] = 0; /* strip newline from string (optional) */
read--;
printf ("\n read '%zd' characters: '%s'\n\n", read, line);
return 0;
}
output:
./bin/getln
Enter a line of text: this is a line of text with white .. .. space.
read '52' characters: 'this is a line of text with white .. .. space.'
fgets(string, sizeof(string), stdin) will accept or scanf("%[\n]s",string); will accept

Condition in while loop using cin

I have following code
//in main
int x;
while ( cin>>x ){
// code goes here
}
Now,i know that this loop executes untill read to x fails which occurs when type mismatch occurs
So pressing a char lets me to come out of loop as x is of type int and char will not be read from input stream.
But problem is with whitespaces, as they are also not int so why loop does not ends when i press enter or whitespace?
According to The C++ Programming Language Special Edition, $21.9 Advice [5]:
Remember that by default >> skips whitespace; §21.3.2.
And in $21.3.2:
Whitespace is defined as the standard
C whitespace (blank, tab, newline, formfeed, and carriage return) by a call to isspace() as defined
in (§20.4.2).
The comment of #jrok provided the answer.
Hence, as long as the input is a white space cin waits for input which may represent the requested type. It stops if an invalid character is in the stream or - after a valid non white space character has been consumed - the character is a white space.
You might read line by line to detect empty input:
std::string line
while(getline(cin, line)) {
// Note: Omitting the case where the line contains spaces, only.
if(line.empty()) {
// No input;
break;
}
else {
// Parse and process the line.
}
}
Note: If skipping white spaces is disabled, the behavior changes.