The input and output for the following program are given below:
#include<stdio.h>
int main(){
int a=0, b=100, c=200;
scanf("%d,%d,%d",&a,&b,&c);
printf("%d %d %d\n",a,b,c);
return 0;
}
Input-1:
1,2,3
Output-1:
1 2 3
So the first output is correct and as expected.
Input-2:
1 2 3
Output-2:
1 100 200
Here it reads first integer correctly but I am not able to understand, how the scanf() reads the data after first integer when we are not giving the input in specified format?
As values entered after first integer are not assigned to any variables, What happens to those values?
Are they written on some random memory locations?
Here it reads first integer correctly but I am not able to understand,
how the scanf() reads the data after first integer when we are not
giving the input in specified format?
scanf stops at the first mismatch and leaves the rest of the target objects untouched. You can inspect the return value to determine how many "items" scanf matched.
As values entered after first integer are not assigned to any
variables, What happens to those values?
The unmatched data is left in the input buffer, available for a subsequent read using scanf, fgets etc.
I used getchar() and putchar() after last printf() statement in the
program but nothing was read.
Strange. You should be able to get away with something like:
int ch;
while ((ch = getc(stdin)) != EOF)
putchar(ch);
TL;DR answer: It doesn't. It stops reading.
To clarify, input is not in specified format is a matching failure for scanf(). That is why it's always recommended to check the return value of scanf() to ensure all the input items got scanned successfully.
In the second input scenario, the scanf() has failed to scan all the input parameters because of the format mismatch of expected and received inputs [and you have no idea of that]. Only the value of a has been scanned successfully, and reflected.
[Just for sake of completeness of the answer]:
After the input value of a, due to the absence of a , in the input, mismatch happened and scanf() stopped scanning, returning a value of 1. That's why, b and c prints out their initial values.
Related
I'm using a function called checkType to check whether the user has entered a valid input of integer type. For example, if the user enters 15 it will print valid and 15c will print not valid. However, if the user enters a string input only like ccccc, it results in an infinite loop and the program crashes. I have added some screenshots below to show the outputs.
int checkType(int input, char *c) {
if (input == 2 and *c == '\n') {
return 1;
} else {
return 0;
};
}
int main(void) {
int faces = 0;
char c;
int valid = 0;
int input;
while (valid == 0) {
printf("Enter number of faces: ");
input = scanf("%d%c", &faces, &c);
valid = checkType(input, &c);
printf(valid == 0 ? "not valid\n" : "valid\n");
}
}
Infinite Loop:
The scanf() family of functions is not really made for input of questionable syntax.
The usual approach to solve your problem is to read in all the input in a way which is sure to succeed, e.g. by reading a complete line (instead of a number, word-like string, or anything else with expected format) with fgets().
Then you can try to parse that line-representing string as by expected format. (You can use sscanf() for the parsing attempt.) If that fails you ignore it and read the next line, or try parsing according to an alternative allowed format for the same input.
The relevant difference is that reading a whole line will succeed and remove it from the input stream. In contrast to that, your code, in case of syntax failure, leaves in the input stream whatever did not match the expected syntax. As such it will, of course, fail the next iteration of the reading loop again. That is what causes your endless loop.
In detail:
read a whole line into a buffer,
using fgets() and the option to restrict the number of characters to the size of the buffer
at this point all of the line is removed from the input (aka stdin, aka input stream),
which means that the next read will get new input even if the read line does not match any allowed format,
this is the relevant difference to trying to read input directly with scanf()
from the line buffer, attempt to read separate values according to an allowed format,
using sscanf() and with a check of the return value
if successful great, you have your expected variables filled (e.g. an integer);
you could try scanning for additional, not format-covered trailing input (and continue like for incorrect input, even if the beginning of the line matched an allowed format)
if not successful try a different allowed format,
using sscanf() again,
from the same line buffer, which is not changed, not even if a format partially matched
if no allowed format matches the input it is time to consider it incorrect
incorrect input can be ignored or can cause a fatal parsing error in your program, your choice
However, if the user enters a string input only like ccccc,
it results in an infinite loop and the program crashes
Reason : scanf returns the number of valid read values from stdin. If we give cccc as input, scanf cannot read the value, because the input and variable faces are of different data type. This makes input = 0. So the function checkType returns 0, which in turn makes valid = 0. This makes while(valid == 0) always true and hence the endless loop.
Scanf will read form stdin, and not clean the stdin buffer if not match. So it will read wrong data again in your case, you can just add a clean function with stdin after scanf, like: __fpurge(stdin)
You can refer to the following two links:
https://man7.org/linux/man-pages/man3/scanf.3.html
http://c-faq.com/stdio/stdinflush2.html
With input like "ccccc" and scanf("%d%c" ..., there is no conversion to an int. scanf() returns 0 and stdin remains unchanged. Calling the function again has the same result.
Code neds to consume errant input - somehow.
Research fgets() to read a line of user input.
What is the output of this code if I input 25 to scanf()? I run this program, the output is 1 but I don't understand why? Can anyone explain?
#include <stdio.h>
#include <stdlib.h>
int main() {
int i;
printf("%d\n",scanf("%d",&i));
return 0;
}
scanf() returns the number of arguments successfully assigned. In your case, scanf only has one directive which has a respective argument to be assigned, so it returns 1 if the input conversion was done successfully.
1 is given now as argument to printf, which prints 1 into the output.
With the premise that the scanf() conversion was successfully,
printf("%d\n", scanf("%d",&i));
is basically equivalent to
printf("%d\n", 1);
Going straight forward
int i = 0, j = 0;
printf("%d\n", scanf("%d %d", &i, &j));
with the input of
25(enter)
50(enter)
and both conversions done successfully, would gave you the output 2 and
printf("%d\n", scanf("%d %d", &i, &j));
would basically be equivalent to
printf("%d\n", 2);
Side Note:
The return value of scanf() should always be checked by the algorithm but it is more an objective to the program to see if an input failure occurred than to diagnose it directly to the user.
These functions (scanf family) return the number of input items successfully matched and assigned.
So in this case it can return 1 if the scan was successful or 0 if not. If there is an error in the input stream it can also return EOF
Scanf is a basic function in C language.Since every function return a type of value or null,Scanf function returns numbers of inputs scanned successfully.
For Example: Scanf("%d%d") scans for 2 inputs, so it returns value 2.
Scanf("%f%d%d%d") scans for 4 inputs, so it returns value 4.
&variable_name is used to store the scanned value in the variable by using address-of operator.For scanning string, &-address-of operator can be neglible.
Example scanf("%s",variable)
Printf is a function which returns number of characters printed.It can be used with format specifer like %d,%f etc.
In the above program
printf("%d\n",scanf("%d",&i));
Scanf is first executed by scanning one integer input as %d is specified and stored in the variable of type int. Scanf returns value 1 since it is scanning only one input.
Printf function prints the value 1.Printing value does not depend upon input value.It depends only on number of inputs , scanf is scanned successfully.
you are outputting the scanf function which returns the variable numbers not the value in i.
I have wrote the following code using c programming language (Standard 89):
#include <stdio.h>
#include <stdlib.h>
int main()
{
int cc,dd;
scanf("%d/%d",&cc,&dd);
int ll;
scanf("%d",&ll);
printf("Value of ll is: %d",ll);
return 0;
}
If I submit the following as an input in one line: 4/5h I get the following output: Value of ll is: 67
So I have 2 questions;
1) where that 67 value came from? (I tried to change the input to something like 1/2t but got the same result)
According to what I have read since there is no integers in the buffer the application should wait until one is available (For example to wait for a new input)
2) When I run my code using debug mode I can see that ll value is 65 but not 67!
By typing non-digit characters in entries like "5h" or "2t" for dd, you're fouling up the read for ll in the second scanf call.
%d tells scanf to skip any leading whitespace, then to read decimal digit characters up to the first non-digit character. If you type a string like "5h" or "2t", that leading digit will be successfully converted and assigned to dd, but the trailing non-digit character will be left in the input stream, and that's fouling up the read for ll. No new value is being read into ll, you're getting whatever indeterminate value it had when the program started up.
Always check the result of scanf (and fscanf and sscanf) - if it's less than the number of inputs you expect, then you have a matching failure (you're not handling some input correctly). If it's EOF, then you have a failure on the input stream itself.
For this particular case, you can work around the problem by checking the result of scanf - if it's 0, then there's a bad character in the stream. Throw it away and try again:
int r;
while ( ( r = scanf( "%d", &ll ) ) != 1 && r != EOF )
getchar();
This will call scanf and try to read a value into ll. We expect scanf to return a 1 on a successful input, so we'll loop while the result of scanf isn't 1 (and isn't EOF, either). If the read isn't successful, we assume there's a non-digit character stuck in the input stream, so we read and discard it with the getchar call.
I'm really confused about the usage of getchar() and scanf(). What's the difference between these two?
I know that scanf() [and family] get a character by character from the user [or file] and save it into a variable, but does it do that immediately or after pressing something (Enter)?
and I don't really understand this code, I saw many pieces of code using getchar() and they all let you type whatever you want on the screen and no response happen, but when you press enter it quits.
int j, ch;
printf("please enter a number : \n");
while (scanf("%i", &j) != 1) {
while((ch = getchar()) != '\n') ;
printf("enter an integer: ");
}
Here in this code can't I use scanf() to get a character by character and test it? Also, what does this line mean?
scanf("%i", &j) != 1
because when I pressed 1 it doesn't differ when I pressed 2? what does this piece do?
and when this line is gonna happen?
printf("enter an integer: ");
because it never happens.
Well, scanf is a versatile utility function which can read many types of data, based on the format string, while getchar() only reads one character.
Basically,
char someCharacter = getchar();
is equivalent to
char someCharacter;
scanf("%c", &someCharacter);
I am not 100% sure, but if you only need to read one character, getchar() might be 'cheaper' than scanf(), as the overhead of processing the format string does not exist (this could count to something if you read many characters, like in a huge for loop).
For the second question.
This code:
scanf("%i", &j) != 1
means you want scanf to read an integer in the variable 'j'. If read successfully, that is, the next input in the stream actually is an integer, scanf will return 1, as it correctly read and assigned 1 integer.
See the oldest answer to this SO question for more details on scanf return values.
As far as I understand,
the getchar function will read your input one character at a time.
scanf will read all types of data, and will be more useful to define a data group.
However, as far as strings go, my teacher recommends using gets instead of scanf. This is because scanf will stop 'getting' the data at the first white space you put in, like in a sentence...
while (scanf("%i", &j) != 1) {
while((ch = getchar()) != '\n') ;
printf("enter an integer: ");
}
Here's how this code breaks down.
scanf() consumes individual characters from the input stream until it sees a character that does not match the %i conversion specifier1, and that non-matching character is left in the input stream;
scanf() attempts to convert the input text into a value of the appropriate type; i.e., if you enter the string "1234\n", it will be converted to the integer value 1234, the converted value will be assigned to the variable j, and the '\n' will be left in the input stream;
if there are no characters in the input string that match the conversion specifier (such as "abcd"), then no conversion is performed and nothing is assigned to j;
scanf() returns the number of successful conversions and assignments.
if the result of the scanf() call is not 1, then the user did not enter a valid integer string;
since non-matching characters are left in the input stream, we need to remove them before we can try another scanf() call, so we use getchar() to consume characters until we see a newline, at which point we prompt the user to try again and perform the scanf() call again.
1. The %i conversion specifier skips over any leading whitespace and accepts optionally signed integer constants in octal, decimal, or hexadecimal formats. So it will accept strings of the form [+|-]{0x[0-9a-fA-F]+ | 0[0-7]+ | [1-9][0-9]*}
The scanf can scan arbitrarily formatted data and parse it as multiple types (integers, floating point, strings, etc). The getchar function just gets a single character and returns it.
The expression
scanf("%i", &j) != 1
reads a (possibly signed) integer from the standard input, and stores it in the variable j. It then compares the return value of the scanf function (which returns the number of successfully scanned conversions) and compares it to 1. That means the expression will be "true" if scanf didn't read or converted an integer value. So the loop will continue to loop as long as scanf fails.
You might want to check this scanf reference.
That the printf doesn't happen might be either because it never happens (use a debugger to find out), or it just seemingly doesn't happen but it really does because the output needs to be flushed. Flushing output is done either by printing a newline, or with the fflush function:
fflush(stdout);
As far as I know, scanf will read user input until the first whitespace, considering the input format specified. getchar, however, reads only a single character.
scanf will return the number of arguments of the format list that were successfully read, as explained here. You obtain the same result when pressing 1 or 2 because both of them are successfully read by the %i format specifier.
getchar reads one char at a time from input. where as scanf can read more depending upon the data type u specify.
its not good practice to use scanf() try using fgets(), its much more efficient and safe than scanf.
In C programming language the scanf() function reads from keyboard characters or numbers?
For example, if the format is %d and I write "1" or "a", the scanf() reads only integer numbers and ignore other characters?
I have read on a book that the scanf() reads charcters from keyboard, and then converts the characters into data types specified by formats.
Can anyone explain me.
Thanks in advance.
If you look at the function signature of scanf(), it returns an int, which you can use to check whether the scan operation was successful or if it failed:
On success, the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file.
If a reading error happens or the end-of-file is reached while reading, the proper indicator is set (feof or ferror). And, if either happens before any data could be successfully read, EOF is returned.
If an encoding error happens interpreting wide characters, the function sets errno to EILSEQ.
%c is used to read characters
%d is for integers
When you write
scanf("%d",&i)
if i is declared as integer then if you try to print the value of i then it will print integer.
And when you write
scanf("%c",&i)
if i is declared as character then if you try to print the value of i then it will print charcter.
Also check scanf:-
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.
Return Value
On success, the function returns the number of items of the argument
list successfully filled. This count can match the expected number of
items or be less (even zero) due to a matching failure, a reading
error, or the reach of the end-of-file.
If a reading error happens or the end-of-file is reached while
reading, the proper indicator is set (feof or ferror). And, if either
happens before any data could be successfully read, EOF is returned.
If an encoding error happens interpreting wide characters, the
function sets errno to EILSEQ.
Scanning stops when an input character does not match such a format character. Scanning also stops when an input conversion cannot be made
http://www.linuxmanpages.com/man3/scanf.3.php
You are wondering infrastructure details of your communication with the program in a prompt(cmd, terminal etc.) environment i guess. When you write the code like:
int x;
scanf("%d", &x);
and compile and run, program stops and waits for the scanf line to be entered anything to the underlined environment such as cmd or terminal. When you or your user start entering anything from the keyboard, program does nothing maybe buffering. But when you press enter,
program tries to get the characters(up to the whitespace) and convert them to desired variable type that is integer, because you said so in the scanf function parameter. This mentioned conversion happens implicitly. If you wrote:
char str[20];
scanf("%s", str);
and enter some keys from the keyboard, then the underlined behavior of the conversion would be different.
For summary, logic is simple:
if you define varible int, then the program tries to convert to int; if you define float, program tries to convert to float. But all entered keys come from the character sequence and this is called string. I recommend you to read the usage of scanf
and let it go.
scanf() reads charcters fromstdin, and then converts the characters into data types specified by formats. ?
Man page on scanf clearly answers this,
The scanf() family of functions scans input according to format as described
below. This format may contain conversion specifications; the results from such
conversions, if any, are stored in the locations pointed to by the pointer
arguments that follow format. Each pointer argument must be of a type that is
appropriate for the value returned by the corresponding conversion specification.