How to go back from switch menu - c

I want to make a menu that classifies animals into insects, birds, mammals and fishes with specific characteristics for each of these (using composite variables). I thought I'd use a nested switch case(one switch for the category of the animals and another switch for each category to perform the actions). The problem is, after I've entered a new entry for instance, I wanna have the option to go back and pick another action or even go back and pick another category. How can I do that? I tried with a do-while but I'm just getting an endless loop.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct{
unsigned int noLegs, lifeSpan;
char *name;
}insect;
typedef struct{
float speed, length;
char *habits, *name;
}bird;
typedef struct{
float weight, height;
char *food, *name;
}mammal;
typedef struct{
float weight, depth, salt;
char *name;
}fish;
int main(int argc, char **argv)
{
char choice, action;
bool running = true;
bool returnBack = true;
insect *i = (insect *)malloc(sizeof(insect));
if(!i)
{
printf("Failed to allocate memory.\n");
return -1;
}
while(running)
{
printf("Please choose a category:\n");
printf("1. Insects\n2. Birds\n3. Mammals\n4. Fishes\n5. Exit\n");
scanf(" %c", &choice);
switch(choice)
{
case '1':
printf("You've chosen: Insects\n");
while(returnBack)
{
printf("Please choose an action:\n");
printf("a. Add entry\nb. Delete entry\nc. Replace entry\nd. Lookup entries\ne. Back\n");
scanf(" %c", &action);
switch(action)
{
case 'a':
printf("What entry would you like to add?\n");
i->name = (char *)malloc(sizeof(char));
scanf("%s", i->name);
printf("How many legs does a %s have?\n", i->name);
scanf("%u", &(i->noLegs));
printf("What is the lifespan of a %s?\n", i->name);
scanf("%u", &(i->lifeSpan));
break;
case 'b':
printf("Which entry would you like to delete?\n");
break;
case 'c':
printf("Which entry would you like to replace?\n");
break;
case 'd':
printf("Which entry would you like to replace?\n");
break;
case 'e':
returnBack = false;
break;
default:
printf("Invalid action.\n");
}
}
break;
case '2':
printf("You've chosen: Birds\n");
break;
case '3':
printf("You've chosen: Mammals\n");
break;
case '4':
printf("You've chosen: Fishes\n");
break;
case '5':
running = false;
break;
default:
printf("Invalid choice.\n");
}
}
return 0;
}

As said by alex01011, you just need a while over the whole switch
When the user selects 5 running becomes FALSE and the loop exits.
One thing though, you forgot to clear the whitespace in the first scanf()
#include <stdio.h>
#include <stdlib.h>
#define TRUE (1==1)
#define FALSE (!TRUE)
/* ...
* ALL THE STRUCTS
*/
int main(int argc, char **argv)
{
char choice, action, running = TRUE;
insect *i = (insect *)malloc(sizeof(insect));
// CHECK ON MALLOC RETURN
while(running)
{
printf("Please choose a category:\n");
printf("1. Insects\n2. Birds\n3. Mammals\n4. Fishes\n5. Exit\n\n");
scanf(" %c", &choice); // <-- The leading space was missing
switch(choice)
{
/* ...
* PREVIOUS CASES
*/
case '5':
running = FALSE;
break;
default:
printf("Invalid choice.\n");
}
}
return 0;
}

Related

returning a structure in a function using typedef struct

im trying to return a struct into main using the function addMovie that i have made please ignore the rest of the code this would only be applicable to case "a" of main. and when i apply to main does it have to be in a separate struct? how else would i be able to export it to main ? it needs to be saved to an array of stucture out of 100 which is defined at the top. the line return new; is giving me error
#include <stdio.h>
#include <conio.h>
#define CONST 100
void sortMovies(struct movies[]);
void changeMovie(struct movie[]);
int findMovie(struct movies[], int nOfMovies, struct movies[].UPC);
struct movies newMovie();
typedef struct {
char title[30];
char UPC[12];
int qnty;
double price;
}movies;
int main()
{
int nOfMovies = 0, findR, stop = 0;
char decider;
while (stop != 1)
{
movies main[CONST];
movies tempMovie;
printf("(A)dd a new movie\n(C)hange a Movie's Information \n(D)elete a Movie \n(L)ist All Movies\n(Q)uit");
scanf(" %c", &decider);
switch (decider)
{
case 'a':
case 'A':
tempMovie = newMovie();
nOfMovies = findMovie(movies[], nOfMovies, movies[].UPC);
nOfMovies++;
break;
case 'c':
case 'C':
printf("enter movie upc:");
scanf("%c", movies.UPC);
findR = findMovie(movies, nOfMovies, movie.UPC);
break;
case 'd':
case 'D':
findR = findMovie(movie, nOfMovies, movie.UPC);
if (findR != -1)
{
printf("are you sure?");
case 'y':
case 'Y':
break;
default:
printf("An invalid option was selected!");
}
break;
case 'l':
case 'L':
sortMovies(movie);
break;
case 'q':
case 'Q':
return 0;
break;
default:
printf("An invalid option was selected!");
}
}
}
struct movies newMovie() {
movies new;
printf("enter movie upc:");
scanf("%c", new.UPC);
printf("enter movie title:");
scanf("%c", new.title);
printf("enter movie qauntity:");
scanf("%d", new.qnty);
if (new.qnty <= 0)
{
printf("quanitity must be greater than 0");
printf("enter movie qauntity:");
scanf("%d", new.qnty);
}
printf("enter movie price:");
scanf("%lf", new.price);
if (new.price <= 0)
{
printf("price must be greater than 0");
printf("enter movie price:");
scanf("%lf", new.price);
}
return new;
}```

How to make a member of a struct dynamic

Say I have a struct of something and I want to make its members dynamic. I think the members should be something like this
char* id;
.....
following by a malloc to each member like this
books->id=(char*) malloc(size);
thou it seems when I try it my program crashed so I'm trying to understand what am I doing wrong
This is the part that I think that is relevant to my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxsize 512
typedef struct Books {
char *id;
char title[maxsize];
char author[maxsize];
char pages[maxsize];
char year[maxsize];
char subject[maxsize];
} book;
char* filename;
int libsize=4;
int bookcount=1;
...
int main(int argc, char* argv[]){
if (argc < 1)
return -1;
filename=argv[1];
FILE* fptr;
char tempstring[maxsize],* token;
int i=0,ch;
book *books;
fptr=fopen(filename,"r");
if(fptr==NULL)
return-1;
//this count how many books are in the file
while(ch!= EOF){
ch=fgetc(fptr);
if(ch == '\n')
++bookcount;
}
fclose(fptr);
while(libsize<bookcount){
libsize *= 1.5;
}
books = (book*) malloc(libsize*sizeof(book));
if(books==NULL)
exit(-1);
books->id=(char*)malloc(100);
fptr=fopen(filename,"r");
if(fptr==NULL)
return-1;
//this gets all the books into the book array
for(i=0;i<bookcount;i++){
fgets(tempstring,maxsize,fptr);
token=strtok(tempstring,",");
strcpy(books[i].id,token);
token=strtok(NULL,",");
strcpy(books[i].title,token);
token=strtok(NULL,",");
strcpy(books[i].author,token);
token=strtok(NULL,",");
strcpy(books[i].pages,token);
token=strtok(NULL,",");
strcpy(books[i].year,token);
token=strtok(NULL,",");
strcpy(books[i].subject,token);
}
fclose(fptr);
printf("to add a book press 1\n");
printf("to delete a book press 2\n");
printf("to find a book press 3\n");
printf("to print all books press 4\n");
printf("to save library in a file press 5\n");
printf("to add books from a file press 6\n");
printf("to exit press 0\n");
pick(books);
return 1;
}
void pick(book books[]){
char input;
scanf("%c",&input);
switch (input){
case '1':
addbook(books);
break;
case '2':
delbook(books);
break; //pretty sure break isnt needed but it works so...eh
case '3':
srchbook(books);
break;
case '4':
printbooks(books);
break;
case '5':
printbooksf(books);
break;
case '6':
addbookf(books);
break;
case '0':
free(books);
exit (1);
case '\n':
pick(books);
default:
printf("please enter a valid command\n");
pick(books);
break;
}
}
edit2: added more of the code
edit3: found what was the problem what i did was trying to get to the pointer itself (i think) so the system flipped when i try to did it.
what i should have done was getting to each member array of the struct like that
for(i=0;i<bookcount;i++){
books[i].id=(char*)malloc(charcount);
books[i].title=(char*)malloc(charcount);
books[i].author=(char*)malloc(charcount);
books[i].pages=(char*)malloc(charcount);
books[i].year=(char*)malloc(charcount);
books[i].subject=(char*)malloc(charcount);
}
and not
books->id .....
You only malloc memory for id once. You need to do it for each book:
Like:
// books->id=(char*)malloc(100); Remove this line
fptr=fopen(filename,"r");
if(fptr==NULL)
return-1;
//this gets all the books into the book array
for(i=0;i<bookcount;i++){
fgets(tempstring,maxsize,fptr);
token=strtok(tempstring,",");
books[i].id=(char*)malloc(100); // Add this line
strcpy(books[i].id,token);
BTW
This code seems strange:
while(libsize<bookcount){
libsize *= 1.5;
}
books = (book*) malloc(libsize*sizeof(book));
why not simply do:
books = (book*) malloc(bookcount*sizeof(book));
(note: you don't need to cast malloc)

Im having issues with the redefintion of "fptr"

The 15th line is what I cant fix. Please be kind enough to look at my code and diagnose the issue. I am new to programming and will appreciate anyone pointing me in the right direction.
#include <stdio.h>
#include <stdlib.h>
#define TEAMS 200
#define RUNNERS 10000
#define LENGTH 20
#define TEAMSIZE 50
FILE *fptr;
fptr = fopen("myfile.txt","w");
void getdetails();
struct person {
char name[LENGTH];
int number;
int age;
int event;
float money;
float time;
}p;
struct team {
char tname[LENGTH];
int nummembers;
float money;
struct person members[TEAMSIZE];
}t;
int main() {
int c,flag=0,i=0,j,k=0;
printf("\n---------------------------------------------------");
printf("\n---------------------------------------------------");
printf("\nHeader Specification");
while(flag==0) {
printf("\n1.Individual Registration");
printf("\n2.Team Registration");
printf("\n3.Running Events");
printf("\n4.Donation Totals");
printf("\n5.Exit");
printf("\nEnter your choice:");
scanf("%d",&c);
switch(c) {
case 1:
printf("\n For Individual Registration");
printf("\n1.Early Registration");
printf("\n2.regular Registration");
int ch;
printf("\nEnter your choice:");
scanf("%d",&ch);
switch(ch) {
case 1:
printf("\n For Early Registration");
i=i+1;
getdetails(i);
break;
case 2:
printf("\n For Early Registration");
i=i+1;
getdetails(i);
break;
default:
printf("\n not valid");
break;
}
break;
case 2:
printf("\n For Team Registration");
printf("\n Enter team name:");
scanf("%s",t.tname);
printf("\n Enter team participant number:");
scanf("%d",&t.nummembers);
k=k+1;
for(j=1;j<=t.nummembers;j++) {
getdetails(k);
}
break;
case 5:
flag=1;
break;
}
}
return 0;
}
void getdetails(int i) {
printf("Enter your name:");
scanf("%s",p.name);
printf("Enter your age:");
scanf("%d",&p.age);
printf("Enter the event:");
scanf("%d",&p.event);
printf("Enter the donation amount:");
scanf("%f",&p.money);
if(fptr == NULL) {
printf("Error!");
exit(1);
}
fprintf(fptr,"\n%s register for\t%dk race\tand the number is%d.",p.name,p.event,i);
fclose(fptr);
}
A runtime-executable statement, like
fptr = fopen("myfile.txt","w");
cannot reside in global scope. It has to reside in block scope, i.e., in some function body.

C program compiles in xcode, but runs infinite loop in terminal

I've been working on a group program for a systems programming class which will run functions that someone at a bank would use. These functions include add bank customers, output balance of a customer, and so on. The problem lies with the add customer function.
This function will run in an infinite loop in terminal and Putty, but when I run it as a standalone program in XCode the loop quits. Is there anything wrong with the program that I, my group members AND our professor are overlooking?
#include <stdio.h>
#include <string.h>
#include "./bank.h"
void add(FILE *fp)
{
int i=0;
char firstName[20];
char lastName[20];
float camount;
int prompt;
float samount;
float mamount;
fseek(fp,0,2);
do
{
printf("\nEnter first name: ");
scanf("%s", firstName);
strcpy(bank[i].firstName, firstName);
printf("\nEnter last name: ");
scanf("%s",lastName);
strcpy(bank[i].lastName, lastName);
printf("\nEnter checking account balance: ");
scanf("%f", &camount);
bank[i].checking = camount;
printf("\nEnter savings account balance: ");
scanf("%f", &samount);
bank[i].savings = samount;
printf("\nEnter money market account balance: ");
scanf("%f", &mamount);
bank[i].moneyMarket = mamount;
fwrite(&bank[i],1, sizeof(struct BankInfo),fp);
i++;
printf("Enter 1 to enter another name and 0 to quit: ");
scanf("%d", &prompt);
printf("%d\n", prompt);
} while(prompt == 1);
fclose(fp);
return;
}
Screenshot of output once Makefile is executed:
Sidenote: This function does write onto the file that we are passing which is great but we still need for it to break out of the loop.
EDIT: code for the main function:
#include
#include
#include
#include "bank.h"
#include "definitions.h"
int main()
{
FILE *fp;
int selection;
fp=fopen("bankInfo.dat","ab+");
selection=menu();
while(selection !=6)
{
switch(selection)
{
case 1:
add(fp);
break;
case 2:
// outputBalance(fp);
break;
case 3:
delete(fp);
break;
case 4:
update(fp);
break;
case 5:
// display(fp);
break;
case 6:
exit(0);
break;
default:
printf("Invalid selection\n");
break;
}
}
fclose(fp);
return 0;
}
You are assigning selection only once. This should fix your issue:
while(true)
{
selection=menu();
switch(selection)
{
case 1:
add(fp);
break;
case 2:
// outputBalance(fp);
break;
case 3:
delete(fp);
break;
case 4:
update(fp);
break;
case 5:
// display(fp);
break;
case 6:
fclose(fp);
exit(0);
break;
default:
printf("Invalid selection\n");
break;
}
}
return 0;

Process Returned -1073741819 (0xc0000005) Code::Blocks

I'm kind of new to programming C with Code::Blocks(Version 12.11), started this semester in my college, but I manage.
I recently learned in class about pointers, memory allocation and dynamic arrays(none are my forte), and I incorporated them in my program(and it compiles)
Now the problem comes when I run the Program and go to Menu -> Add a Product, the program terminâtes when I input a price and I receive "Process Returned -1073741819 (0xc0000005)".
I did some research and found out it's an access violation but I don't really understand how to correct it.
Regards
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxCharName 64
#define maxCharUserPass 8
#define maxCharId 5
// Product Structure
typedef struct{
char name[maxCharName];
char idCode[maxCharId];
float price;
float stock;
}product;
// DataBase of Products
typedef struct{
int sizeT;
product *array;
} TProducts;
TProducts a;
// Press any Key on the Keyboard to Proceed
void pressKeyToContinue(){
puts("\n\n\n Please Press any Key to Continue...");
getchar();
}
// Start Page
void startPage(){
puts("\n\n\n -- Welcome to WeePro Manager --\n\n");
puts(" -- Version 1.0 --\n\n\n\n");
puts(" -- Developped By: Nick --");
pressKeyToContinue();
system("cls");
}
// Program Terminator
void shutdown(){
puts("\n\n\n Good-Bye");
pressKeyToContinue(); // Awaits User Input
exit(0);
}
// Asks User Information for Verification
int userLogin(){
char userName[maxCharUserPass] = "WPuser";
char inputUserName[maxCharUserPass];
char passWord[maxCharUserPass] = "12345";
char inputPassWord[maxCharUserPass];
printf("Username? ");
scanf("%s",inputUserName); fflush(stdin);
printf("Password? ");
scanf("%s", inputPassWord); fflush(stdin);
system("cls");
if((strcmp(userName, inputUserName) == 0)&&(strcmp(passWord, inputPassWord) == 0)){
return 1;
}else{ return 0;}
}
// Lists All Products With their Respective Information
void listAll(){
int idx = 0;
puts("List:");
while((idx < a.sizeT)&&(a.array[idx].name != NULL)){
printf(":::%s ( id: %s )", a.array[idx].name, a.array[idx].idCode);
printf("Price: %6.2f eur/g", a.array[idx].price);
printf("Stock: %6.2f g", a.array[idx].stock);
idx++;
}
pressKeyToContinue();
system("cls");
}
// Input Product ID Code
char* inputIdCode(){
char* tempIdCode;
puts("ID Code?");
scanf("%s", tempIdCode);
system("cls");
return tempIdCode;
}
// Search By ID Code
int searchIdCode(){
int idx = 0;
char* tempIdCode;
tempIdCode = inputIdCode();
do{
if(strcmp(a.array[idx].idCode, tempIdCode) == 0){
return idx;
}else{
idx++;
}
}while(idx < a.sizeT);
puts("No Product With Such an ID Code!");
return -1;
}
// Input Product Name
char *inputProductName(int length){
char name[maxCharName];
puts("Product Name?");
scanf("%s", name); fflush(stdin);
system("cls");
return name;
}
// Input Product Price
float inputProductPrice(int length){
float price;
puts("Product Price?");
scanf("%f", price); fflush(stdin);
system("cls");
return price;
}
// Input Product Stock
float inputProductQuantity(int length){
float quantity;
puts("Product Stock?");
scanf("%f", quantity); fflush(stdin);
system("cls");
return quantity;
}
/////////////////
// Add Product //
/////////////////
// New Product Adder
void addProduct(){
char* tempStr;
float temp;
if(a.sizeT == 0){
a.sizeT = 1;
a.array = (product*)malloc((a.sizeT)*sizeof(product));
}else{
a.sizeT++;
a.array = (product*)realloc(a.array, (a.sizeT)*sizeof(product));
}
tempStr = inputProductName(a.sizeT);
strcpy(a.array[a.sizeT].name, tempStr);
temp = inputProductPrice(a.sizeT);
temp = inputProductQuantity(a.sizeT);
system("cls");
}
void transaction(){}
////////////////////
// Delete Product //
////////////////////
// Delete Product
void deleteProduct(){
int idx, idxPro;
char* tempIdCode;
puts("Delete Which Product?\n");
tempIdCode = inputIdCode();
idxPro = searchIdCode(tempIdCode);
idx = idxPro + 1;
while(idx < a.sizeT){
a.array[idx] = a.array[idx+1];
idx++;
}
a.array = realloc(a.array, (a.sizeT-1)*sizeof(product));
}
//Product Information Modifier
void modifyProduct(){
char choice;
int tabLength;
do{
puts("Modify What?\n");
puts(" -> [N]ame\n");
puts(" -> [P]rice\n");
puts(" -> [S]tock\n\n");
puts(" -> [R]eturn to Previous Menu"); // Prints the Menus' Options
scanf("%c", &choice);
choice = toupper(choice); // Save Users' Choice And Up Case
fflush(stdin);
switch(choice){
case 'N':
system("cls");
tabLength = searchIdCode();
inputProductName(tabLength);
break;
case 'P':
system("cls");
tabLength = searchIdCode();
inputProductPrice(tabLength);
break;
case 'S':
system("cls");
tabLength = searchIdCode();
inputProductQuantity(tabLength);
break;
case 'R':
system("cls");
returnToMenu2();
break;
default:
puts("Something Went Wrong!\n");
pressKeyToContinue();
system("cls");
}
}while(choice != 'o');
}
// Sub-Menu Interface
void menu(){
char choice;
do{
puts("Please Make Your Selection.\n");
puts(" -> [A]dd a New Product\n");
puts(" -> [M]odify a Product\n");
puts(" -> [D]elete a Product\n\n");
puts(" -> [R]eturn to Main Menu"); // Prints the Menus' Options
scanf("%c", &choice); fflush(stdin);
choice = toupper(choice); // Save Users' Choice And Up Case
switch(choice){
case 'A':
system("cls");
addProduct();
break;
case 'M':
system("cls");
modifyProduct();
break;
case 'D':
system("cls");
deleteProduct();
break;
case 'R':
system("cls");
returnToMenu1();
break;
default:
puts("Something Went Wrong!\n");
pressKeyToContinue();
system("cls");
}
}while(choice != 'o');
}
// Return To Ma
> Blockquote
in Menu
void returnToMenu2(){
menu();
}
// Main Menu
void controlPanel(){
char choice;
do{
puts("Please Make Your Selection.\n");
puts(" -> [T]ransaction\n");
puts(" -> [M]enu\n");
puts(" -> [L]ist\n");
puts(" -> [S]hutdown"); // Prints the Panels' Options
scanf("%c", &choice); fflush(stdin);
choice = toupper(choice); // Save Users' Choice And Up Case
switch(choice){
case 'T':
system("cls");
transaction();
break;
case 'M':
system("cls");
menu();
break;
case 'L':
system("cls");
listAll();
break;
case 'S':
system("cls");
shutdown();
break;
default:
puts("Something Went Wrong!\n");
pressKeyToContinue();
system("cls");
}
}while(choice != 'o');
}
// Return To Main Menu
void returnToMenu1(){
controlPanel();
}
int main(){
int loginSuccess=1;
//loginSuccess = userLogin();
switch(loginSuccess){
case 0:
shutdown();
break;
case 1:
startPage();
controlPanel();
break;
}
}
An attempt is being made to write to randon memory, via the uninitialized pointer tempIdCode:
char* inputIdCode(){
char* tempIdCode;
puts("ID Code?");
scanf("%s", tempIdCode);
system("cls");
return tempIdCode;
}
You need to allocate memory for tempIdCode before attempting to write to it. You must use malloc() here (and not return the address of a local array):
char* tempIdCode = malloc(20);
if (tempIdCode)
{
/* The format specifier "%19s" instructs scanf()
to read at most 19 characters, one less than
allocated to allow for terminating null character
written by scanf(), to prevent potential buffer
overrun. */
scanf("%19s", tempIdCode);
}
The caller of the function must explicitly check for a return NULL pointer. The caller must also free() the allocated memory.
This is a killer:
// Input Product Name
char *inputProductName(int length){
char name[maxCharName];
puts("Product Name?");
scanf("%s", name); fflush(stdin);
system("cls");
return name;
}
The reference returned by this function points to an already freed block of memory on the stack, as char name is only valid as long the program is inside the function name is declared in.
When leaving the function name is freed automagically, so any dereferencing of the function's result leads to UB, as it most propably will be accessing unallocated memory.
To solve this you might like to pass in a buffer, where to read the data into:
// Input Product Name
char * inputProductName(int length, char * name){
puts("Product Name?");
scanf("%s", name); fflush(stdin);
system("cls");
return name;
}
and call it like this:
// New Product Adder
void addProduct(){
char* tempStr;
float temp;
if(a.sizeT == 0){
a.array = malloc((a.sizeT)*sizeof(product));
}else{
a.array = realloc(a.array, (a.sizeT)*sizeof(product));
}
a.sizeT++;
inputProductName(a.sizeT, a.array[a.sizeT].name);
...

Resources