1

For this program i'm asking the user to enter a digit and it returns the digit you've entered but in another language. I'm using a switch case to utilize this and for user input errors when typing a letter instead of the digits 0-9 it defaults to invalid user input, however, when I enter 10, 11, or 12 which is outside the range it prints out isa which is number 1 which shouldn't be happening. How do I make it so that if the user enters an invalid number outside the 0-9 range it also says invalid input?

Here's the code

#include <stdio.h>

int main(void) {
  printf("This program will display the Filipino(Tagalog) word for a digit of your choice.\n");
  printf("Enter a digit 0-9: ");
  int digit = getchar();
  switch(digit) {
    case '0' :
      printf("wala\n");
      break;
    case '1' :
      printf("isá\n");
      break;
    case '2' :
      printf("dalawá\n");
      break;
    case '3' :
      printf("tatló\n");
      break;
    case '4' :
      printf("ápat\n");
      break;
    case '5' :
      printf("limá\n");
      break;
    case '6' :
      printf("anim\n");
      break;
    case '7' :
      printf("pitó\n");
      break;
    case '8' :
      printf("waló\n");
      break;
    case '9' :
      printf("siyám\n");
      break;
    default :
      printf("Invalid input\n");
  }
  return 0;
}

Thank you!

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115

2 Answers2

3

It's because getchar() only retrieves one character from standard input. It doesn't read in an entire integer. When you pass 10, 11 or 12, your code is actually reading in 1 and leaving the second digit in standard input.

You have at least a couple of options:

  1. Read in an integer from stdin, using scanf() instead of getchar(). Take a look at How can I get an int from stdio in C?, this should provide you all the information you need to do it this way, if you choose to do it. You will need to modify your switch-cases to use integer literals rather than character literals for the digits you want to switch on.
  2. Alternatively, you could instead read in an entire line of input with fgets() and check to make sure it only contains 1 character, then retrieve that first character to use in the switch. This is in keeping with your intent of wanting to switch on digits, and also additionally will not fail if you pass a non-integer input to stdin, whereas if using scanf(), you need to check the return code to make sure malformed input was not given.
    I recommend this approach because it is easier to make it fault-tolerant than the other one.
saxbophone
  • 779
  • 1
  • 6
  • 22
2

Echoing what the previous answerer said, getchar reads only one character from the standard input stream. Once it gets a character, it assigns it to digit. getchar and friends return a value of type int in order to be able to return the EOF value (which is out of char range) so you know when your stream ends. So really digit is a character, just with int type for that extra little bit of range.

I'll add that getchar will leave behind any characters left behind on the input stream that were not used. If you're using this program on the command line and press 3 followed by the enter key in order to get the output tatló, the enter key will leave a '\n' character (in Linux--I'm honestly not sure if it will be '\n' or '\r' in Windows) on the standard input stream, which the first getchar does not consume. So you could check this value with another call to getchar. Something like this:

...
printf("Enter a digit 0-9: ");
int digit = getchar();
if(getchar() != '\n') {
  /*The user typed something after the initial digit, do something, like maybe assigning an invalid value to `digit`*/
  digit = 'a';
}
switch(digit) {
  ...

The second call to getchar will return '\n' if your user entered just a single character; otherwise it will return the second character that the user entered.

This is a suitable solution to parsing a number from user input if you never intend to parse multi-digit numbers.

Wilson
  • 91
  • 5
  • 1
    I'm pretty sure that even on Windows, `'\n'` is the newline character within a C program. According to [this answer](https://stackoverflow.com/a/1761086/6177253), in C `'\n'` is translated to-and-from the native newline character (or character sequence) automatically. The newline character sequence in Windows is CRLF (`'\r\n'`) – saxbophone Jan 24 '23 at 04:29
  • 1
    @saxbophone Detail: The end-of-line character(s) is more of a compiler/shell issue than an OS one. – chux - Reinstate Monica Jan 24 '23 at 06:18
  • @chux-ReinstateMonica Huh, interesting, why do you say that? Because the choice of the line-ending type was made at the shell level rather than the OS? – saxbophone Jan 24 '23 at 21:26
  • 2
    @saxbophone Yes, when I run a Cygwin shell on a windows OS machine with a gcc compiled code, its all `'\n'`. As I see it, the OS really does not get into line-endings much. Shells and command line processors do. – chux - Reinstate Monica Jan 24 '23 at 22:25
  • 1
    @chux-ReinstateMonica I can see why you see it that way, after seeing your example, I agree, cheers – saxbophone Jan 25 '23 at 16:50