cloopsswitch-statementisspace

Nested switch() - case issue in C. Why are <ctype.h> functions not working the way I would like them to?


I have been trying to understand why this is not working properly for the past five hours.

The question explicitly asks for the use of switch() and no if-else (or of the likes) to count the number of words, lines, and characters in typed up text. And exit the program with Ctrl+D or Ctrl+Z.

Here, I deconstructed the counting by figuring different cases of whether the current typed input is whitespace or not, and from thereon, judging by the previous letter, whether it is justified to count it as an extra word, character, and/or line. ( input = punctuation, previous input= character --> add 1 to word count and 1 to character count ; if input = newline and previous input !=whitespace --> add one to line counter + one to word counter, etc.)

My code is the following:


int main() {
  int letter = 0, prev_letter = 0, num_char = 0, num_words = 0, num_lines = 0;

  printf("User, please provide any text you wish using letters, spaces, tabs, "
         "and enter. \n When done, enter Ctrl+D or Ctrl+Z on your keyboard.");

  while ((letter = getchar()) != 4 &&
         letter != 26) // In ASCII, Ctrl+D is 4, and Ctrl+Z is 26
  {
    switch (isspace(letter)) {
    case 0: // False = is not a whitespace
    {
      switch (
          isalpha(prev_letter)) // checking to see if alphanumeric input or not
      {
      case 1:
        switch (ispunct(letter)) {
        case 1:
          num_words++;
          num_char++; // Punctuation considered as characters in this particular
                      // sub-exercise.
          break;
        }
        break;

      case 0:
        num_char++;
        break; // All other cases are just another character added in this case
               // 0 (Not whitespace)
      }
    } break;

    case 1: {
      switch (letter) {

      case 9: // 9 =Horizontal tab
      {
        switch (isspace(prev_letter)) {
        case 0:
          num_words++; // Assuming if not whitespace, then punctuation or
                       // character.
          break;
        default:
          break;
        }

      } break;

      case 32: // 32 = Space
      {
        switch (isspace(prev_letter)) {
        case 0:
          num_words++; // Assuming if not whitespace, then punctuation or
                       // character.
          break;
        default:
          break;
        }

      } break;

      case 13: // 13 = Carriage return
      {
        switch (isspace(prev_letter)) {
        case 0:
          num_words++;
          num_lines++;
          break;
        default:
          num_lines++;
        }

      } break;

      case 10: // 13 = Line Feed
      {
        switch (isspace(prev_letter)) {
        case 0:
          num_words++;
          num_lines++;
          break;
        default:
          num_lines++;
        }

      } break;

      default:
        printf("Test2");
      }
    } break;

    default:
      break;
    }

    prev_letter = letter;
  }

  printf("Number of characters is: %d. \n", num_char);
  printf("Number of words is: %d. \n", num_words);
  printf("Number of lines is: %d. \n", num_lines);
  return 0;
}```



It seems like isalpha(), ispunct(), isalnum() are not feeding properly my cases.

I have tried breaking it down to individual cases but when inputting text with tabs, spaces, and alphanumeric inputs, it fails to count words, characters, and lines properly.

What am I not seeing properly? Any pointers greatly appreciated.

Solution

  • That seems an odd assignment. Maybe you're misunderstanding it, but assuming you aren't, let me see if I can figure it out.

    switch compares one variable to several values, so that would mean the first part is to determine a single value from several test functions.

    A common use of switch is to check enum values, so you can start by defining an enum with the values you need. You're using isalpha(), ispunct(), and isspace() in your code, so I'll define those enum values.

    enum chartype {
        IS_ALPHA,
        IS_PUNCT,
        IS_SPACE,
        IS_UNKNOWN
    };
    

    You can select an enum value without using if with the ? : operators.

    enum chartype letter_chartype =
        isalpha(letter) ? IS_ALPHA
      : ispunct(letter) ? IS_PUNCT
      : isspace(letter) ? IS_SPACE
      : IS_UNKNOWN;
    

    That lets you use a switch for each character type.

    switch(letter_chartype) {
      case IS_ALPHA:
        ...
        break;
      case IS_PUNCT:
        ...
        break;
      case IS_SPACE:
        ...
        break;
      default:
        ...
        break;
    }
    

    That doesn't do your assignment for you, but I hope that helps give you some direction. I'm assuming you covered the ? : operators. If not, you might have to do something longer, trickier, or stupider (stupid often looks clever, be careful about that).