Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there difference between scanf("%c",&x) and x=getchar()?

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 an int or EOF 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.

like image 603
jacopoburelli Avatar asked Oct 21 '18 10:10

jacopoburelli


People also ask

What does %C do in scanf?

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.

Why are you using a space before %C in scanf %C &ch?

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.

Can we use %s in scanf?

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.

What is the difference between using getchar and scanf with the %c specifier to read a single character?

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.


1 Answers

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.

like image 83
M.M Avatar answered Oct 13 '22 15:10

M.M