Multiple chars in SWITCH CASE in C - c

I have a school project and I'm working on a menu where the users chooses what he wants to do. I want the choice variable to be a char, not an int. Can I add multiple chars in a single switch case? I searched for a solution but I only found one when the value is an int, not a char. I tried this but it didn't work:
char choice;
scanf("%c", &choice);
switch(choice)
{
case 'S', 's':
// do something
break;
case 'I', 'i':
// do another thing
break;
default:
printf("\nUnknown choice!");
break;
}

For starters use the following format in scanf
char choice;
scanf( " %c", &choice );
^^^
(see the blank before the conversion specifier). Otherwise the function will also read white space characters.
You can use several adjacent case labels like for example
switch(choice)
{
case 'S':
case 's':
//do something
break;
case 'I':
case 'i':
//do anotherthing
break;
default:
printf("\n Unknown choice !");
break;
}
An alternative approach is to convert the entered character to the upper case before the switch. For example
#include <ctype.h>
//...
char choice;
scanf( " %c",&choice );
switch( toupper( ( unsigned char )choice ) )
{
case 'S':
//do something
break;
case 'I':
//do anotherthing
break;
default:
printf("\n Unknown choice !");
break;
}

You can use fall through like this:
case 'S':
case 's':
// do something
break;
case ...

You can put multiple case labels after each other:
switch(choice) {
case 'S':
case 's':
//do something
break;
case 'I':
case 'i':
//do anotherthing
break;
default:
printf("\n Unknown choice !");
break;
}

Related

A morseEncoder program in C but have a logic error

I have written a "Morse Encoder" program in C. I can execute the code, there are no errors but a logic error. It does not give what I want. User types something as a string then hits enter but output does not happen.
Here is my code. Have a look at it. Maybe you notice what I did wrong.
#include <stdio.h>
#include <string.h>
#define SIZE 100
const char* morseEncode(char x){
switch(x){
case 'A':
case 'a':
return ".-";
case 'B':
case 'b':
return "-...";
case 'C':
case 'c':
case 'Ç':
case 'ç':
return "-.-.";
case 'D':
case 'd':
return "-..";
case 'E':
case 'e':
return ".";
case 'F':
case 'f':
return "..-.";
case 'G':
case 'g':
case 'Ğ':
case 'ğ':
return "--.";
case 'H':
case 'h':
return "....";
case 'I':
case 'ı':
case 'İ':
case 'i':
return "..";
case 'J':
case 'j':
return ".---";
case 'K':
case 'k':
return "-.-";
case 'L':
case 'l':
return ".-..";
case 'M':
case 'm':
return "--";
case 'N':
case 'n':
return "-.";
case 'O':
case 'o':
return "---";
case 'Ö':
case 'ö':
return "---.";
case 'P':
case 'p':
return ".--.";
case 'Q':
case 'q':
return "--.-";
case 'R':
case 'r':
return ".-.";
case 'S':
case 's':
case 'Ş':
case 'ş':
return "...";
case 'T':
case 't':
return "-";
case 'U':
case 'u':
return "..-";
case 'Ü':
case 'ü':
return "..--";
case 'V':
case 'v':
return "...-";
case 'W':
case 'w':
return ".--";
case 'X':
case 'x':
return "-..-";
case 'Y':
case 'y':
return "-.--";
case 'Z':
case 'z':
return "--..";
default:
return NULL;
}
}
void morseCode (const char *p){
for(int i=0;p[i];i++){
printf("%s/",morseEncode(p[i]));
}
}
int main() {
char phrase[SIZE];
printf("Code is non-sensitive to letters.\nEnter phrase: ");
scanf("%c",phrase);
puts("");
morseCode(phrase);
}
I think I did something wrong in conversions such as const char* to char or vice-versa.
const char *phrase;
phrase is uninitialised, so when you do
scanf("%s",phrase);
you're writing into some random place in memory causing undefined behaviour.
You need to allocate space for your string first. Either as an array
char phrase[100];
or by allocating memory
char *phrase=malloc(100);
And also the const qualifier in the declaration makes little sense since you change the contents when you pass it to scanf. Having it on the function is fine as the functions don't change the value.
The problem is that I ask a character as an input.
scanf("%c",phrase);
So, eventhough user inputs a string, it only saves the first character. Changing it to ask for a string solved the logical error.
scanf("%s",phrase);

Program that keeps running until the user inputs n to exit

I a working on an assignment that allows the user to input "type" and "weight" and it'll display the cost. Here is the code. I want it to keep running until the user enters 'n'.
main()
{
char type,chr;
float cost,weight;
do
{
printf("Insert the type of fish: "); /*inputs type and weight*/
scanf("%c",&type);
printf("insert weight: ");
scanf("%f",&weight);
switch(type)
{
case 'K':
case 'k':
cost=weight*9.00;
break;
case 'R':
case 'r':
cost=weight*10.00;
break;
case 'S':
case 's':
cost=weight*12.00;
break;
case 'G':
case 'g':
cost=weight*8.00;
break;
case 'T':
case 't':
cost=weight*15.00;
break;
default :
printf("Invalid type\n");
}
printf("The cost of fish is:%.2f \n",cost);
printf("Do you want to continue?Y/N: ");
scanf(" %c",&chr);
}
while(chr == 'Y' || chr == 'y');
}
I have used the do..while loop, it worked fine until I typed in 'y' and I cannot enter the type.
Reading types from the stdin stream assumes you know exactly what is next in the stream. As Streeragh mentions, you likely have a newline as the next input character. You can triage this by dumping out what chr is (try it in hex, like %0x). The mentioned article also offers good advice: Input the text as %s (or use readline) and then parse out the input. Look into strtok. And also be aware that stdin can be redirected from a pipe (i.e out.exe < sampleinput.txt) Cheers.

Switch / Case issue

For C language, I know I'm close, but for for any character inputted, the printout is "Consonant". What is wrong with my switch case statement. Will I need if statements?
#include <stdio.h>
#include <stdlib.h>
int main()
{
char name;
printf("Enter a character: ");
scanf_s("%c", &name);
switch (name)
{
case 'a':
printf("Vowel");
break;
case 'e':
printf("Vowel");
break;
case 'i':
printf("Vowel");
break;
case 'o':
printf("Vowel");
break;
case'u':
printf("Vowel");
break;
case 'y':
printf("Sometimes");
break;
default:
printf("Consonant");
}
return 0;
}
Note that the Microsoft page for scanf_s() says:
In the case of characters, a single character may be read as follows:
char c;
scanf_s("%c", &c, 1);
Your scanf_s() call is failing, but you are not checking the result, so you don't know that.
ALWAYS check the result of input functions!
And make sure you've read the manual page for functions you're using.
It's probably also a good idea to use " %c" as the format string to skip white space. However, that's a refinement for later.
You don't have a break; after the code in the default: case label. That's not a good idea.
You can use:
if (scanf_s("%c", &name, 1) == 1)
{
switch (name)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
printf("Vowel\n");
break;
case 'y':
printf("Sometimes\n");
break;
default:
printf("Consonant\n");
break;
}
}
else
fprintf(stderr, "Failed to read a character\n");
Note that all upper-case letters, punctuation, white space and control characters are deemed to be consonants. That's not entirely accurate.

Why does getchar() read an entire line?

The sample of the program is as follow:
int main(void)
{
char input;
printf("\nEnter phone number: ");
while ((input = getchar()) != '\n') {
switch (toupper(input)) {
case 'A': case 'B': case 'C':
printf("2");
break;
case 'D': case 'E': case 'F':
printf("3");
break;
case 'G': case 'H': case 'I':
printf("4");
break;
case 'J': case 'K': case 'L':
printf("5");
break;
case 'M': case 'N': case 'O':
printf("6");
break;
case 'P': case 'R': case 'S':
printf("7");
break;
case 'T': case 'U': case 'V':
printf("8");
break;
case 'W': case 'X': case 'Y':
printf("9");
break;
default:
putchar(input);
}
}
printf("\n\n");
return 0;
}
My question is, how on Earth does the flow here work? I can't seem to understand the path the program took. Does the char variable magically become an array? How is it that putchar() prints the entire line instead of the first character entered? How exactly does something that's supposed to get and print one character, reads and prints an entire line of characters while altering them with the switch statement? Does it test each char as its entered? But then how is the string printed as a string?
Edit: I've done some research and I read about a keyboard buffer, which seems to be the cause of my confusion. To my knowledge, getchar() and putchar() receives and outputs a single character. I'm aware that the loop asks continuously for the next "buffered" char when the getchar() comes back around, still a bit confused by I should get it, but what's more confusing is putchar(). At the end of the loop, when it breaks and goes to the condition, does it print that one character then continues and prints the other one by one with each execution of the loop? Only stopping the loop at which point the new line was read? And if so, only what was previously printed, is displayed on the screen? And then if that's the case then the printed chars would print in line next to each other with each execution, giving the illusion of a string? I need confirmation on this and also, when is the char discarded and replaced? After its printed? And at which line does it receive the next char in the buffer queue?

How to store and return a string in C

My code (below) takes a text file with hexadecimal values and converts the hexadecimal value to binary and prints it. How can I modify this so that my hex_to_binary function can initialise a string array and add the converted binary to the array and then return the array. Then I just want to print the output of the hex_to_binary function by adding a printf statement in my main function. Thanks in advance
#include <stdio.h>
int hex_to_binary(char*);
int main(int argc, char *argv[])
{
FILE *file;
file = fopen(argv[1],"r");
char line[100];
while(!feof(file)){
fgets(line,100,file);
hex_to_binary(line);
}
fclose(file);
getchar();
return 0;
}
int hex_to_binary(char* hex_string)
{
int i=0;
printf("\nEquivalent binary value: ");
while(hex_string[i])
{
switch(hex_string[i])
{
case '0': printf("0000"); break;
case '1': printf("0001"); break;
case '2': printf("0010"); break;
case '3': printf("0011"); break;
case '4': printf("0100"); break;
case '5': printf("0101"); break;
case '6': printf("0110"); break;
case '7': printf("0111"); break;
case '8': printf("1000"); break;
case '9': printf("1001"); break;
case 'A': printf("1010"); break;
case 'B': printf("1011"); break;
case 'C': printf("1100"); break;
case 'D': printf("1101"); break;
case 'E': printf("1110"); break;
case 'F': printf("1111"); break;
case 'a': printf("1010"); break;
case 'b': printf("1011"); break;
case 'c': printf("1100"); break;
case 'd': printf("1101"); break;
case 'e': printf("1110"); break;
case 'f': printf("1111"); break;
}
i++;
}
return 0;
}
There are several ways to do this.
The one thing you can't do is declare a character array in the function, use sprintf to print to it, and return it. You cannot be certain that the space it points to exists anymore after the function returns.
That is, DON'T do this:
int hex_to_binary(char *hex_string)
{
char binary_string[MAX_SIZE + 1];
<...>
return binary_string;
}
To do exactly what you state, you can call malloc to obtain the space inside the function, then return a pointer to it:
int hex_to_binary(char *hex_string)
{
char *binary_string;
if((binary_string = malloc(MAX_SIZE + 1)) == NULL)
return -1; /* Indicate failure */
binary_string[0] = '\0';
<etc>
switch(hex_string[i])
{
case '0' : strcat(binary_string, "0000"); break;
<etc>
return binary_string;
}
This is permitted, because malloc is allocating the memory, probably in the heap, and this memory will still exist afterwards. The issue is, the function that calls hex_to_binary needs to call free() to release this memory, otherwise every call steals a little bit of memory -- this is known as a memory leak.
That is, do:
char *binary_line;
while(!feof(file)){
fgets(line,100,file);
binary_line = hex_to_binary(line);
printf("%s", binary_line);
free(binary_line);
}
NOT
while(!feof(file)){
fgets(line,100,file);
printf("%s", hex_to_binary(line););
}
If you were to call the hex_to_binary in a loop, once per hex digit, you could change the case statements to return a pointer to a string, instead of printing:
switch(hex_digit)
{
case '0' : return "0000";
case '2' : return "0001";
<etc>
This returns a pointer to constant string that you could print and saves freeing the space afterwards.
Another option would be to pass hex_to_binary two parameters, one with the string to convert, and one a pointer to the space to write it to:
int hex_to_binary(char *hex_string, char *binary_line)
{
<etc>
switch(hex_string[i])
{
case '0' : strcat(binary_string, "0000"); break;
<etc>
return 0;
}
Call it like this:
char binary_line[MAX_SPACE + 1];
while(!feof(file)){
fgets(line,100,file);
hex_to_binary(line, binary_line);
printf("%s", binary_line);
}
strcat() function is what you want.
if I were you, for simplicity I do this one below :
Define Global Char array :
char buffer[1000]; // define a space to write our string
....
Change your hex function like this :
while(hex_string[i])
{
switch(hex_string[i])
{
case '0': strcat(buffer,"0000"); break;
case '1': strcat(buffer,"0001"); break;
case '2': strcat(buffer,"0010"); break;
....
}
}
In main use this to print your string :
printf("%s\n",buffer);
Note: Don't forget to clear buffer after your each hex_to_binary function call (otherwise it keeps the previous numbers inside)
change to like this :
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char *hexstr_to_binstr(char *outbuff, const char *s);
int main(int argc, char *argv[]){
FILE *file = fopen(argv[1],"r");
char line[100];
char binstr[4*sizeof(line)];
while(fgets(line, sizeof(line), file)){
puts(hexstr_to_binstr(binstr, line));
}
fclose(file);
getchar();
return 0;
}
const char *xdigit_to_binstr(char x){
switch(x){
case '0': return("0000");
case '1': return("0001");
case '2': return("0010");
case '3': return("0011");
case '4': return("0100");
case '5': return("0101");
case '6': return("0110");
case '7': return("0111");
case '8': return("1000");
case '9': return("1001");
case 'a':
case 'A': return("1010");
case 'b':
case 'B': return("1011");
case 'c':
case 'C': return("1100");
case 'd':
case 'D': return("1101");
case 'e':
case 'E': return("1110");
case 'f':
case 'F': return("1111");
default : return "";
}
return NULL;//never reach this point
}
char *hexstr_to_binstr(char *outbuff, const char *s){
char *p = outbuff;
for(; *s ; ++s){
if(isxdigit(*s)){
memcpy(p, xdigit_to_binstr(*s), 4);
p += 4;
}
}
*p = 0;
return outbuff;
}

Resources