0

PROGRAM: A survey to know the popularity of four cars (Ambassador, Fiat, Dolphin and Maruti) was conducted in four cities (Bombay, Calcutta, Delhi and Madras). Each person surveyed was asked to give his city and the type of car he was using. The results, in coded form, are tabulated as follows:

M 1 C 2 B 1 D 3 M 2 B 4
C 1 D 3 M 4 B 2 D 1 C 3
D 4 D 4 M 1 M 1 B 3 B 3
C 1 C 1 C 2 M 4 M 4 C 2
D 1 C 2 B 3 M 1 B 1 C 2
D 3 M 4 C 1 D 2 M 3 B 4

Codes represent the following information:

M - Madras 1 - Ambassador

D – Delhi 2 - Fiat

C – Calcutta 3 - Dolphin

B – Bombay 4 - Maruti

Write a program to produce a table showing the popularity of various cars in four cities.

PROBLEM: The scanf in the for loop isn't taking input as per the condition I've mentioned. The loop is supposed to run 36 times so that I can input data 36 times, rather it takes only 19 inputs and then the loop ends. I don't know why it's happening.

#include<stdio.h>

void main(){
    unsigned short car, i, survey[5][5] = {{0},{0},{0},{0},{0}};
    char city;
    printf("Enter city initial and car code\n");
    for (i = 0; i < 36; i++)
    {
        scanf("%c %hu",&city,&car);
        switch (city)
        {
        case 'b':
            survey[1][car]++;
            break;
        case 'c':
            survey[2][car]++;
            break;
        case 'd':
            survey[3][car]++;
            break;
        default:
            survey[4][car]++;
            break;
        }
    }
    printf("BOMBAY:\nAmbassador = %hu\nFiat = %hu\nDolphin = %hu\nMaruti = %hu\n",survey[1][1],survey[1][2],survey[1][3],survey[1][4]);
    printf("CALCUTTA:\nAmbassador = %hu\nFiat = %hu\nDolphin = %hu\nMaruti = %hu\n",survey[2][1],survey[2][2],survey[2][3],survey[2][4]);
    printf("DELHI:\nAmbassador = %hu\nFiat = %hu\nDolphin = %hu\nMaruti = %hu\n",survey[3][1],survey[3][2],survey[3][3],survey[3][4]);
    printf("MADRAS:\nAmbassador = %hu\nFiat = %hu\nDolphin = %hu\nMaruti = %hu\n",survey[4][1],survey[4][2],survey[4][3],survey[4][1]);
}

OUTPUT:

m 1
c 2
b 1
d 3
m 2
b 4
c 1
d 3
m 4
b 2
d 1
c 3
d 4
d 4
m 1
m 1
b 3
b 3
c 1
BOMBAY:
Ambassador = 1
Fiat = 1
Dolphin = 2
Maruti = 1
CALCUTTA:
Ambassador = 1
Fiat = 1
Dolphin = 1
Maruti = 0
DELHI:
Ambassador = 1
Fiat = 0
Dolphin = 2
Maruti = 2
MADRAS:
Ambassador = 9
Fiat = 4
Dolphin = 5
Maruti = 9
UpAndAdam
  • 4,515
  • 3
  • 28
  • 46
  • 3
    Instead of `scanf("%c %hu", ...)` try `scanf(" %c %hu", ...)` (note the leading space). – Some programmer dude Jun 30 '23 at 08:59
  • Also, remember that array-indexes are zero-based. If you write your programs to have one-based indexes you will be pretty much alone. – Some programmer dude Jun 30 '23 at 09:01
  • @Someprogrammerdude still doesn't solve the problem. I tried to insert the printf part before the scanf, but it's behaving weird in the output. – Anuska Saha Jun 30 '23 at 14:35
  • The space is definitely needed, otherwise the second call to `scanf` will set the `city` to the newline left over from the first call. Once that happens, all input will be out of sync and all remaining calls will fail. And you *always* need to check what `scanf` [*returns*](https://en.cppreference.com/w/c/io/fscanf#Return_value). – Some programmer dude Jun 30 '23 at 15:29
  • Upper-case versus lower-case? The character `'C'` is *not* the same as the character `'c'`! – Some programmer dude Jul 02 '23 at 05:58
  • And add a specific case for `'m'`, and use the `default` case for handling invalid input. – Some programmer dude Jul 02 '23 at 05:59
  • After adding some extra checks and outputs (like a proper case for `'m'`), [my own example](https://godbolt.org/z/caMq61vx7) shows all problems: The leading space in the format string, the failing of `scanf` (when it returns `1`), and the lower-/upper-case problem. To summarize: Leading space in the format string; Checking the result of `scanf`; And handle both upper- and lower-case input. [Here's an example I wrote](https://godbolt.org/z/nxczxnY1T), with all fixes, and error handling, and more improvements. – Some programmer dude Jul 02 '23 at 06:15

1 Answers1

-1

The following is from the "C Programming Language" regarding the "c" conversion character:

The next input characters (default 1) are placed at the indicated spot. The normal skip-over white space is suppressed; to read the next non-white space character, use %1s

The unique part of the "%c" conversion char is that the normal skip-over white space is suppressed. As a result, the newline char is left in the buffer and gets read in the next iteration of the loop. This is why a loop of 36 iterations is only taking 19 lines of input. You can confirm the behavior by adding a printf() call after the scanf() function.

In my initial answer of scanf("%c %hu\n",&city,&car), I tried to add the "\n" to consume the unwanted/skipped "\n". But the side effect is that it caused the scanf to wait for the next line, hence it would need 37 lines of input to end (dude was correct on this in the comments). A better answer is to do what the book suggests:

scanf("%1s %hu",&city,&car);
user9035826
  • 126
  • 6
  • Trailing newline (or space) is almost always problematic. For interactive input (from terminal), it means the user *must* enter some *extra* input after the last actual input. Otherwise `scanf` will just wait and not return. You should always use a *leading* space in `scanf` format strings. – Some programmer dude Jul 01 '23 at 09:57
  • leading space did not work. Did you test what you suggested? As I said, based on how he was entering the data, the formatter I gave above works as expected. – user9035826 Jul 02 '23 at 05:52
  • Please try a simple example in your own (**interactive**) terminal, like e.g. `#include int main(void) { char c1, c2; scanf("%c\n", &c1); scanf("%c\n", &c2); printf("Done\n"); }` How many inputs do you need to give for the program to claim it's done? The expected two? Or more? Try again with a *leading* space, like `" %c"`. Also see e.g. [What is the effect of trailing white space in a scanf() format string?](https://stackoverflow.com/questions/19499060/what-is-the-effect-of-trailing-white-space-in-a-scanf-format-string) – Some programmer dude Jul 02 '23 at 06:22
  • I have done it in a reverse way. I need to input the city name and the car code simultaneously, for that I first input the car code and then the city initial after a leading space. It didn't throw any error, because after integer input, the compiler read the leading space as a leading space only, followed by then the character input: `scanf("%hu %c",&car,&city);` – Anuska Saha Jul 03 '23 at 06:32
  • 1
    swapping the order and putting the "%hu" in the front does help skip the "\n" char left in the buffer from the previous line of input, which will give you the expected results. – user9035826 Jul 03 '23 at 22:56