scanf different position in the code in c [duplicate] - c

This question already has answers here:
problem in scanning character in C
(8 answers)
Closed 1 year ago.
int main()
{
char Operator;
int num1, num2, result;
/* printf("Enter operator: ");
scanf("%c", &Operator);*/
printf("Enter first and second value: ");
scanf("%d %d", &num1, &num2);
printf("Enter operator: ");
scanf("%c", &Operator);
if(Operator == '+')
{
result = num1 + num2;
printf("%d\n", result);
}
else if(Operator == '-')
{
result = num1 - num2;
printf("%d\n", result);
}
return 0;
}
I tried making a simple calculator, and I put scanf(the one that requests an Operator) where it is now, and it does not work. But if I put it where the comment is, above the "Enter first and second value" it then works. I would just like to know why does it work on one place and not the other.
Thanks in advance.

As pointed out in comments, Your first scanf is reading the integer values but it's not reading the newline in buffer. When you do scanf("%c", &Operator) again for taking character input, it reads that newline character still present in input buffer. To avoid this, you can use scanf(" %c", %Operator) instead which will discard all whitespace characters before matching character:
printf("Enter operator: ");
scanf(" %c", &Operator);
You can also use fgets() to read input into a string and then use sscanf() to read integers from string:
char input[100];
printf("Enter first and second value: ");
if (fgets(input, 100, stdin) == NULL) {
printf("No input provided!\n");
return -1;
}
if (strchr(input, '\n') == NULL) {
printf("Input Buffer Overflow\n");
return -1;
}
if (sscanf(input, "%d %d", &num1, &num2) != 2) {
printf("Error in reading characters\n");
return -1;
}
printf("Enter operator: ");
if (fgets(input, 100, stdin) == NULL) {
printf("No input provided!\n");
return -1;
}
if (strchr(input, '\n') == NULL) {
printf("Input Buffer Overflow\n");
return -1;
}
if (sscanf(input, "%c", &Operator) != 1) {
printf("Error in reading characters\n");
return -1;
}

From the Open Group Base Specifications Issue,
Input white-space characters (as specified by isspace()) shall be
skipped, unless the conversion specification includes a [, c, C, or n
conversion specifier.
%d format specifier will skip preceding input newline character (\n). That's why it works in the first case (case, where operator was read first) .
scanf leaves an newline character \n in the input buffer, after the first scanf.
The second scanf will read the extra \n from the input buffer to variable Operator. That's why it will not work.
Since the format specifier is %c, the newline character will not be skipped.
Solution : Use scanf(" %c", &Operator);. Add an extra space at the beginning.

Related

if statement unable to check the value

can someone tell me what's wrong with this code. The value is being stored in 'ch' but if statement is unable to validate it.
scanf(" %c", &ch);
if (ch == 4){
printf("Correct Answer \n");
score++;
}
else{
printf("Wrong Answer \n");
}
%c means you are expecting a character.
So a 4 you input, is not an integer 4, but a character '4'.
Simply check for ch == '4'
Note that char is a numeric type, so this will compile and run, but not do what's expected because we've read a char (with format specifier %c into a char variable ch, but then compare it to the number 4 rather than the character '4'.
You should also get in the habit of checking the return value of scanf as a failure to read into ch if it's uninitialized will lead to unexpected behavior.
if (scanf(" %c", &ch) != 1) {
// Something to handle the error.
}
if (ch == '4') {
printf("Correct Answer \n");
score++;
}
else {
printf("Wrong Answer \n");
}

Scanf function skips

In similar questions, the scanf reading a char or string skips because it takes in a new line from the input buffer after the "Enter" key is pressed for the previous scanf, but I don't think that's the issue here. This program does not skip the 2nd scanf if input1 is an integer, but it skips it for other types of inputs (double, char, string, etc.).
#include <stdio.h>
#include <string.h>
int main(){
int input1;
char input2[6];
printf("Enter an integer. ");
scanf("%d", &input1);
printf("You chose %d\n", input1);
printf("Write the word 'hello' ");
scanf(" %s", input2);
if (strcmp(input2,"hello")==0){
printf("You wrote the word hello.\n");
} else {
printf("You did not write the word hello.\n");
}
return 0;
}
Why does this happen?
Comments in code:
int input1 = 0; // Always initialize the var, just in case user enter EOF
// (CTRL+D on unix) (CTRL + Z on Windows)
while (1) // Loop while invalid input
{
printf("Enter an integer. ");
int res = scanf("%d", &input1);
if ((res == 1) || (res == EOF))
{
break; // Correct input or aborted via EOF
}
int c;
// Flush stdin on invalid input
while ((c = getchar()) != '\n' && c != EOF);
}
printf("You chose %d\n", input1);
Also, take a look to How to avoid buffer overflow using scanf
Did you try to write "%*c" after your %c or %s or %d ?
Something like this : scanf("%s%*c", input1);

How to read multiple scanf input in C in one line? say 200 Merck 58.9?

I am new to this, please forgive me if my question has issues.
I would like to read in an integer, a character array (say size 30), and a floating point number in C. How do I read all of it in one line in C, say 200 Merck 58.9? I have tried using scanf consecutively in the following, but the second scanf is not working - the space between input (e.g. 200 Merck 58.9) is causing mayhem.
printf("Please enter an integer, one word string, and a float in one line");
scanf("%i", &any_integer);
scanf("%29s", &any_string); // no spaces - just a one word string
scanf("%f", &any_float);
I would then like to test what the user enters, ensure that the integer and float is positive and not above 50, and in the string ignore anything that is not a character. Here is a start for the integer.
/* Test the input */
while(any_integer < 0 || any_integer > 50)
{
printf("\n*** Invalid integer.\n Please enter a value between 1 and 50:
");
scanf("%i", &any_integer);
}/* end while */
while(any_float < 0)
{
printf("\n*** Invalid float.\n Please enter a positive value: ");
scanf("%f", &any_float);
}/* end while */
I would like to put this setup in an infinite while loop that terminates with 999, but i am struggling with the details laid out above.
Perhaps
char s[30];
int i;
float f;
while (true) {
if (scanf(" %d%29s%f", &i, s, &f) == 3) {
printf("%d%s%F", i, s, f);
} else{
// Sort out incorrect input
// Eat up to the new line
scanf("%*[^\n]");
if (feof(stdin)) {
// Do summat here - break perhaps
}
}
}
is what you require
The problem is you pass the address of any_string, which is incorrect, and may cause undefined behavior is any_string is a pointer to a char array. You should write:
scanf("%29s", any_string);
To improve error handling and improve input control, I suggest you read the line with fgets() and attempt parse with sscanf(). If the format is incorrect, you can restart with a new line:
int i1;
char s1[30];
float f1;
printf("Please enter an integer, one word string, and a float in one line\n");
for (;;) {
char buf[100];
char c;
if (!fgets(buf, sizeof buf, stdin)) {
fprintf(stderr, "premature end of file\n");
exit(1);
}
if (sscanf(buf, "%i%29s%f%c", &i1, s1, &f1, &c) != 4 || c != '\n') {
printf("Invalid input, enter a new line\n");
continue;
}
if (i1 < 0 || i1 > 50 || f1 < 0 || f1 > 50) {
printf("Invalid values: must be between 0 and 50, try again\n");
continue;
}
/* input values are correct */
break;
}
You can just put them in one line like that:
scanf("%i %29s %f", &any_integer, any_string, &any_float);

How to check if scanf() worked fine in C? [duplicate]

This question already has answers here:
Why is scanf() causing infinite loop in this code?
(16 answers)
Closed 7 years ago.
I am trying to see if user enters 3 correct input. If not the loop ask for input again and again until they correct it correctly.
#include <stdio.h>
int main(void) {
int num1,num2;
char str;
int check;
printf("Enter : ");
check = scanf("%d,%d, %c", &num1, &num2, &str);
while (check != 3) {
printf("Enter : ");
check = scanf("%d,%d, %c", &num1, &num2, &str);
}
}
Let's say if I entera, 5.4, c we get an infinite loop. Why is it giving an infinite loop?
There are far more ways to incorrectly use scanf in a loop that proper ones. The primary issue (aside from input or matching failures that are explained in the man page), is failing to empty the input buffer (stdin when reading from a terminal) after a failed conversion. (There is also the issue that the user must enter something.) When a user enters text and presses [Enter] a newline ('\n') is generated and placed in the input buffer to mark the end of line. When you enter a, 5.4, c, 'a' is fine, but 5.4 is not an int and the processing fails:
If processing of a directive fails, no further input is read, and
scanf() returns.
When scanf returns, it leaves the remaining characters in stdin and you loop and attempt to read again. scanf attempts to read what is left in stdin, processing again fails, and the loop continues endlessly.
In this situation the only way to prevent the indefinite loop is to manually empty the input buffer after you call to scanf. Something simple will do:
int c;
...
while (...) {
scanf (...)
while ((c = getchar()) != '\n' && c != EOF) {}
}
This will insure you start with an empty buffer on the next iteration. For example:
#include <stdio.h>
int main (void) {
int num1 ,num2, c;
char str;
while (printf ("\nEnter : ") &&
scanf (" %d, %d, %c%*c", &num1, &num2, &str) != 3) {
printf ("error: invalid input, required: 'int, int, char'\n");
/* empty remaining chars from input buffer */
while ((c = getchar()) != '\n' && c != EOF) {}
}
printf ("\n num1 : %d\n num2 : %d\n str : %c\n\n", num1, num2, str);
return 0;
}
Example Use
$./bin/scanf3
Enter : a
error: invalid input, required: 'int, int, char'
Enter : a, 5.4, c
error: invalid input, required: 'int, int, char'
Enter : 10, 25
error: invalid input, required: 'int, int, char'
Enter : 10, 25, a
num1 : 10
num2 : 25
str : a
note: this does not protect against the user entering nothing (just pressing [Enter]) and the cursor just sitting there blinking as it waits for input. That is an inherent behavior of scanf, part of which is the reason that line-oriented input methods (fgets or getline) are preferable when taking input.
First time scanf() reads the character then it reads the newline (enter/whitespace character ).This character is present in the input buffer and is read by the scanf() function.
So clear the buffer before reading the new user input using fflush(stdin).
EDIT : Tested in windows VS2013.Sorry i dont have Linux. Windows and Linux define the behaviour of fflush() in different way.If you are using in Windows platform :
int main(void) {
int num1, num2;
char str;
int check;
printf("Enter : ");
check = scanf("%d,%d, %c", &num1, &num2, &str);
while (check != 3) {
////Flush the input buffer ////
fflush(stdin);
printf("Enter : ");
check = scanf("%d,%d, %c", &num1, &num2, &str);
}
}
EDIT : this will work in all platforms.
Another simple way is to consume the remaining read line by
while ((c = getchar()) != '\n' && c != EOF);
so now
int main(void) {
int num1, num2;
char str,c;
int check;
printf("Enter : ");
check = scanf("%d,%d, %c", &num1, &num2, &str);
while (check != 3) {
////read the remaining char ////
while ((c = getchar()) != '\n' && c != EOF);
printf("Enter : ");
check = scanf("%d,%d, %c", &num1, &num2, &str);
}
}

scanf reads the wrong char

I need to write a program in C that let's the user choose to draw a rectangle square or print the board he made but everytime after the first input of a shape the program acts as if he entered an invalid character.
printf("please make you decision R-rectangle, S-square, E-end\n");
scanf("%c", &decision);
do
{
if (decision == 'R') {
printf("you chose rectangle! please enter the X start position, Y start position, hieght and width\n");
scanf("%d %d %d %d", &rectMat[0][rectCounter], &rectMat[1][rectCounter], &rectMat[2][rectCounter], &rectMat[3][rectCounter]);
if (rectCounter + 1 < MAX_RECT)
{
if (checkRECT(rectMat[0][rectCounter], rectMat[1][rectCounter], rectMat[2][rectCounter], rectMat[3][rectCounter], areaMat) == 1)
{
drawRECT(rectMat[0][rectCounter], rectMat[1][rectCounter], rectMat[2][rectCounter], rectMat[3][rectCounter], areaMat);
rectCounter++;
}
else
{
printf("we couldn't fit you rectangle\n");
}
}
else
{
printf("you have too many rectangles\n");
}
}
if (decision == 'S')
{
printf("you chose square! please enter the X start position, Y start position and size of the side\n");
scanf("%d %d %d", &sqrMat[0][rectCounter], &sqrMat[1][rectCounter], &sqrMat[2][rectCounter]);
if (sqrCounter<MAX_SQR)
{
if (checkSQR(sqrMat[0][rectCounter], sqrMat[1][rectCounter], sqrMat[2][rectCounter],areaMat)==1)
{
drawSQR(sqrMat[0][rectCounter], sqrMat[1][rectCounter], sqrMat[2][rectCounter], areaMat);
sqrCounter++;
}
else
{
printf("we couldn't fit your square\n");
}
}
else
{
printf("you have too many sqaures\n");
}
}
if (decision == 'P')
{
printArea(areaMat);
}
if (decision != 'E'&& decision != 'P'&& decision != 'S'&& decision != 'R')
{
printf("invalid entry\n");
}
printf("please make you decision R-rectangle, S-square, E-end\n");
scanf("%c", &decision);
} while (decision != 'E');
When you read characters using the "%c" format, it will read the next character in the input buffer, it will not skip any white-space. And when using scanf to read anything, the newline you enter to send the input to the program will also be sent, and added as a white-space character after the end of your input. Most formats do skip leading white-space (like for example the "%d" format), but the "%c" and "%[" formats do not.
When reading character it's almost always advisable to skip leading white-space, which is done by adding a space before the format, like e.g.
scanf(" %c", &decision);
// ^
// |
// Note space here
Also note that there is a difference between upper- and lower-case letters. 'R' != 'r'. Either check for both upper- and lower-case letters, or use toupper (or tolower) to convert.
you better off using getc() instad of scanf() since you're expecting a single char anyway

Resources