Switch statement with strings? - c

I'm working on a small homework assignment and I'm supposed to make a food menu. Anyways, my switch isn't working. I'm trying to use a simple function that I can pass a value of "fish", "drink", or "chips" to and then it will output:
"Are you ordering FISH?" (or chips/drink)
I can't get the switch to work, it's supposed to detect what I pass into it and then output a printf based on the switch case.
CODE:
#include <stdio.h>
void menu() {
printf("\nWelcome to Sunny FISH & CHIPS!\n\n");
printf("######## Fish : Haddock(K) Large(L) | $5.00\n");
printf("# FOOD # Halibut(T) Large(L) | $4.00\n");
printf("######## Chips: Cut(C) Large(L) | $2.00\n");
printf(" Ring(R) Large(L) | $3.00\n");
printf(" | \n");
printf("########## Soft Drinks(S) Large(L) | $2.00\n");
printf("# DRINKS # Coffee(C) Large(L) | $1.75\n");
printf("########## Tea(T) Large(L) | $1.50\n");
printf("---------------------------------------------\n");
printf("Note: Medium price: 80%% of large.\n");
printf(" Small price: 60%% of large.\n");
printf("TAX is 10%%.\n");
printf("More than 5 fish, 10%% discount on drink.\n");
printf("Every 10 fish purchased, get 1 free softdrink.\n");
printf(" - size of drink is according to size of fish\n");
}
void question (char choice[5]) {
switch (choice[5])
{
case choice["fish"]:
printf("Do you order FISH?\n");
case choice["drink"]:
printf("Do you order CHIPS?\n");
case choice["chips"] :
printf("Do you order DRINKS?\n");
default :
printf("Enter a valid choice: \n");
}
}
main() {
// menu();
question("fish");
}

C does not support that kind of switch, but if it would, the syntax would be
switch(choice)
{
case "fish":
something();
break;
case "drink":
other_thing();
break;
}
A switch to me is often clearer than a (long) list of if - else ifs. Even though in this case it seems overcomplicated, I would prefer approaches like this:
#include <stdio.h>
#include <string.h>
enum menu_items { FISH, DRINK, CHIPS, UNKNOWN };
struct items
{
char *name;
enum menu_items id;
} items_list[] = {
{ "fish", FISH },
{ "drink", DRINK },
{ "chips", CHIPS }
};
int main(void)
{
int i;
enum menu_items mid;
struct items *choice = NULL;
// ...
for(i = 0, choice = NULL; i < sizeof items_list/sizeof (struct items); i++)
{
if (strcmp(answer, items_list[i].name) == 0)
{
choice = items_list + i;
break;
}
}
mid = choice ? choice->id : UNKNOWN;
// the following would be enough to obtain the output of your example;
// I've not embodied the code into a func, but it's easy to do if you need
if ( mid != UNKNOWN )
{
// the function a_func transforms the string of the food
// e.g. to uppercase, or it could map it to whatever according to some
// other data... or expand the struct to hold what you want to output
// with "fish", "drink", "chips", e.g. choice->screen_name
printf("Do you order %s?\n", a_func(choice->name));
}
else
{
printf("Enter a valid choice:\n");
}
// ---------
// or if you prefer the switch you have something like:
switch(mid)
{
case FISH:
printf("fish\n");
break;
case DRINK:
printf("drink\n");
break;
case CHIPS:
printf("chips\n");
break;
default:
printf("unknown choice\n");
break;
}
return 0;
}
If you choose properly the approach, your code could be always the same and only your data grow.

In addition to the other answers, if you find that your list of choices all begin with a unique letter (or have a unique letter in another position) then you can switch on that letter:
switch (choice[0]) {
case 'f':
// they chose fish
break;
case 'c':
// they chose chips
break;
case 'd':
// they chose drink
}
This will be faster than using strcmp (although it doesn't matter for your case) and is less maintainable. However, it's good to know all the options and realise how you can use some of these things.

You cannot use switch statement with strings.
You may consider using strcmp to compare strings.
if (strcmp(choice,"fish")==0) {
//fish
}
else if (strcmp(choice,"drink")==0) {
//drink
}
.
.
.

C doesn't support switches on strings...you should use strcmp()

switch doesn't work like that in C. You'll need to make an if statement construct and use strcmp() to compare the strings.

Related

Make a 2D array in a struct, store strings inside array

I have to make a library system using structs and pointers, that registers a person with their name, ID, phone number, and the name of the books (maximum 3). I have created a struct for every borrower, and I am trying to store input taken by the user, specifically at the part of getting the book titles, to store into an array of other structs (for other borrowers). I have to be able to free the locations of the borrowers once they return all books, so I'd have to use dynamic memory for that.
This is the code I have so far, not sure how exactly I would go about storing every borrower using pointers.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_NAME_SZ 256
#define CLEAR() system("CLS")
struct borrower
{
char name[20];
char lastName[20];
char id[7];
char phoneNumber[10];
char titleOfBook[3][20];
};
int main(void)
{
struct borrower b;
char op;
do
{
puts("\n1) Register borrower");
puts("2) Find by ID");
puts("3) Show All");
puts("4) Erase by ID");
puts("0) Exit");
printf("Option:");
setbuf(stdin, 0);
opc=getchar();
switch(op)
{
case '1':
RegisterBorrower(&b);
break;
case '2':
//showID();
break;
case '3':
//showAll();
break;
case '4':
//erase();
break;
case '0':
break;
}
}while (op!=48);
return 0;
}
void RegisterBorrower(struct borrower *b)
{
CLEAR();
setbuf(stdin,0);
printf("ID: "); gets(p->id);
printf("Name: "); gets(p->name);
printf("Last Name: "); gets(p->lastName);
setbuf(stdin,0);
printf("Phone Number: "); gets(p->phoneNumber);
int numberOfBooks=0, cont=0, i;
char bookTitle[20];
printf("How many books do you want to take out?(max 3): ");
scanf("%d", &numberOfBooks);
setbuf(stdin,0);
if(numberOfBooks<=3 && numberOfBooks>0)
{
for(i=0; i<numberOfBooks; i++)
{
setbuf(stdin,0);
printf("Book Title: "); gets(bookTitle);
strcpy(p->titleOfBook[i][0], bookTitle);
}
}else
{
printf("You cannot take out this amount of books.");
}
}
Everything "works" (doesn't crash) up until the part I ask for the book titles, it only runs once. Any help would be greatly appreciated.
EDIT:
My problem was that I used
strcpy(p->titleOfBook[i][0], bookTitle);
which only copies to one character because of the [0]. I changed it to
strcpy(p->titleOfBook[i], bookTitle);
and it worked fine.

So many errors and not sure how to fix it

I'm currently still practicing my c programming skills but there are so many errors here that I'm confuse on what is wrong and how to fix it. It's for a database program that I was practicing on.
It keeps showing:
new2.c:86: error: request for member ‘previousreading’ in something not a structure or union
and
new2.c:94: error: ‘Break’ undeclared (first use in this function)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
int custid;
char custname;
float currentreading;
float previousreading;
double charge;
int choice;
unsigned cust;
int revenue, meterdifference, BILL;
printf("----------------------------------\n");
printf("Electricity Management System\n");
printf("----------------------------------\n");
printf("\n1. Record Usage");
printf("\n2. Add Customer");
printf("\n3. Edit Customer");
printf("\n4. Delete Customer");
printf("\n5. Show Customer");
printf("\n6. Show Total monthly income");
printf("\n7. Exit");
scanf("%d",&choice);
if(choice >=1 || choice <=7)
{
switch(choice)
{
case 1: //Record Usage
printf("Enter Customer ID\n");
FILE *cfPtr;
if ((cfPtr = fopen("customer.txt", "r"))== NULL)
puts("This file could not be opened");
else
{
puts("Enter the customer ID, name.");
scanf("%d%29s", &cust.custid, cust.custname);
puts("Enter the current reading in kWh");
scanf("%d", cust.currentreading);
if(cust.currentreading < cust.previousreading)
puts("Input invalid");
else
{
if (cust.currentreading>=200)
{
cust.charge = (cust.currentreading - cust.previousreading)*21.80;
printf("\nThe charge is RM%f\n", &cust.charge);
}
else
{
if (cust.currentreading>=300)
{
cust.charge= ((cust.currentreading - cust.previousreading)*33.40)+21.80;
printf("\nThe charge is RM%f", &cust.charge);
}
else
{
if (cust.currentreading>=600)
{
cust.charge= ((cust.currentreading - cust.previousreading)*51.60)+21.80;
printf("\nThe charge is RM%f", &cust.charge);
}
else
{
if (currentreading>=900)
{
cust.charge = ((cust.currentreading - cust.previousreading)*54.60)+21.80;
printf("\nThe charge is RM%f", &cust.charge);
}
else
{
cust.charge = ((cust.currentreading - cust.previousreading)*57.10)+21.80;
printf("\nThe charge is RM%f", &cust.charge);
}
}
}
}
}
}
Break;
case2: //Add Customer
puts("This option allows user to add new customer");
printf("Enter Customer ID and name.");
scanf("%d%c", &cust.custid, cust.custname);
puts("To return to menu");
Break;
case 3: //Edit Customer
puts( "This option allows user to edit customer info");
Break;
case 4: //delete customer
puts( "This option allows user to delete customer");
Break;
case 5: //Show Customer
printf("To show customer information\n");
FILE*tPtr;
char custid[100],custname[100];
int previousreading,currentreading;
double charge;
printf("\n Show Customer\n");
if((tPtr= fopen("customer.txt","r"))==NULL){
puts("File not found");
}
else{
printf("%-15s%-25s%-20s%-15s%-15s\n","ID","Name","Previous Reading","Current Reading","Charges");
while(!feof(tPtr)){
fscanf(tPtr,"%[^;];%[^;];%d;%d;%lf",cust.custid,cust.custname,&cust.previousreading,&cust.currentreading,&cust.charge);
printf("%s\t\t%-25s%-20d%-15d%-15.2lf",cust.custid,cust.custname,cust.previousreading,cust.currentreading,cust.charge);
}
fclose(tPtr);
}
printf("\n\n");
Break;
case 6: //Show total income(monthly)
puts("To show monthyly income");
printf("total usagekWh, meterdifference");
printf("%-15s%-35.2d\n", "Total UsagekWh","meterdifference");
scanf("%-16dtotal usage(kWh)%-24d: %.2f",&meterdifference);
printf("%-13dtotal revenue%-24d: %.2f",BILL);
revenue=BILL;
printf("revenue is %.2f", BILL);
Break;
case 7: //Exit
Break;
}
}
else
printf("\nError. Number not in choices.");
return 0;
}
typedef struct{
int custid[50];
char custname[100];
int previousreading;
int currentreading;
float charges;
}cust;
Put the typedef before main. typedefs must occure before you use them just as vaiables.
Replace unsigned cust; by cust cust;. unsigned cust; is the same as unsigned int cust; and declares an unsigned integer, you want to declare a cust.
Replace float charges; by float charge; in the typedef
Replace Break; by break;. Case matters in C. Break is not Break, just as Int is not int.
Then it compiles.
Now if it it runs correctly or not is another story.
There is not a single structure in your code, not in the form of a variable declaration nor as a type definition1, and you are treating cust which is simply an unsigned int as if it was a structure, perhaps you mean
struct {
float previousreading;
float currentreading;
/* And so on */
} cust;
Also, there is no Break keyword in c, it's break, all lower case.
But,
Don't do it, create a new struct so that you can use declare variables of type struct Costumer for example. Like at the end of your code, except that the compiler needs to know about it before using it, and the cust variable should have it's type.
A char is not a string type, if you want a string you need an array of char, so char custname; is not going to work for the name string.
Use meaningful names for your variables, and the members if your structure and the type name too. Like costumer instead of cust.
Additional NOTE
See Why while (!foef(file)) is always wrong. Your code will always attempt a read with fscanf() that will fail but it proceeds to print the data, it's very likely that your last row is printed twice once you make the code compile.
Instead, check the return value of fscanf(), if you don't know what it returns and don't fully understand it you can always read fscanf(3) documentation.
1At least not before you attempt to use it.

Must freads be in order?

So I'm writing a code for a program with multiple menus that write different struct datas to a file and then with another menu that displays the data written in those files. Here's the code for the menu:
void displayall()
{
FILE *fp;
int choice=0;
struct depart loc = {0};
struct arrive loc1 = {0};
struct travel trav = {0};
fp=fopen("traveldat.dat","r");
while (1)
{
fread(&loc,sizeof(loc),1,fp);
fread(&loc1,sizeof(loc1),1,fp);
fread(&trav,sizeof(trav),1,fp);
double distance,time;
distance = sqrt(pow((loc1.x2-loc.x1),2)+pow((loc1.y2-loc.y1),2));
time = distance/trav.spd;
if (feof(fp))
{
break;
}
printf("\tYour departure location is : %s\n",loc.dep);
printf("\tWith the x-coordinate : %.2f\n",loc.x1);
printf("\tAnd the y-coordinate : %.2f\n\n",loc.y1);
printf("\tYour destination location is : %s\n",loc1.dest);
printf("\tWith the x-coordinate : %.2f\n",loc1.x2);
printf("\tAnd the y-coordinate : %.2f\n\n",loc1.y2);
printf("\tThe distance between these two locations is : %.2fkm\n\n",distance);
printf("\tYour preferred travel method is : %s\n",trav.mthd);
printf("\tWhich has a top speed of : %.2f km/h\n\n",trav.spd);
printf("\tYour expected travel time is : %.2f hours*\n\n",time);
printf("\t*Estimation,actual travel times may vary depending on certain conditions\n\n");
printf("\tThe system will now display the Main Menu\n\n");
}
fclose(fp);
}
The problem I'm facing is that if I go to the menu that writes loc1 or trav before the menu that writes loc, the display menu doesn't work, returns to the main menu, and then refuses to open whenver I try to access it. Is it because fread(&loc) is placed before the other freads? Or is there something I'm missing? Apologies in advance if this code is an eyesore or if I'm asking wrongly, I've only been learning programming for about a month.
Edit: loc1 and loc code as requested
void arrival_location_menu()
{
FILE *fp;
int choice=0;
struct arrive loc1;
fp=fopen("traveldat.dat","a");
printf("Please select your option (Destination location)\n");
printf("1.HOME\n");
printf("2.Andromeda Galaxy\n");
printf("3.The Library\n");
printf("4.Cprogramming.com\n");
printf("5.Return to main menu\n");
scanf("%d",&choice);
fflush (stdin);
switch (choice)
{
case 1: loc1.x2 = 3750;
loc1.y2 = 3450;
loc1.dest = "HOME";
system("CLS");
break;
case 2: loc1.x2 = 9870;
loc1.y2 = 5660;
loc1.dest = "Andromeda Galaxy";
system("CLS");
break;
case 3: loc1.x2 = 1367;
loc1.y2 = 3123;
loc1.dest = "The Library";
system("CLS");
break;
case 4: loc1.x2 = 2133;
loc1.y2 = 4767;
loc1.dest = "stackoverflow.com";
system("CLS");
break;
case 5: system("CLS");
break;
default: printf("Invalid option! Returning you to main menu...\n");
}
fwrite(&loc1,sizeof(loc1),1,fp);
fclose(fp);
return;
}
//DEPARTURE MENU
void departure_location_menu()
{
FILE *fp;
int choice=0;
struct depart loc;
fp=fopen("traveldat.dat","w");
printf("Please select your option (Departure location)\n");
printf("1.UTAR\n");
printf("2.PLUTO\n");
printf("3.IDK\n");
printf("4.UMM\n");
printf("5.Return to main menu\n");
scanf("%d",&choice);
fflush (stdin);
switch (choice)
{
case 1: loc.x1 = 1738;
loc.y1 = 1997;
loc.dep = "UTAR";
system("CLS");
break;
case 2: loc.x1 = 9850;
loc.y1 = 5675;
loc.dep = "PLUTO";
system("CLS");
break;
case 3: loc.x1 = 1363;
loc.y1 = 3125;
loc.dep = "IDK";
system("CLS");
break;
case 4: loc.x1 = 2130;
loc.y1 = 4785;
loc.dep = "UMM";
system("CLS");
break;
case 5:
system("CLS");
break;
default: printf("Invalied option!\n");
}
fwrite(&loc,sizeof(loc),1,fp);
fclose(fp);
return;
}
You seem to be asking if you can read data from anywhere in the file. Yes you can.
There is a function called fseek() to adjust the file pointer. The file pointer is the location next read from or written too.
There is also a function called ftell() to read the current file pointer. That's important if you're going to change the file pointer and want to restore it later.
I would also suggest you get into the habit of initializing variables ( even if it's to NULL or zero ), and of checking return values from functions. These two simple things can make debugging so much simpler.
I believe user #m-m has already explained the coding logic error.

Strings Became Symbols When They Output in C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have a problem when i output some strings in my codes. When i input 1 string and then output it, there is no problem at all. But, when i input at least 2 strings, it went fail. The strings became symbols, except the last one. Here is the screenshot:
I've been using fflush(stdin) and fflush(stdout), but the problem is still exist.
So, what should i do? I need your advice.
Here is my complete codes:
#include <stdio.h>
#include <stdlib.h>
void menu();
void entry();
void search();
void PrintSingle();
void PrintComplete();
float TotalUsed(int i);
float RegularCost(int i);
float tax(int i);
float discount(int i);
float TotalPayment(int i);
#define NMaks 101
typedef enum {false=0,true=1} boolean;
typedef struct {int BillNumber,BillClass;float LastMeter,CurrentMeter;char name[];} BillDatabase;
BillDatabase bill[NMaks];
int DataAmount=0;
int main() {
menu();
return 0;
}
void menu() {
int i;
repeat:
system("cls");
printf("\t\t.: Electric Billing System :.\n\n");
printf("[1] Entries customer information\n");
printf("[2] Search customer\n");
printf("[3] Print single bill\n");
printf("[4] Print complete billing report\n");
printf("[5] Exit\n\n");
printf("Select the menu[1..5]: ");scanf("%d",&i);
switch (i) {
case 1 : entry();break;
case 2 : search();break;
case 3 : PrintSingle();break;
case 4 : PrintComplete();break;
case 5 : {
printf("\n\nGoodbye!");
getch();
break;
}
default : {
printf("\n\nWrong menu!");
goto repeat;
}
}
}
void entry() {
char repeat;
do {
system("cls");
printf("\t\t.: Electric Billing System :.\n\n");
printf("[1] Entries customer information\n\n");
DataAmount++;
printf("Bill number: ");scanf("%d",&bill[DataAmount].BillNumber);
printf("Customer name: ");fflush(stdin);fflush(stdout);gets(bill[DataAmount].name);
printf("Class[1..3]: ");scanf("%d",&bill[DataAmount].BillClass);
printf("Last meter: ");scanf("%f",&bill[DataAmount].LastMeter);
printf("Current meter: ");scanf("%f",&bill[DataAmount].CurrentMeter);
printf("\nEntry again[y/n]: ");repeat=getche();
} while (tolower(repeat)=='y');
menu();
}
void search() {
int i,BN;
boolean found;
char repeat;
do {
system("cls");
printf("\t\t.: Electric Billing System :.\n\n");
printf("[2] Search customer\n\n");
printf("Enter the bill number: ");scanf("%d",&BN);
found=false;
for (i=1;i<=DataAmount;i++)
if (BN==bill[i].BillNumber) {
found=true;
break;
}
if (found) {
printf("\nCustomer found!\n\n");
printf("Bill number\tN a m e Class\t\tLast meter\tCurrent meter\n");
fflush(stdin);fflush(stdout);
printf("%d\t\t%15.15s\t%d\t\t%.2f kWh\t%.2f kWh\n",bill[i].BillNumber,bill[i].name,bill[i].BillClass,bill[i].LastMeter,bill[i].CurrentMeter);
}
else
printf("\nCustomer not found!\n");
printf("\nSearch again[y/n]: ");repeat=getche();
} while (tolower(repeat)=='y');
menu();
}
void PrintSingle() {
int i,BN;
boolean found;
char repeat;
do {
system("cls");
printf("\t\t.: Electric Billing System :.\n\n");
printf("[3] Print single bill\n\n");
printf("Enter the bill number: ");scanf("%d",&BN);
found=false;
for (i=1;i<=DataAmount;i++)
if (BN==bill[i].BillNumber) {
found=true;
break;
}
if (found) {
printf("\nCustomer found!\n\n");
printf("Bill number\tN a m e Class\t\tLast meter\tCurrent meter\n");
fflush(stdin);fflush(stdout);
printf("%d\t\t%15.15s\t%d\t\t%.2f kWh\t%.2f kWh\n",bill[i].BillNumber,bill[i].name,bill[i].BillClass,bill[i].LastMeter,bill[i].CurrentMeter);
printf("Total used\tRegular cost\tTax\t\tDiscount\tTotal Payment\n");
printf("%.2f kWh\t$%7.2f\t$%7.2f\t$%7.2f\t$%7.2f\n",TotalUsed(i),RegularCost(i),tax(i),discount(i),TotalPayment(i));
}
else
printf("\nCustomer not found!\n");
printf("\nPrint again[y/n]: ");repeat=getche();
} while (tolower(repeat)=='y');
menu();
}
void PrintComplete() {
int i;
system("cls");
printf("\t\t.: Electric Billing System :.\n\n");
printf("[4] Print complete billing report\n\n");
printf("Bill number\tN a m e\t\tClass\tTotal Payment\n");
for (i=1;i<=DataAmount;i++) {
fflush(stdin);fflush(stdout);
printf("%d\t\t%15.15s\t\t%d\t$%.2f\n",bill[i].BillNumber,bill[i].name,bill[i].BillClass,TotalPayment(i));
}
printf("\nPress any key to the main menu");
getch();
menu();
}
float TotalUsed(int i) {
return bill[i].CurrentMeter-bill[i].LastMeter;
}
float RegularCost(int i) {
float price;
switch (bill[i].BillClass) {
case 1 : price=10.0;break;
case 2 : price=7.5;break;
default : price=13.75;
}
return TotalUsed(i)*price;
}
float tax(int i) {
float TaxPercentage;
switch (bill[i].BillClass) {
case 1 : TaxPercentage=1.5/100;break;
case 2 : TaxPercentage=0.25/100;break;
default : TaxPercentage=3.5/100;
}
return RegularCost(i)-(RegularCost(i)*TaxPercentage);
}
float discount(int i) {
float DiscountPercentage;
switch (bill[i].BillClass) {
case 1 : DiscountPercentage=3.0/100;break;
case 2 : DiscountPercentage=2.0/100;break;
default : DiscountPercentage=5.5/100;break;
}
if (RegularCost(i)>100.0)
return RegularCost(i)-(RegularCost(i)*DiscountPercentage);
else
return 0.0;
}
float TotalPayment(int i) {
return RegularCost(i)+tax(i)-discount(i);
}
Note: I use Code Blocks for the IDE.
I see a number of problems here.
First of all, your over-use of global variables is troubling. The array bill and the int DataAmount should definitely not be global. This is not good c programming practice and I would not trust someone whose code looks like this. Please give your "menu", "entry", "printcomplete", and "search" functions arguments so that you can make these variables local, not global.
Second, there are very few cases where it is acceptable to have many statements on the same line as in
printf("Customer name: ");fflush(stdin);fflush(stdout);gets(bill[DataAmount].name);
I'm getting a headache just looking at it!!! pleeease don't!
Third, You are not using array bounds correctly in this for loop, which is the cause of the bug you are asking about in the first place.
for (i=1;i<=DataAmount;i++) {
fflush(stdin);fflush(stdout);
printf("%d\t\t%15.15s\t\t%d\t$%.2f\n",bill[i].BillNumber,bill[i].name,bill[i].BillClass,TotalPayment(i));
}
Remember, in the C language, array indices start at 0 and end at "n - 1". Your loop is starting at 1 and ending at "n".
The reason for the bogus character is that you are accessing a BillDataBase that is outside the boundaries of the array bill.
Fourth, as Sami Kuhmonen said, you are not allocating any memory for your name array. Although this is probably not causing the bug you are seeing, it will almost certainly cause your program to crash with a segmentation fault at some point in the future. In order to fix this looming problem, you have 2 options
The easy way out: change your BillDatabase struct to the following
typedef struct
{
int BillNumber, BillClass;
float LastMeter, CurrentMeter;
char name[128];
} BillDatabase;
This is easy, but not good, because the name can never be more than 128 chars. Also, please don't EVER put the entire struct on one line. I almost started hitting myself over the head with my saxophone.
The harder way out: learn to use malloc(), and manually allocate the name arrays.
You are not allocating any memory for your names, so you're just writing into random places in memory. This is undefined behaviour.

When I run this program, after entering a name, I get a segmentation fault. How can I fix this to make it work properly?

Restauraunt.c
This program allows you to create a restaurant menu, stores it in a file, and then rates each item on the menu. It uses file functions to output everything into a file that can then be viewed through almost any program. When the program gets to the line in nametofile() 'fprintf(restauraunt, "%s Restauraunt\n\n",name);' the program gives a segmentation fault. I do not know why it is doing this, I have attempted several different methods of debugging, but none have worked. If you have any suggestions, please comment them below.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
FILE *restauraunt;
char name[20];
char item[20];
char price[20];
int count=0;
void nametofile();
void rate();
void itemtofile();
void counter();
void renamefile();
int main()
{
int i,j;
int num;
printf("Restauraunt Creator\n\n");
printf("Enter the name of your restauraunt:\n");
scanf("%s",&name);
nametofile();
printf("\nEnter the number of items to be included in your menu:\n");
scanf("%d", &num);
/* Cycles through each entry to the menu */
for(i=0;i<num;i++)
{
counter();
fpurge(stdin);
printf("\nPlease enter the name of item number %d:\n",count);
scanf("%s", &item);
printf("\nPlease enter the price of item number %d:\n",count);
scanf("%s", &price);
itemtofile();
rate();
}
renamefile();
}
/*void nametofile()
{
restauraunt = fopen("restauraunt","w");
fprintf(restauraunt, "%s Restauraunt\n\n",name);
fclose(restauraunt);
}*/
/* The function that sends the restaurant name to the file */
void nametofile()
{
int i;
i = strlen(name);
name[i+1] = '\0';
restauraunt = fopen("restauraunt","w");
/* the line that gives a segmentation fault */
fprintf(restauraunt, "%s Restauraunt\n\n",name);
fclose(restauraunt);
}
/* rates each menu item */
void rate()
{
int rating;
srandom((unsigned)time(NULL));
restauraunt = fopen("restauraunt", "a");
rating = random() % 5 + 1;
fprintf(restauraunt,"Your food's rating was:\t%d stars!",rating);
switch(rating)
{
case 1:
{
fprintf(restauraunt," Here's why: Your food was not very good tasting and the price was ridiculously high.\n");
break;
}
case 2:
{
fprintf(restauraunt," Here's why: Your food was mildly good tasting and the price was too high.\n");
break;
}
case 3:
{
fprintf(restauraunt," Here's why: Your food was somewhat good tasting and the price was fair.\n");
break;
}
case 4:
{
fprintf(restauraunt," Here's why: Your food was quite good tasting and the price was very nice.\n");
break;
}
case 5:
{
fprintf(restauraunt," Here's why: Your food was very delicious and the price was amazingly low.\n");
break;
}
}
}
/* sends each item to the file */
void itemtofile()
{
restauraunt = fopen("restauraunt","a");
fprintf(restauraunt, "%s: $%s\nRating:",item,price);
fclose(restauraunt);
}
/* counts up one each time function is called */
void counter()
{
count += 1;
}
/* renames the file at the end */
void renamefile()
{
int x,y;
char bridge[] = { "menu" };
name[0] = tolower(name[0]);
x = strcat(name,bridge);
y = rename("restauraunt",name);
}
name is a char array. When you pass it to scanf or other functions, it decays to a pointer, so you do not need the & operator:
scanf("%19s", name);
When you read strings with scanf, it is a good idea to pass the size limit: this lets you avoid buffer overruns. Since name is declared as char[20], you pass 19, because one more char needs to be reserved for the null terminator.

Resources