C switch, how to fix multiple default prints?

81 views Asked by At

If i give my program this:

abcdefghijklmnopqrstuvwxyz

It answered with this?!

Invalid command a
Invalid command c
Invalid command e
Invalid command g
Invalid command i
Invalid command k
Invalid command m
Invalid command o
Invalid command q
Invalid command s
Invalid command u
Invalid command w
Invalid command y

Any idea why only every other letter is getting my default message, and why there is so many and not just one, how can i fix this so i only get one default message no matter how many invalid characters i input?

Here is that part of my code:

while (1) {
  scanf("%c", &command);
  getchar();

  switch (command) {
  case 'A': // Adds a new entry to the program database.
    if (scanf("%s %f", name, &price) != 2) {
      printf("A should be followed by exactly 2 arguments.\n");
      // while (getchar() != '\n'); // Clear the input buffer
    } else {
      getchar(); // Consume the newline character
      addGame(&games, &numGames, name, price); // Pass pointer to games
    }
    break;
  case 'B': // Buy game command, which sells a specified number of games
    if (scanf("%s %d", name, &count) != 2 || count <= 0) {
      getchar(); // Consume the newline character
      printf("Number of bought items cannot be less than 1.\n");
    } else {
      getchar(); // Consume the newline character
      buyGame(games, numGames, name, count);
    }
    break;
  case 'L': //Prints a list of the program database into the standard output
    printDatabase(games, numGames);
    break;
  case 'W': //Writes the program database into a text file
    scanf("%s", filename);
    getchar();
    saveToFile(games, numGames, filename);
    break;
  case 'O': //Loads the database from the specified text file
    scanf("%s", filename);
    getchar();
    loadFromFile(&games, &numGames, filename); // Pass pointer
    break;
  case 'Q': //Quits the program after releasing the program database
    releaseMemory(games, numGames);
    return 0;
  case '\n': //Not sure i need this?
    break;
  default:
    printf("Invalid command %c\n", command);
  }
}

I can send more of my code if someone think it's needed :)

3

There are 3 answers

1
Vlad from Moscow On

In the beginning of the while loop you have

while (1) {
scanf("%c", &command);
getchar()
//...

So when you enter such a sequence of symbols

abcdefghijklmnopqrstuvwxyz

then the call of scanf reads one character as for example 'a' and the next call of getchar reads the next character 'b'. As the command 'a' is invalid then next call of scanf reads the next character 'c' and the call of getchar reads the letter 'd' and so on. What you do is what you get.

Instead of these two calls

scanf("%c", &command);
getchar()

you could use only one call of scanf like

scanf(" %c", &command);

Pay attention to the leading space in the format string. It allows to skip white space characters including the new line character '\n'. And if the input is invalid you should clear the input buffer under the label default for example like

while ( getchar() != '\n' );

or

scanf( "%*[^\n]" );

And remove calls of getchar also in other places of your code.

0
Some programmer dude On

You read only one character at a time, not whole lines. That's why you get "so many and not just one".

To read whole lines use fgets instead. And add validation that only one character was input, if you need.

The reason you only get every second character reported as wrong, is just because of the misguided getchar call after scanf("%c", &command). The scanf call will read e.g. a, then the getchar call will read the b. And so on.

0
Luis Colorado On

in your loop, at the top:

  scanf("%c", &command);  /* read one char into command */
  getchar();              /* skip the next char, ignoring it */

you read a character into command, then getchar() just drops the next char. This is why you read alternate characters and produce that output, as the input characters are lowercase while you are checking only for some uppercase characters.