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.
CodePudding user response:
isalpha
and similar return zero if the parameter is not letter or not zero if it is.
Use if
statement not switch
to test the condition. Using switch
for logical data is not logical or practical.
use functions and write your own implementations of those functions using switch ... case
Example (using GCC extension case ranges - to be portable you need to have separate case for every letter or digit [like in myispace
])
int myisalpha(unsigned char x)
{
switch(x)
{
case 'a' ... 'z':
case 'A' ... 'Z':
return 1;
}
return 0;
}
int myisdigit(unsigned char x)
{
switch(x)
{
case '0' ... '9':
return 1;
}
return 0;
}
int myisspace(unsigned char x)
{
switch(x)
{
case ' ':
case '\n':
case '\r':
case '\t':
case '\v':
case '\f':
return 1;
}
return 0;
}
CodePudding user response:
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).