Using Scanf after getchar? - c

I am taking C programming course. I did not understand these codes.
#include <stdio.h>
int main()
{
int c;
int ival;
printf("type : ");
c = getchar();
scanf("%d", &ival);
printf("c = %d\n", c); //65
printf("ival = %d\n", ival); //127
return 0;
}
For example whenever I type Abc, I am getting c = 65; ival = 1.
why ival is 1?

ival is never initialized, so it can have any value. The reason is that, c is receiving 'A' (through getchar()) and then scanf fails to read a number (since the next character in the input, 'b', is not a decimal number), so it never touches ival.
You can check the return value of scanf to see if it fails or succeeds:
if (scanf("%d", &ival) != 1)
printf("you need to enter a number\n");
else
printf("entered: %d\n", ival);
Note that scanf returns the number of items it successfully read and assigned. For example scanf("%d %f %c", ...) would return 3 if all three items were correctly read.1
1Note that assigned means that ignored input (such as those with the assignment-suppresion modifier (*)) doesn't count towards the return value of scanf (C11, 7.21.6.2.10,16). Furthermore, %n doesn't affect the return value of scanf (C11, 7.21.6.2.12).

With Abc, getchar() will read A, thus, c will hold the character code for A, which happens to be 65 on your machine (this is the ascii code for A).
For ival, you can get anything: since %d on scanf() expects to read an integer, and you didn't provide one, scanf() returned prematurely, leaving bc in the input buffer, so the value you read from ival when you call printf() is undefined: it can print anything.

The reason is that your program invokes undefined behavior.A is read by getchar while bc is left unread by scanf because %d expects to read an integer and hence on encountering the character it stop reading immediately and leave ival uninitialized.

Related

Why my program doesn't allow me to input b?

I want to input valors for a and b, being a an int and b a str. When I run my program I can input a valor, but then it ingnores printf() and gets() for b.
#include<stdio.h>>
int main()
{
int a;
char b[5];
printf("Write a:\n");
scanf("%i", &a);
printf("Write b:\n");
gets(b);
printf("a = %i, b = %s", a, b);
return 0;
}
In the end, it just prints:
a = (valor written), b =
I don't know what's wrong with this, neither if it's a different way to get this working. I'm pretty new with C. Thank you in advance. ;)
The function gets is unsafe and is not supported by the C Standard. Instead use either scanf or fgets.
As for your problem then after this call of scanf
scanf("%i", &a);
the input buffer contains the new line character '\n' that corresponds to the pressed key Enter. And the following call of gets reads an empty string by encountering the new line character.
Instead of using gets write
scanf( " %4[^\n]", b );
Pay attention to the leading space in the format string. It allows to skip white space characters as for example the new line character '\n'. And the call of scanf can read a string with maximum length equal to 4. If you want to read a larger string then enlarge the array b and the field width specifier in the format string.

(C) Scanf - input gets 0 every time

Each time i set a value in b after a, the value is reset to 0 in a.
In other words, as the code goes, no matter what i input in a it will be always 0 after the second scanf function.
EDIT: I need to use b as char type for the essay, for memory efficiency, so i can't set b to int, but i need to input integer in there.
EDIT2: I need to input an integer in b, example for an input:
1
2
from that point if i
printf("%d",a);
i get 0.
unsigned short a;
char b;
scanf("%hu",&a);
scanf("%d",&b);
You are using the wrong format specifier with
scanf("%d", &b);
It should be
scanf("%c", &b);
However since there is a previous scanf statement there is a newline still in the buffer, and to filter that out you can use
scanf(" %c", &b);
Most format specifiers automatically filter out leading whitespace but %c and %[] and %n do not.
It is unclear from the mistake whether the format specifier is at fault, or the variable type.
%d requires an int:
int b;
Then, you should check the return value of your scanf() calls. Do both calls return 1?
(scanf() returns the number of input items assigned. Because both your calls have one %..., you must return 1 in both cases.)
with char b; and scanf("%d",&b);, scanf will write sizeof (int) bytes to b.
This will corrupt other memory.
scanf("%hhd",&b); will only write one byte to b.

getchar not working in switch case (c)

Using a very simple calculator program that prompts a user for an operation to perform, followed by a prompt for two integers on which to perform this operation. The program is supposed to loop after these operations, except in the case where the user enters the character 'q', at which point the program is supposed to quit.
#include <stdio.h>
int main (void)
{
char c;
int number[2], num1, num2, result;
double num1d, num2d, resultd;
int done=1;
while(done)
{
printf("\t What sort of operation would you like to perform? \n \t Type + - * / accordingly. \n");
c = getchar();
printf("\tplease enter a number \n");
scanf("%d",&number[0]);
printf("\tplease enter another number \n");
scanf("%d",&number[1]);
num1 = number[0];
num2 = number[1];
switch(c)
{
case('-'):
result = num1-num2;
printf("\nThe first number you entered subtracted by the second number is %d.\n", result);
break;
case('+'):
result = num1+num2;
printf("The first number you entered added to the second number is %d.\n", result);
break;
case('*'):
result = num1*num2;
printf("The first number you entered multiplied with the second number is %d.\n", result);
break;
case('/'):
num1d = (double) num1;
num2d = (double) num2;
resultd = num1d/num2d;
printf("The first number you entered divided by the second number is %g.\n", resultd);;
break;
case('q'):
printf(" Now Exiting...\n");
done=0;
break;
default:
puts("Invalid key pressed. Press q to exit");
break;
}
}
return 0;
}
Works correctly for a single calculation, but subsequently performs oddly; in particular it prints
printf("\t What sort of operation would you like to perform? \n \t Type + - * / accordingly. \n");
printf("\tplease enter a number \n");
altogether.
The standard method of clearing the input buffer while (getchar() != '\n'); doesn't fix this. One out of two times that this text displays incorrectly the user can still use the program as if the instructions were displaying as they should (so the user can type an operation such as +, carriage return, and then some integer and a carriage return, and the program will perform correctly from that point on) Every other time however the program will put "Invalid key pressed. Press q to exit" regardless of input.
What everyone else here is saying is true, getchar() returns an int but that's not your problem.
The problem is that getchar() leaves a newline character after you use it. If you're going to use getchar() you must always consume the newline char afterwards. This simple fix:
printf("\t What sort of operation would you like to perform? \n \t Type + - * / accordingly. \n");
c = getchar();
getchar(); //<-- here we do an extra getchar for the \n
printf("\tplease enter a number \n");
scanf("%d",&number[0]);
printf("\tplease enter another number \n");
scanf("%d",&number[1]);
and that will eliminate the problem. Every time you type <somechar><enter> it's really putting two characters on the buffer, for example if I hit + and enter I'm getting:
'+''\n' // [+][\n]
getchar() will only get the first of these, then when getchar() is called again it won't wait for your input it will just take that '\n' and move on to the scanf()
You shouldn't mix character-by-character with more high-level input functions such as scanf(). It's better to use scanf() to input the command character too, but of course then you will have to press enter after the command. I believe this it the root cause of your problems.
As an aside, note that getchar(), despite it's name, returns int, not char. This is because it can return EOF which is a special constant whose value is different from that of all characters.
Further, you should always check the return value of I/O functions like scanf(), they can fail if the input doesn't match the pattern string.
As a debugging hint, you can of course print the value of c before interpreting it, so you can easier see and understand the flow of the program.
I'm guessing it works the first time, but not the next time. This is because the scanf calls leaves the newline in the input buffer so the next time getchar is called in the loop it will return the newline character. Add a space after the format in the scanf calls
scanf("%d ",&number[0]);
and it will discard remaining whitespace from the buffer.
Use a debugger to step through the code and check the variables to verify.
Your getchar should return int. The reason is as below
getchar reads characters from the program's standard input
and returns an int value suitable for storing into a char.
The int value is for one reason only: not only does getchar
return all possible character values, but it also returns an
extra value to indicate that end-of-input has been seen.
The range of a char might not be enough to hold this extra value,
so the int has to be used.
So basically you need to change char c to int c in your code

How can I get the data entered by the user in C using scanf?

//get choice input
int n;
scanf ("%d",&n);
// print the option that the user entered i.e. you chose option 2
printf("you chose option %n /n" ,n);
Sorry for the newbie question; I haven't done C coding before!
There are two problems. First %n is (horrifyingly) an output item; it writes to a pointer to int - and you don't provide it with a pointer to int, so you invoke undefined behaviour. Use %i or %d (most usually %d) for a plain (signed) integer.
You also won't see the printf() output until you output a newline, or the program terminates, because you mistyped the newline escape sequence (it is \n, not /n). Thus, your code
printf("you chose option %n /n" ,n);
should be revised to:
printf("you chose option %d\n", n);
Finally (for now), you should also validate the return value from scanf(); if it tells you it failed to convert anything, you should not try using n:
if (scanf("%d", &n) == 1)
printf("you chose option %d\n", n);
else
printf("Oops - failed to read an integer from your input\n");
Note that if the user typed 'a' (say), then no amount of retrying to read the integer will work. You probably need to gobble up the rest of the line of input:
else
{
printf("Oops - failed to read an integer from your input\n";
int c;
while ((c = getchar()) != EOF && c != '\n')
;
}
Now it is safe to go back and try again.
The only problem i see with that code is the descriptor from printf. It should be %d. Also is \n not /n for the new line ( but that doesn't cause any problems). So try this:
#include <stdio.h>
void main()
{
//get choice input
int n;
scanf ("%d",&n);
// print the option that the user entered i.e. you chose option 2
printf("you chose option %d \n" ,n);
}

Inputting float into a program that only deals with ints

I have a program, but when I input float numbers whenever the program asks for inputs, the program abruptly skips a step and moves onto the end output. The program is below:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,b,c;
int i;
printf("Please enter a number: ");
scanf("%d", &a);
printf("Please enter a number: ");
scanf("%d", &b);
c = 0;
for(i=0; i < b; i++)
{
c = c + a;
}
printf("%d x %d = %d\n", a, b, c);
return 0;
}
When I input an int for a, and a float for b, the program will output the product as expected if the numbers after the decimal point for b is truncated. However when I input a float for a, the program doesn't take the value for the second number b and instead skips that step and outputs the integer version of a x -858993460 = 0.
For example:
a = int, b = float
Please enter a number: 3
Please enter a number: 5.6
3 x 5 = 15
a = float, b = skipped
Please enter a number 3.9
Please enter a number: 3 x -858993460 = 0
All the flaws in the code are deliberate, but I just wanted to know why it behaves the way I explained above. I know it's because of something to do with trying to input a float into a signed integer but I'm not sure what exactly is causing it to skip the second scanf("%d", &b). Can anyone explain why this happens?
Thanks.
It looks like scanf() is reading your "3" in the second case, and ignoring the "9".
Then when the second scanf() is called, there is already text in the input buffer (the ".9").
I can't tell exactly what it's doing with the ".9". It may have found the dot and just aborted there with b uninitialized. It should be a simple matter to determine what is happening by stepping through with the debugger.
But, basically, not all the input is being processed by the first call to scanf() and so that's what the second call is trying to read. And that's why it's not waiting for you to input any data for the second call.
Console input is line buffered; when you enter 3.9 into a %d format specifier, only the 3 is consumed, the remaining data remains buffered, so the second scanf() call attempts to convert it according to its specifier, it finds a '.' and aborts the conversion leaving b undefined.
scanf() will continue to "fall-through" until the '\n' at the end of the input data is consumed. You can do this thus:
printf("Please enter a number: ");
scanf("%d", &a);
while( getchar() != '\n' ) { /* do nothing */ }
printf("Please enter a number: ");
scanf("%d", &b);
while( getchar() != '\n' ) { /* do nothing */ }
Note that if the format specifier is %c, a modification of the "flush" code is required, because the converted character may already be '\n' :
scanf("%c", &c);
while( c != '\n' && getchar() != '\n' ) { /* do nothing */ }
If the next character that is to be read cannot be converted under the current format as specified by the Format Specifier, scanf stops scanning and storing the current field and it moves to the next input field (if any).
And that particular character is treated as unread and used as the first character of next input field or any subsequent read operation.
In the example given above, it is scanning 3 and then cannot resolve . to the format specifier "%d". Hence it stores 3 in variable a leaving .9 as unread. The control when passes to the next scanf statement, it scans ., but again as it cannot resolve . to format specifier "%d", it skips the input scanning for that field.
Now as variable b was not assigned, it contains some garbage value. And any arithmetic operation with garbage values result into garbage values.

Resources