C Structs and Switch Case


Switch Case Statement:

    Continuing on we will take a look at the switch-case statement and how you can make an interface with it so that you can do stuff infinitely. The switch-case statement is one of the basic ones and is present in most languages without any need of libraries. It’s actually a better way of creating an if-else statement for specific input values and when every value is corresponding to a specific “function” in the programm. 

For example, when you want to set up a way of doing something when x is 0 and something else when x is 1 you can do it with ease with an if-else if statement like this:

if(x == 0){

    //do something

}

else if( x == 1){

    //do something else

}

You can do it even when you have many of those statements but an easier way is creating an switch case statement that works with most types of variables like integers, floats and even strings! When a is an integer you do it like this:

switch(a){

    case 1:

        //do something

       break;

   case 2:

       //do something else

       break;

  ...

  default:

      //default function

}

We put break cause else it will “fall down” and run other cases to. Sometimes it may be helpfull tho when you want to run many cases at once.  The default one is like the else statement of the if-else statement and stands for every other value a could have. So you could put something that tells the user that the value was not right and so on.

Structs:

Structs are a way of defining user variable types where you can put anything you like, like integer’s, float’s, char’s, Array’s, Pointer’s and even other Structs. They are a way of setting up a variable that will act as a location of saving many things at once and so you can create an Array of not only Integer’s or String’s but and MultiArray that stores many informations. They are declared like this in C:

struct struct_name {   type member1;   type member2;   ...

}struct_name is the name of the struct and you can put as many member's as you wish doing stuff like:

int a; 

char b[20]; 

float *p; 

and so on.

Setting it up like that you have to use **struct struct_name s; ** to create a struct variable s of type struct_name.

To get rid of the struct every time you can use typedef.

typedef struct struct_name {   type member1;   type member2;

   ...} struct_alias;

The struct_alias is the way you want to call it when creating a variable. So using typedef we can now create a struct variable s of type struct_name using **struct_alias s; ** The struct_name is optional when you are using typedef so you could also use only struct_alias. 

Finishing of let me tell you that you can use struct pointers (that will be really helpfull when we get into lists), create a struct array that will be todays Code and that you have to use the ’.’ modifier to access each specific member and to do stuff with it afterwards like this:

#include<stdio.h>

#include<string.h>

typedef struct{

    int id;

    char name[20];

}Student;

int main(){

    Student s;

   //setting the variable

    s.id = 10;

   //getting it as input

   scanf("%19s", s.name);

   //printing the variables

   printf("%d %s\n", s.id, s.name);   

}

Code:

We want to create an interface in command line (menu with switch case) that lets you work with informations about Musical Groups and their Album’s. We’ll have to save the Group’s ID, Name, Foundation Year and 2 of the Album’s from which we want to know the Name, Release Date and Sales Count. The Group and Album need to be Structs and we want to save infinitely informations (dynamic struct array).

The Interface needs to have the following:

  • let us load from and save to a file

  • let us add Groups

  • let us search for a specific Group based on the ID or Name

  • let us display all Groups

  • let us find the Albums of a given Group after a given Year

  • let us find the best-selling Album of a given Group

  • let us sort the Group’s Alphabetically

All of those Options will be accessed with a switch case statement inside of an infinite while loop.

All of the Options need to be called via Function.

The groups.txt should look like this:

2 //this is the group_count

100 Scorpions 1965 //group 1 information

Blackout 1982 1100000 //album 1 information of group 1

Sting_in_the_tale 2010 18500 //album 2 information of group 1

101 Dive_Straits 1977   //group 2 information

Making_Movies 1980 1000000 //album 1 information of group 2

Brother_in_arms 1985 9000000 //album 2 information of group 2

#include <stdio.h> //input output

#include <stdlib.h> //malloc, realloc

#include <string.h> //strcmp 

//Defining Structs Album and Group

typedef struct{

	char album_name[21];

	int release_year;

	long int sales;

}Album;

typedef struct{

	int group_id;

	char group_name[21];

	int year;

	Album album[2]; //2 albums to make it easier

}Group;

//Function Declaration

Group* load_groups_from_file(Group *group, int *group_count);

void save_groups_to_file(Group *group, int group_count);

Group* add_group_to_struct(Group *group, int *group_count);

void search_group_id(Group *group,int temp, int group_count);

void search_group_name(Group *group, char buf[], int group_count);

void print_groups(Group *group, int group_count);

void find_album_after_year(Group *group, int temp, int search);

void find_best_selling_album(Group *group, int search);

Group* sort_groups(Group *group, int group_count);

int input_group_pos(Group *group, int group_count);

int main(){

	int group_count = 0;//group count

	int a;				//switch case variable

	Group *group;		//dynamic array of struct group

	char buf[50];		//for string input

	long int temp;		//for integer input

	int search;			//for searching at case 7 and 8

	while(1){	//infinite loop

		system("cls"); //clear the console

		//print menu

		printf("1\. Load groups from file\n");

		printf("2\. Save groups to file\n");

		printf("3\. Add a group\n");

		printf("4\. Search/Display a group by group id\n");

		printf("5\. Search/Display a group by group name\n");

		printf("6\. Display all groups\n");

		printf("7\. Find the albums of a given group after a given year\n");

		printf("8\. Find the best-selling album of a given group\n");

		printf("9\. Sort group array by group name\n");

		printf("0\. Exit\n");

		printf("Choice: ");

		scanf("%d", &a);		

		switch (a){

			case 0:

				exit(0); //terminate programm

			case 1:	//open file "groups.txt" and copy the groups into the array

				group = load_groups_from_file(group, &group_count); //because group_count is not a pointer we pass it's address

				break;	

			case 2:	//one file "groups.txt" and save the groups into the file

				save_groups_to_file(group, group_count);

				break;							

			case 3:	//add new group into the group array

				group = add_group_to_struct(group, &group_count);

				break;						

			case 4:	//search and display group with this specific id

				printf("Give a ID: ");

				scanf("%d",&temp);

			    search_group_id(group, temp, group_count);

				break;			

			case 5:	//search and display group with specific name

				printf("Give a Groupname: ");

				scanf("%49s",buf);

				search_group_name(group, buf, group_count);

				break;

			case 6:	//diplay all groups

				print_groups(group, group_count);

				break;	

			case 7:	//display all album of an group after a specific date

				search=input_group_pos(group, group_count);

				if(search == -1){

					printf("No Groups Added!\n");

					break;

				}

				printf("Give a Year: ");

				scanf("%d",&temp);

				find_album_after_year(group, temp, search);

				break;			

			case 8:	//display album of specific group with best sales out of the 2

				search=input_group_pos(group, group_count);

				if(search == -1){

					printf("No Groups Added!\n");

					break;

				}

				find_best_selling_album(group, search);			

				break;		

			case 9:	//sort the groups alphabetically

				group = sort_groups(group, group_count);

				break;						

			default:{

				printf("You must select something from above!!!\n");

				break;

			}

		}

		sleep(2); //sleep for 2 seconds

	}		

}

//FUNCTIONS

Group* load_groups_from_file(Group *group, int *group_count){

	int i;

	FILE *fp; //file pointer to read from "groups.txt"

	if((fp = fopen("groups.txt", "r")) == NULL){ //checking if file exists

		perror ("groups.txt");

		return group;

	}

	fscanf(fp, "%d", group_count); //read group_count as pointer doesn't need &

	group = (Group*)malloc(*group_count * sizeof(Group)); //we need *group_count cause it's a pointer

	for(i=0; i<*group_count; i++){

		fscanf(fp, "%d %s %d", &group[i].group_id, group[i].group_name, &group[i].year);

		fscanf(fp, "%s %d %ld", group[i].album[0].album_name, &group[i].album[0].release_year, &group[i].album[0].sales);

		fscanf(fp, "%s %d %ld", group[i].album[1].album_name, &group[i].album[1].release_year, &group[i].album[1].sales);

	}

	return group;	

}

void save_groups_to_file(Group *group, int group_count){

	int i;

	FILE *fp; //file pointer to write into "groups.txt"

	fp = fopen("groups.txt", "w"); //for saving you don't need to check existance cause it will create it

	fprintf(fp, "%d\n", group_count);

	for(i=0; i<group_count; i++){

		fprintf(fp, "%d %s %d\n", group[i].group_id, group[i].group_name, group[i].year);

		fprintf(fp, "%s %d %ld\n", group[i].album[0].album_name, group[i].album[0].release_year, group[i].album[0].sales);

		fprintf(fp, "%s %d %ld\n", group[i].album[1].album_name, group[i].album[1].release_year, group[i].album[1].sales);

	}			

	fclose(fp);

}

Group* add_group_to_struct(Group *group, int *group_count){

	long int temp;

	char buf[50];

	if(*group_count == 0){ //if it was not created it needs malloc

		group = (Group*)malloc( (*group_count + 1) * sizeof(Group) );

	}else{

		group = (Group*)realloc(group, (*group_count + 1) * sizeof(Group));

	}

	printf("Group ID: ");

	scanf("%d",&temp);

	group[*group_count].group_id=temp;

	do {

	printf("Groupname: ");

	scanf("%49s",buf);

	} while(strlen(buf)>=20);

	strcpy(group[*group_count].group_name, buf);

	printf("Foundation Year: ");

	scanf("%d",&temp);

	group[*group_count].year=temp;

	printf("Now give 2 Albums in this Order: Name Release_Date Sale_Count\n");

	printf("Album 1: \n");

	scanf("%19s %d %ld", group[*group_count].album[0].album_name, &group[*group_count].album[0].release_year, &group[*group_count].album[0].sales);

	printf("Album 2: \n");

	scanf("%19s %d %ld", group[*group_count].album[1].album_name, &group[*group_count].album[1].release_year, &group[*group_count].album[1].sales);

	(*group_count)++; //increment group_count

	return group;

}

void search_group_id(Group *group, int temp, int group_count){

	int i;

	if(group_count == 0){ //checking emptyness

		printf("No Groups Added!\n");

		return;

	}

	for(i=0; i<group_count; i++){

		if(temp==group[i].group_id){

			printf("%d %s %d\n", group[i].group_id, group[i].group_name, group[i].year);

			printf("%s %d %ld\n", group[i].album[0].album_name, group[i].album[0].release_year, group[i].album[0].sales);

			printf("%s %d %ld\n", group[i].album[1].album_name, group[i].album[1].release_year, group[i].album[1].sales);

			printf("\n");			

			break;	

		}

	}

	if(i==group_count) printf("No Group has this ID!\n");

}

void search_group_name(Group *group, char buf[], int group_count){

	int i;

	if(group_count == 0){ //checking emptyness

		printf("No Groups Added!\n");

		return;

	}

	for(i=0; i<group_count; i++){

		if( strcmp(buf, group[i].group_name)==0 ){

			printf("%d %s %d\n", group[i].group_id, group[i].group_name, group[i].year);

			printf("%s %d %ld\n", group[i].album[0].album_name, group[i].album[0].release_year, group[i].album[0].sales);

			printf("%s %d %ld\n", group[i].album[1].album_name, group[i].album[1].release_year, group[i].album[1].sales);

			printf("\n");

			break;

		}

	}

	if(i==group_count) printf("No Group has this Name!\n");

}

void print_groups(Group *group, int group_count){

	int i;

	if(group_count == 0){ //checking emptyness

		printf("No Groups Added!\n");

		return;

	}

	printf("Groups: \n");

	for(i=0; i<group_count; i++){

		printf("%d %s %d\n", group[i].group_id, group[i].group_name, group[i].year);

		printf("%s %d %ld\n", group[i].album[0].album_name, group[i].album[0].release_year, group[i].album[0].sales);

		printf("%s %d %ld\n", group[i].album[1].album_name, group[i].album[1].release_year, group[i].album[1].sales);

		printf("\n");

	}	

}

void find_album_after_year(Group *group, int temp, int search){

	int i;

	for(i=0; i<2; i++){

		if(group[search].year>=temp){

			printf("%s %d %ld\n", group[search].album[i].album_name, group[search].album[i].release_year, group[search].album[i].sales);

		}

	}

}

void find_best_selling_album(Group *group, int search){

	if(group[search].album[0].sales>group[search].album[1].sales){

		printf("%s %d %ld\n", group[search].album[0].album_name, group[search].album[0].release_year, group[search].album[0].sales);

	}

	else{

		printf("%s %d %ld\n", group[search].album[1].album_name, group[search].album[1].release_year, group[search].album[1].sales);

	}

}

Group* sort_groups(Group *group, int group_count){

	int i,j;

	Group swap;

	if(group_count == 0){ //checking emptyness

		printf("No Groups Added!\n");

		return group;

	}

	for(i=0; i<group_count; i++){

		for(j=0; j<group_count; j++){

			if( strcmp(group[j].group_name, group[i].group_name)>0 ){

				swap=group[i];

				group[i]=group[j];

				group[j]=swap;				

			}

		}

	}

	return group;

}

int input_group_pos(Group *group, int group_count){

	int i;

	int search;

	char buf[50];

	if(group_count == 0){ //checking emptyness

		return -1;

	}

	do {	

		printf("Give Groupname: ");

		scanf("%49s",buf);

		search=0;

		for(i=0; i<group_count; i++){

			if( strcmp(buf, group[i].group_name)==0 ){

				search=i;

				break;

			}

		}

		if(search==0) printf("No Group has this Name!\n");

	} while(search==0);

	return search;

}

You can see that I return a pointer everytime I change something in the dynamic struct array. You could also do it via reference (using **group instead of *group) and using *something and passing the address of the pointer(!) when calling the function. But, to make it simple let’s stick with returning cause it’s more C-Like and putting it by reference is easier in Object-oriented Programming like Java or C#, cause working with pointer’s is difficult and knowning when to put &, * or nothing at a scanf or printf statement gets a little difficult.


C Language


Basics


Beginner Codes

C Beginner Codes

Beginner Arrays

C Beginner Arrays

Pointers, Strings and Files

C Pointers, Strings and Files

Dynamic Memory Allocation

C Dynamic Memory Allocation

Structs and Switch Case

C Structs and Switch Case


Datastructures


Recursive Algorithms

C Recursive Algorithms

Linked Lists

C Linked Lists

Binary Trees

C Binary Trees

Queues using Arrays

C Queues using Arrays

Stacks using Arrays

C Stacks using Arrays

Queues using Linked Lists

C Queues using Linked Lists

Stacks using Linked Lists

C Stacks using Linked Lists

Advanced Lists and Queues

C Advanced Lists and Queues

Advanced Trees

C Advanced Trees

Stack-Queue Exercise using Dynamic Arrays

C Stack-Queue Exercise using Dynamic Arrays

Stack-Queue Exercise using Linked Lists

C Stack-Queue Exercise using Linked Lists

Hashtables with Chaining

C Hashtables with Chaining

Hashtables with Linear Probing

C Hashtables with Linear Probing


Other


Can I Run A Dual Monitor Setup

C Can I Run A Dual Monitor Setup

Function Comparison

C Function Comparison