I'm writing to understand as much as I can of the following program that I tried to compute, because I thought it had some possible application for everyday life.
The program goes like this (it's a cypher):
#include <stdio.h>
void cifrario(int k) {
char b, d;
scanf("%c", &d);
d = getchar();
putchar(d);
scanf("%c", &b);
b = getchar();
while (b != d) {
if (('A' <= b && b <= 'Z') || ('a' <= b && b <= 'z')) {
b = b + k;
printf("%c", b);
scanf("%c", &b);
b = getchar();
} else
printf("%c", b);
}
}
int main() {
int h;
scanf("%d", &h);
cifrario(h);
return 0;
}
As you can see, I'm trying to shift the alphabet of a certain constant given in input.
The things I'm not quite understanding and I'm not quite aware of, are why the program should not function without a scanf
or getchar
, and both are necessary on the same value, let's say here:
scanf("%c", &d);
d = getchar();
I thought the two were totally equivalent; in fact searching on the internet I found this as far as concerns getchar
:
This function returns the character read as an
unsigned char
cast to anint
orEOF
on end of file or error.
That's what I expected scanf()
did.
I have found that:
if I put all the character without spaces I'm getting (I think) just a shift of the same character for double letter instead of two.
the else
in the while
doesn't work as expected because as soon I put a different character from the alphabetic ones and see the outcome the output fail in an infinite string of that character.
A simple type specifier consists of a percent (%) symbol and an alpha character that indicates the type. Below are a few examples of the type specifiers recognized by scanf: %c — Character. %d — Signed integer.
Space before %c removes any white space (blanks, tabs, or newlines). It means %c without space will read white sapce like new line(\n), spaces(' ') or tabs(\t). By adding space before %c, we are skipping this and reading only the char given.
In scanf() you usually pass an array to match a %s specifier, then a pointer to the first element of the array is used in it's place. For other specifiers like %d you need to pass the address of the target variable to allow scanf() to store the result in it.
Definition. scanf is a C function to read input from the standard input until encountering whitespace, newline or EOF while getchar is a C function to read a character only from the standard input stream(stdin), which is the keyboard. Thus, this is the main difference between scanf and getchar.
Yes, there are some differences.
The main one is behaviour in case that reading a character failed. (Usually this can happen due to the input stream being closed, but there are other reasons for read failure too).
The scanf
function indicates failure through its return value. If you do not check the return value (as you don't in your code) then you have no way of knowing whether the read failed or not. In this failure case the d
might retain its old value although I am not sure if the standard guarantees that or not.
The getchar()
indicates failure by returning EOF
, which is a negative integer value (usually -1
but not guaranteed to be). In your code you write d=getchar()
which means you cannot distinguish this result from a valid read of a character with the same character code as EOF
. (Common systems have characters in the range -128
to 127
). The d
will never retain its previous value for this code.
In order to correctly cope with errors you either use scanf
and test the return value is 1
; or store the result of getchar()
in an int
and check the value is not EOF
before going on to assign it to a char
.
There is also a theoretical difference in the success case. This is not relevant on modern systems. The scanf
version will store the successful character in d
. However, the getchar()
version returns a non-negative integer which is the character converted to unsigned char
. The code d=getchar()
then involves converting this value to char
. If char
is signed this invokes implementation-defined behaviour and it might result in a different character code to what you would have gotten from scanf
. I'm not aware of any system that ever existed where this would actually be different however.
Both versions read the next available character from the stream. At the bottom of your question you describe some other behaviour but I think you are confusing the behaviour of scanf
with "%d"
with that of "%c"
.
In your program the while (b != d)
would never terminate if you never encounter another character the same as d
, you need to fix this problem and make sure it terminates when the read fails.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With