C - Case statement failing to compare variable - c

I'm a little confused with the case statement in the PrintGenre function; it passes the value correctly, but defaults to Undefined.
Little bit of background; this is ultimately becoming a (very simple) text music player, and I think I've found an easier way to do this, but just for my overall understanding I wanted to figure out why this case statement isn't functioning the way I wanted it to.
If I remove the default option, it goes to the last case option in the list.
I'm fairly new to the C language, so if there's anything I'm misunderstanding please let me know.
#include "terminal_user_input.h"
#include <stdio.h>
#include <string.h>
enum musicGenre {Pop, Alternative_Rock, Electronic, Undefined};
struct Album
{
my_string Title;
my_string Artist;
int Year;
enum musicGenre Genre;
};
my_string PrintGenre(int Genre)
{
//Variables
my_string result;
printf("%d", Genre); //outputs correctly
switch (Genre)
{
case 0:
strcpy(result.str, "Pop");
case 1:
strcpy(result.str, "Alternative Rock");
case 2:
strcpy(result.str, "Electronic");
default:
strcpy(result.str, "Undefined");
}
return result;
}
int main()
{
// Variables
struct Album Album1;
int choice;
printf("1. Pop\n");
printf("2. Alternative Rock\n");
printf("3. Electronic\n");
choice = read_integer("Please select a genre: ");
switch (choice)
{
case 1:
Album1.Genre = 0;
break;
case 2:
Album1.Genre = 1;
break;
case 3:
Album1.Genre = 2;
break;
default:
Album1.Genre = 3;
break;
}
printf("%d", Album1.Genre);
printf("The genre of Album 1 is %s", PrintGenre(Album1.Genre).str);
return 0;
}

In your code,
switch (Genre)
{
case 0:
strcpy(result.str, "Pop");
case 1:
strcpy(result.str, "Alternative Rock");
case 2:
strcpy(result.str, "Electronic");
default:
strcpy(result.str, "Undefined");
}
all the case statements bodies are missing a break; statement, which makes it a fall-through switch.
To avoid this "undesired" behaviour, you need to add a break; statement every time you want to limit the flow of program to a certain part of the body.
Quoting the example from the C11 standard, chapter ยง6.8.4.2/P7
EXAMPLE In the artificial program fragment
switch (expr)
{
int i = 4;
f(i);
case 0:
i = 17;
/* falls through into default code */ << --- NOTE HERE
default:
printf("%d\n", i);
}

add break;
switch (Genre)
{
case 0:
strcpy(result.str, "Pop"); break;
case 1:
strcpy(result.str, "Alternative Rock"); break;
case 2:
strcpy(result.str, "Electronic"); break;
default:
strcpy(result.str, "Undefined");
}

Related

Are macros for large switch statements faster than functions with large switch statements?

So, for inline functions (1-2 statements) and small macros, it seems that there isn't too much of a performance difference between using a macro or an inline function.
However, given the function call overhead for a larger function, I am wondering for,
GCC 7.0
C language (not C++)
OSX (not sure if this would vary that much cross platform)
Would using large macros for a switch statement be faster than putting them in an equivalent function call? This is on my part assuming such large functions will not be inlined. Here is my example code.
#define LEX_CHAR(chPtr, tag) switch(*chPtr) { \
case 'a':\
case 'b':\
case 'c':\
case 'e':\
case '$': tag = Tag_A;\
break; \
case '0':\
case '1':\
case '2':\
case '3': tag = Tag_B;\
break;\
case 'r':\
if(chPtr[1] == 'd' || chPtr[1] == '#') tag = Tag_c;\
else tag = Tag_B;\
break;\
case '+':\
case '#':\
case '!':\
if(chPtr[1] == 'd') tag = Tag_C;\
case '-':\
case '^':\
tag = Tag_D;\
break;\
default:\
tag = Tag_B;\
}
enum Tag
{
Tag_A,
Tag_B,
Tag_C,
Tag_D
};
typedef enum Tag Tag;
void Lex_Char(char* chPtr, Tag* tag)
{
switch(*chPtr) {
case 'a':
case 'b':
case 'c':
case 'e':
case '$': *tag = Tag_A;
break;
case '0':
case '1':
case '2':
case '3': *tag = Tag_B;
break;
case 'r':
if(chPtr[1] == 'd' || chPtr[1] == '#') *tag = Tag_C;
else *tag = Tag_B;
break;
case '+':
case '#':
case '!':
if(chPtr[1] == 'd') *tag = Tag_C;
case '-':
case '^':
*tag = Tag_D;
break;
default:
*tag = Tag_B;
}
}
So between these two, the macro and the function, is there any optimization in using the macro over the function?
First, note that when you have code in a macro, the compiler must insert it inline in the calling code. When you make it a function, the compiler may insert it inline.
You should also understand what happens when you declare a function like:
void Lex_Char(char* chPtr, Tag* tag) { ... }
This tells the compiler that the function is accessible from other C files - the compiler has to make a full version of this function. Inlining the function would then mean making two copies of the code - one for the full function version, and one inlined at the call site. The compiler will be reluctant to do this unless your optimisation settings put a strong emphasis on size over speed.
If a function is only to be used within the current translation unit, you should mark it "static":
static void Lex_Char(char* chPtr, Tag* tag) { ... }
This tells the compiler that it is inaccessible from outside. If the function is only ever used once within the current module, then the compiler can happily inline it - doing so is "free".
You can also mark the function as "static inline", giving the compiler a hint that you are keen on it being inlined.
Of course, this all depends on having optimisation enabled for the compiler - if you don't enable optimisation, all your time testing is worthless.
An inlined static function is always a better choice than a macro (when you have the choice - macros can be more flexible than inline functions). The code is clearer to write, and you have better static warning and error checking. The resulting code (assuming optimisation) will be the same.
Your timing tests, incidentally, are pointless here - the compiler will see that the values involved don't change and will not run the function more than once, when it is inlined and optimisation is enabled. It might not run it at all, but pre-calculate the result at compile time.
Oh, and you've forgotten a "break" in the case '!'.
So it turns out after a timed test, and repeated under an identical for loop, the macro version is about twice as fast as the regular function.
Here's is my complete timer and full file compiled to produce the result
#include "stdio.h"
#include "stdlib.h"
#include "time.h"
#define LEX_CHAR(chPtr, tag) switch(*chPtr) { \
case 'a':\
case 'b':\
case 'c':\
case 'e':\
case '$': tag = Tag_A;\
break; \
case '0':\
case '1':\
case '2':\
case '3': tag = Tag_B;\
break;\
case 'r':\
if(chPtr[1] == 'd' || chPtr[1] == '#') tag = Tag_C;\
else tag = Tag_B;\
break;\
case '+':\
case '#':\
case '!':\
if(chPtr[1] == 'd') tag = Tag_C;\
case '-':\
case '^':\
tag = Tag_D;\
break;\
default:\
tag = Tag_B;\
}
enum Tag
{
Tag_A,
Tag_B,
Tag_C,
Tag_D
};
typedef enum Tag Tag;
void Lex_Char(char* chPtr, Tag* tag)
{
switch(*chPtr) {
case 'a':
case 'b':
case 'c':
case 'e':
case '$': *tag = Tag_A;
break;
case '0':
case '1':
case '2':
case '3': *tag = Tag_B;
break;
case 'r':
if(chPtr[1] == 'd' || chPtr[1] == '#') *tag = Tag_C;
else *tag = Tag_B;
break;
case '+':
case '#':
case '!':
if(chPtr[1] == 'd') *tag = Tag_C;
case '-':
case '^':
*tag = Tag_D;
break;
default:
*tag = Tag_B;
}
}
int main(){
Tag tagPnt = Tag_D;
char* code = "#he";
clock_t start, end;
start = clock();
//for(size_t i = 0; i<10000;i++) Lex_Char(code, &tagPnt); Number of seconds: 0.000067
for(size_t i = 0; i<10000;i++) LEX_CHAR(code, tagPnt); // Number of seconds: 0.000032
end = clock();
printf( "Number of seconds: %f\n", (end-start)/(double)CLOCKS_PER_SEC );
printf("%d is tag\n", tagPnt);
return 0;
}
Result:
Function: 0.000067
Macro: 0.000032

Trying to access string in struct causes segmentation fault

It's my first time posting a question here and i'll try to be as precise as I can.So i have this project and when i try to access a string in a struct it gives me a segmentation fault.
struct InfoSession {
TabNodePtr FirstTab;
TabNodePtr LastTab;
TabNodePtr CurrTab;
TabNodePtr AuxTab;
char* OpeningAddress;};
this is the struct included in the Session.c file where i have all the functions that i want to call in my main.
void SessionNewOpeningAddress(char * OpeningAddress,InfoSessionPtr Session){
scanf("%s",&OpeningAddress);
strcpy(Session->OpeningAddress,OpeningAddress);}
this is one of the functions that cause a segmentation fault(after testing i realised that each function that calls Session->OpeningAddresscause a segmentation fault.)This is my main.c where my main is included.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Session.h"
int main(int argc, char *argv[]) {
InfoSessionPtr MySession=NULL;
int option;
char OpeningAddress;
do{
printf("\n\n1. Create Session.\n\
2. Create new tab.\n\
3. Go to next tab.\n\
4. Go to previous tab.\n\
5. Move tab left.\n\
6. Move tab right.\n\
7. Set new opening address.\n\
8. Show the default opening address.\n\
9. Go to next site.\n\
10.Go to previous site.\n\
11.Show the current address.\n\
12.Close the current tab.\n\
13.Close session.\n\
14.Open a new address.\n\
Dwste thn epilogh sas(1-14, 0 gia eksodo):");
scanf("%d",&option);
switch(option)
{case 1:
SessionNew(&OpeningAddress);
MySession =&SessionNew;
printf("The Session has been created!");
break;
case 2:
SessionNewTab(MySession);
break;
case 3:
SessionTabNext(MySession);
break;
case 4:
SessionTabPrev(MySession);
break;
case 5:
SessionTabMoveLeft(MySession);
break;
case 6:
SessionTabMoveRight(MySession);
break;
case 7:
printf("Dwste nea dieuthinsi gia default\n");
SessionNewOpeningAddress(&OpeningAddress,MySession);
break;
case 8:
SessionShowOpeningAddress(MySession);
break;
case 9:
SessionSiteNext(MySession);
break;
case 10:
SessionSitePrev(MySession);
break;
case 11:
SessionAddressShow(MySession);
break;
case 12:
SessionTabClose(MySession);
break;
case 13:
SessionClose(MySession);
break;
case 14:
SessionNewAddress(&OpeningAddress,MySession);
break;
}
}while(option);
return 0;}
I've searched all over the internet but i still cant understand where the problem is.Anyone that can help me please reply as fast as you can.
Oh and the SessionNew function is here(everything works fine in this function):
InfoSessionPtr SessionNew(char * OpeningAddress){
TabNodePtr Tab;
InfoSessionPtr IS;
SiteNodePtr Site;
IS=malloc(sizeof(struct InfoSession));
Tab=malloc(sizeof(struct TabNode));
Site=malloc(sizeof(struct SiteNode));
IS->OpeningAddress=malloc(strlen(OpeningAddress)+1);
Site->Address=malloc(strlen(OpeningAddress)+1);
IS->AuxTab = NULL;
IS->CurrTab = Tab;
IS->FirstTab = Tab;
IS->LastTab = Tab;
Tab->NextTab = Tab;
Tab->PrevTab = Tab;
Site->UpTab = Tab;
Tab->CurrSite = Site;
Tab->FirstSite = Site;
OpeningAddress = "google";
strcpy(IS->OpeningAddress,OpeningAddress);
strcpy(Site->Address,IS->OpeningAddress);}
Consider this. I moved the statement OpeningAddress = "google"; before the malloc and changed it to strcpy. As I did nt have the session.h file and the other functions, i removed those references.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct InfoSession {
char* OpeningAddress;};
typedef struct InfoSession *InfoSessionPtr;
void SessionNewOpeningAddress(char * OpeningAddress,InfoSessionPtr Session){
scanf("%39s",OpeningAddress);
strcpy(Session->OpeningAddress,OpeningAddress);}
InfoSessionPtr SessionNew(char * OpeningAddress){
InfoSessionPtr IS;
IS=malloc(sizeof(struct InfoSession));
strcpy ( OpeningAddress, "google");
IS->OpeningAddress=malloc(strlen(OpeningAddress)+1);
strcpy(IS->OpeningAddress,OpeningAddress);
return IS;}
int main(int argc, char *argv[]) {
InfoSessionPtr MySession=NULL;
int option;
char OpeningAddress[40] = "g";
do{
printf("\n\n1. Create Session.\n\
2. Create new tab.\n\
3. Go to next tab.\n\
4. Go to previous tab.\n\
5. Move tab left.\n\
6. Move tab right.\n\
7. Set new opening address.\n\
8. Show the default opening address.\n\
9. Go to next site.\n\
10.Go to previous site.\n\
11.Show the current address.\n\
12.Close the current tab.\n\
13.Close session.\n\
14.Open a new address.\n\
Dwste thn epilogh sas(1-14, 0 gia eksodo):");
scanf("%d",&option);
switch(option)
{case 1:
MySession = SessionNew(OpeningAddress);
printf("The Session has been created!");
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
printf("Dwste nea dieuthinsi gia default\n");
SessionNewOpeningAddress(OpeningAddress,MySession);
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
case 13:
break;
case 14:
break;
}
}while(option);
return 0;}

Why does strcat fail to concatenate two strings?

I need to convert a number into a string. I'm a dealer and distribute cards to players. The deck contains 40 cards. Four seeds.
#include <stdio.h>
#include <conio.h>
#include <string.h>
char *convertNum(int a); //initialization function
void main(){
char *car=convertNum(30);
printf(" number to convert 30 : %s", car);
getch();
}
char *convertNum(int a){
char *seed, *value;
switch ((a-1)/10){
case 0: seed="C"; break;
case 1: seed="Q"; break;
case 2: seed="F"; break;
case 3: seed="P"; break;
default: seed="X"; break;
}
switch(a%10){
case 0: value="10"; break;
case 1: value="01"; break;
case 2: value="02"; break;
case 3: value="03"; break;
case 4: value="04"; break;
case 5: value="05"; break;
case 6: value="06"; break;
case 7: value="07"; break;
case 8: value="08"; break;
case 9: value="09"; break;
default: value="XX"; break;
}
strcat(value, seed); /* ERROR: I need to concatenate the strings value and seed, but this isn't the right way */
return value;
}
What can I do to concatenate the strings? value and seed are pointers.
1.The pointers *value and *seed are uninitialized . They have no meomories. You need to initialize those pointers using malloc() or calloc() with some block of memory then it can hold values.
Hope this will work for you
In your function,you are assigning the pointers seed and value to string literals in the switch statements,however,what you need to do is allocate memory for these two pointers,copy strings to them using strcpy() or other standard library function,and concatenate at the end of the function.Make sure the allocated memory is big enough to hold both strings along with the '\0' character.Finally don't forget to free allocated memory when done.
#include <stdio.h>
#include <conio.h>
#include <string.h>
char *convertNum(int a);
void main(){
char *car=convertNum(30);
printf("number to convert 30 : %s\n", car);
free(car);
getch();
}
char *convertNum(int a){
char *seed = (char*)malloc(20*sizeof(char)), *value = (char*)malloc(20*sizeof(char));
switch ((a-1)/10){
case 0: strcpy(seed,"C"); break;
case 1: strcpy(seed,"Q"); break;
case 2: strcpy(seed,"F"); break;
case 3: strcpy(seed,"P"); break;
default: strcpy(seed,"X"); break;
}
switch(a%10){
case 0: strcpy(value,"10"); break;
case 1: strcpy(value,"01"); break;
case 2: strcpy(value,"02"); break;
case 3: strcpy(value,"03"); break;
case 4: strcpy(value,"04"); break;
case 5: strcpy(value,"05"); break;
case 6: strcpy(value,"06"); break;
case 7: strcpy(value,"07"); break;
case 8: strcpy(value,"08"); break;
case 9: strcpy(value,"09"); break;
default:strcpy(value,"XX"); break;
}
strcat(value, seed);
free(seed);
return value;
}
You are pointing value and seed to string literals in your switch statements. You are not allowed to modify string literals with strcat(), because they are stored in read-only memory.
You could use malloc() in your convertNum() function to solve your problem. But then please don't forget to call free() when you no longer need a string. However, you can also provide a statically allocated array of characters from your main() function to the convertNum() function. This makes sense here, because your result strings will always have a fixed length of 3 characters:
void main(){
// Allocate an array of four characters and initialize it with zeros.
// You need 4 characters, because strings need to be zero terminated.
char car[4] = {0};
// Pass (a pointer to) the array to your covertNum() function.
convertNum(30, car);
printf(" number to convert 30 : %s", car);
getch();
}
Then you have to modify your convertNum() function as follows:
void convertNum(int a, char* result){
char *seed, *value;
switch ((a-1)/10){
[...]
}
switch(a%10){
[...]
}
strcpy(result, value); // Copy 'value' to the beginning of the 'result' array.
strcat(result, seed); // Append 'seed' to 'value'; 'result' becomes zero-terminated.
}
This gives the following output:
number to convert 30 : 10F
In case you want your output to be F10, then you have to switch value and seed in the last two lines of the convertNum() function.

C programming - enum switch case with TCHAR

I am doing a win32 program with C and I do not know how to do a enum and switch case with UNICODE.
I receive from the client a named pipe with this structure
typedef struct {
TCHAR UtilOrigem[10];
TCHAR Comando[3]; // Comando
TCHAR Argumento1[10];
}cmd;
cmd.comando have values "00", "01", "02" .....
And I want to do a switch case with cmd.comando.
Please help me.
Thanks
Carlos
Try this:
int val = _ttoi(cmd.comando);
switch (val)
{
case 0:
...
break;
case 1:
...
break;
case 2:
...
break;
...
}
Or even simpler:
int val = 10*(cmd.comando[0]-L'0')+(cmd.comando[1]-L'0');
switch (val)
{
case 0:
...
break;
case 1:
...
break;
case 2:
...
break;
...
}

Jumping from one case to the default case in switch statement

switch(ch){
case 'a':
//do something, condition does not match so go to default case
//don't break in here, and don't allow fall through to other cases.
case 'b':
//..
case 'c':
//..
case '_':
//...
default:
//
break;
}
In a switch statement like above one I enter case 'a', I break only if the condition inside it occurs, otherwise I want to jump to default case. Is there any other way of doing this rather than labels or gotos?
goto For The Win
switch (ch) {
case 'a':
if (1) goto LINE96532;
break;
case 'b':
if (1) goto LINE96532;
break;
LINE96532:
default:
//
break;
}
Just reorder the cases so that that case is the last:
switch(ch){
case 'b':
//..
case 'c':
//..
case '_':
//...
case 'a':
//do something, condition does not match so go to default case
if (condition)
break;
//don't break in here, and don't allow fall through to other cases.
default:
//
break;
}
If the condition doesn't depend on cases, why put it inside?
if (!condition){
// do default
}else{
switch(ch){
case 'a':
// do a
break;
...
}
}
Refactor your code:
int test_char(char ch)
{
switch(ch) {
case 'a': if (condition) return 0; break;
case 'b': // ...
default: return -1;
}
return 1;
}
...
// defaults processing switch
switch(test_char(ch)) {
case 0: break; // condition met
case 1: // default processing
default: // case not handled by test_char
}
This also adds the benefit of being flexible to test for multiple classes of default processing. Say you have a group of chars [c, d, e, f] which share some common logic. Simply return 2 from test_char() for these cases (possibly after some conditions has been tested), and add a case 2: handler to the default processing switch statement.
I'm not sure if thes is the best answer, but here it goes:
If you absolutely do not want to use labels, and you want to keep the cases in their current order, then you could continue after case 'a' and then check so see if(ch != 'a') at the beginning of each subsequent case, only executing the statement if the condition is true:
switch(ch){
case 'a':
// do something
case 'b':
if(ch != 'a') {
//do something
}
//repeat for each subsequent case
default:
//do something
break;
}
This is probably not the most efficient way to solve your problem, but it should accomplish what you want.
If you must have the switch statements first because the condition you're checking for depends on the case (or the case has to be evaluated first before you can check on the condition), simply set a flag inside your switch cases, and if that flag is set, then do a default operation. For instance:
int default_true = 0;
switch (case_value)
{
case 'a': /* if the condition is true, set the default_true flag */
case 'b': /* if the condition is true, set the default_true flag */
//...
default: default_flag = 1; // set the default_true flag to true
}
if (default_flag)
{
//place your "default" code here rather than inside the switch statement
//this prevents code reduplication
}
Here's what I did:
char ucResult = 1;
switch(ch){
case 'a':
if(ucResult){
// do something
if(error) ucResult = 0;
}
case 'b':
if(ucResult){
// do something
if(error) ucResult = 0;
}
case 'c':
if(ucResult){
// do something
if(error) ucResult = 0;
}
case '_':
if(ucResult){
// do something
if(error) ucResult = 0;
}
default:
//
break;
}
With this structure, you can switch to default case from any previous cases. Handy for breaking outer loops too.
I hope my solution answers your question. Simply let the cases follow through all the way (beginning with the matching case) but use a condition to disable subsequent cases from running.
typedef enum boolean
{
FALSE = 0, TRUE = 1
} bool;
void pstuff(char input)
{
bool _skip = FALSE;
switch(input)
{
case 'a':
printf("Case a.");
_skip = TRUE;
case 'b':
if(!_skip)
{
printf("Case b.");
_skip = TRUE;
}
case 'c':
if(!_skip)
{
printf("Case c.");
_skip = TRUE;
}
//...
default:
printf("Done!\n"); //Always gets printed.
}
}
Well, the post is really old but to answer everyone:
you can simple write 'goto default;' and you will directly jump to the default case without any problems.
Example:
switch (value)
{
case value1:
// do something;
break;
case value2:
// do something
break;
.
.
.
.
case value20:
// do something
**goto default;**
.
.
case valueN:
// do something
break;
default:
// do something
break;
}

Resources