How does C++ buffer work(about whitespace)? - c++

Assume that i put ' 123abc' as input in C++ console application.
if i get input as
int a; char ch;
scanf("%d", &a);
scanf("%ch", &ch);
i got 123 in a, 'a' in ch. Right?
Then, where does 4 blanks go? scanf just blow away blanks?
Is there no way can i get that blanks after i get 123abc?
To sum it up my question,
When i get int input with scanf, does scanf blow away blank in buffer?
What does happen i execute that code?
Can i get 4 blanks in ' 123abc' after i get '123' and 'a'?

As others pointed out, you really should read scanf documentation so you can see which specifier will be able to read whitespaces.
Regarding your first question:
When i get int input with scanf, does scanf blow away blank in buffer? What does happen i execute that code?
For numeric inputs, scanf will ignore any whitespace character.
When you execute scanf("%d", &a); it will go over the spaces (or any other whitespace character) until it finds a digit and start reading a decimal integer (as specified by %d).
Regarding your second question:
Can i get 4 blanks in ' 123abc' after i get '123' and 'a'?
I'm not sure what you mean here, you want to read a past value after having gone through the whole buffer?
You won't be able to do this.
If you need the spaces, get them before reading anything else.
Or read the whole buffer into your own buffer and deal with it.
There are many ways to deal with this.
Here's an example:
#include <cstdio>
int main()
{
{
printf( "Reading into your own buffer:\n" );
char my_buffer[128];
scanf( "%127[^\n]%*c", my_buffer ); // the %*c is to throw away the trailing \n
printf( "my_buffer: [%s]\n", my_buffer );
}
{
printf( "Reading each part separately:\n" );
char spaces[5];
int number;
char remaining_chars[4];
scanf( "%4[ ]", spaces );
scanf( "%d", &number );
scanf( "%3s", remaining_chars );
printf( " spaces: [%s]\n", spaces );
printf( " number: [%d]\n", number );
printf( "remaining_chars: [%s]\n", remaining_chars );
}
return 0;
}
And here is a sample run:
Reading into your own buffer:
123abc
my_buffer: [ 123abc]
Reading each part separately:
123abc
spaces: [ ]
number: [123]
remaining_chars: [abc]

I recommend you to read this documentation about scanf.
Whitespace character: the function will read and ignore any whitespace
characters encountered before the next non-whitespace character
(whitespace characters include spaces, newline and tab characters --
see isspace). A single whitespace in the format string validates any
quantity of whitespace characters extracted from the stream (including
none).
and if you wont to read sentence you can use fscanf or getline
EDIT This is how to do it -
scanf(" %[^\n]",str);
the anser is from this qustion here

Related

scanf for only ONE char

I need to be able to detect extraneous input and exit my program.
If I input a string of more than 1 char into scanf("%c", &var); it takes the first letter and stores it into var but the programs continues.
I tried to use if (scanf("%c", &var) != 1) but it returns 1 every time no matter the input so its no difference.
I know other functions like fgets() may be better suited for this but I have been instructed to use the scanf() function.
How should I do this?
When reading user input scanf can take its input from a file, or the console.
When reading from the console, the data becomes available to the program only when a line break is added. This means anything that was typed on the same line, is read.
Imagine I have a maze program, and it wants me to choose which way to go....
while( !atGoalLocation() ) {
printf( "Which direction (f)orward (l)eft (r)ight?\n" );
scanf( "%c", &dir );
processDirection( dir );
}
I could either enter the route through the maze as
f
l
f
r
f
f
Or it may also be correct to enter my input as
flfrff
Depending on your task, they may mean the same thing.
If you want to allow either of these inputs, then make sure you eat the white space by adding " " to the scanf.
if( scanf( " %c", &dir ) == 1 )
If the line break version is the only method you want to accept, then you should separate the lines and then try the scan.
char line[200];
while( fgets( line, sizeof( line ), stdin ) != NULL ){
sscanf( line, "%c", &dir );
Also for C++ we should be using the std::cin and std::cout. However the same complications occur for unread characters on the same line, so I would still use a line based parser.
std::string line;
while( std::getline( std::cin, line ) ){
// here we could parse the line using std::strstream to decode more complext things than a char.
dir = line[0];
You need to add a space before the %c:
scanf(" %c",&var);
And if you just dont want your program to wait for an enter after typing the character, use getch() defined in "conio.h"
c = getch();
OR
In scanf("%c",&var); you could add a newline character \n after %c in order to absorb the extra characters.
scanf("%c\n",&in);

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

scanf - program waits for another like?

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.