Related
I've got a university project where I have to write a database of workers. I decided to use dynamic array of structures:
struct data
{
char id[50];
char name[50];
char surname[50];
char account_num[50];
double net_pension,taxed_pension;
};
int main()
{
int current_size=0;
struct data *database;//creating a table
database=(struct data*)malloc(1*sizeof(struct data));//memory allocation
menu(database);//running menu
return 0;
}
function menu
void menu(struct data *database)
{
int current_size=1;
int input=0;
char inpt[512];
do
{
printf("Input function or input help for list of avaible commands \n");
fgets(inpt,511,stdin);
input=mod_input(inpt);
if(input==404)
{
printf("Function does not exist \n");
}
else if(input==1)
{
print_result(database,current_size);
}
else if(input==2)
{
add_element(database,¤t_size);
}
else if(input==3)
{
modify_element(database,current_size);
}
else if(input==4)
{
sort_table(database, current_size);
}
else if(input==5)
{
search(database,current_size);
}
else if(input==6)
{
hilfe();
}
else if(input==7)
{
search_by_col(database,current_size);
}
input=8;
}
while(input!=0);
}
decides what we want to do, for example writing "add" will start my problematic function, which is supposed to add new records
void add_element(struct data *database,int *size)
{
int subflag=0;
char inpt[50];
int place=((*size)-1);
int pass=(*size);
printf("%i",pass);
if((*size)!=1)
{
modify_element(database,(*size));
}
do
{
printf("Input unical ID \n");
fgets(inpt,50,stdin);
if(does_exist(inpt,database,pass)==1)
{
subflag=1;
strncpy(database[place].id,inpt,50);
}
else
{
printf("ID exists");
}
}
while(subflag==0);
subflag=0;
do
{
printf("Input name \n");
fgets(inpt,50,stdin);
if(is_word(inpt)==1)
{
subflag=1;
strcpy(database[place].name,inpt);
}
}
while(subflag==0);
subflag=0;
do
{
printf("Input surname \n");
fgets(inpt,50,stdin);
if(is_word(inpt)==1)
{
subflag=1;
strcpy(database[place].surname,inpt);
}
}
while(subflag==0);
subflag=0;
do
{
printf("Input account number \n");
fgets(inpt,50,stdin);
if(is_accnum(inpt)==1)
{
subflag=1;
strcpy(database[place].account_num,inpt);
}
}
while(subflag==0);
subflag=0;
do
{
printf("Input net gain \n");
fgets(inpt,50,stdin);
if(is_num(inpt)==true)
{
printf("%d",atof(inpt));
subflag=1;
database[place].net_pension=atof(inpt);
}
}
while(subflag==0);
subflag=0;
do
{
printf("Input taxed gain \n");
fgets(inpt,50,stdin);
if(is_num(inpt)==true)
{
subflag=1;
database[place].taxed_pension=atof(inpt);
}
}
while(subflag==0);
printf("record added \n");
if((*size)==1)
(*size)++;
}
function modify_size reallocs memory, does_exist ensures, that id's are unique, is acc_num, num and word checks input for given rules. They all work perfectly when you use function first time. But after you try to add second one "record added" does not display and function add runs from the beginning. I ahve no idea why. That is the main problem. Secondary one is menu, because when you input "print" it runs add_element. Code that converts input is:
int mod_input(char function[])
{
printf(function);
if(strcmp(function,"modify")==1)
return 3;
else if(strcmp(function,"sort")==1)
return 4;
else if(strcmp(function,"search")==1)
return 5;
else if(strcmp(function,"help")==1)
return 6;
else if(strcmp(function,"add")==1)
return 2;
else if(strcmp(function,"print")==1)
return 1;
else if(strcmp(function,"search_by_column")==1)
return 7;
return 404;
}
Thank you in advance for help. Also I know that some parts could be done better, but for now, I try to just force it to work.
whole programme
lab3.c and header
Intuitively, what you need to do is pass around a pointer to a pointer to your array, not just a pointer to it. And that's what BLUEPIXY was trying to get at in a comment.
The problem is that if you do x = realloc(y, new_size), there's no guarantee that x will be equal to y.
In particular, database = realloc(database, new_size) inside a subroutine may leave the subroutine with a different value for database than the one passed in as an argument. The caller still has the old value for database.
The results are undefined, and may include worse than what you got.
What you want is something like
struct data *datap;
struct data **database = &datap;
*database = malloc(sizeof(struct data))
With corresponding changes all the way down - basically pass database, and set *database = realloc(...) when you get to that stage.
Also, make sure you update *size appropriately at the same time.
I am trying to make a program that has a menu and it has an option to set the "current" date. I can define the date and it will stay until the program shuts down. I've got another method to get the date, by asking the user the date when linking a person to it, the problem is that it wont go on the main data on the main menu. It will only be the data for the .date on the person structure, I guess I explained it well. I've tried many ways and I really can't figure it out, if someone can help me out...
typeData readData() {
int val;
typeData data;
do {
printf("Day: ");
data.day = readInteger(MIN_DAYS, MAX_DAYS);
printf("Month: ");
data.month = readInteger(MIN_MONTH, MAX_MONTH);
printf("Year: ");
data.year = readInteger(MIN_YEAR, MAX_YEAR);
val = validateData(data);
if(val == 0) {
printf("The data is not valid.\n");
}
} while (val == 0);
return data;
}
I think I need to get it by reference but I'm trying for some time already and can't do it. Thanks everyone.
While it's legal C, passing structs by value and returning them is usually not the best way. Consider:
void
readData(typeData *data)
{
int val;
do {
printf("Day: ");
data->day = readInteger(MIN_DAYS, MAX_DAYS);
printf("Month: ");
data->month = readInteger(MIN_MONTH, MAX_MONTH);
printf("Year: ");
data->year = readInteger(MIN_YEAR, MAX_YEAR);
val = validateData(data);
if (val == 0) {
printf("The data is not valid.\n");
}
} while (val == 0);
}
UPDATE:
Here is a sample main program plus sample changes to validateData:
int
validateData(typeData *data)
{
int data_valid = 1;
// check for error
// this is whatever checks you already do ...
if (data->... != ...)
data_valid = 0;
return data_valid;
}
int
main(int argc,char **argv)
{
typeData main_data;
readData(&main_data);
// do something useful with the data [or transform it, etc]
processData(&main_data);
// print some results
printData(&main_data);
return 0;
}
UPDATE #2:
Here's a modified [partial] program, based on your latest example. I had to guess at the overall organization, but, at least it has the necessary changes to menuPrincipal:
int
validateData(typeData *data)
{
int data_valid = 1;
// check for error
// this is whatever checks you already do ...
if (data->... != ...)
data_valid = 0;
return data_valid;
}
char
menuPrincipal(typeDate *date)
{
char option;
if (date->day == 0 && date->month == 0 && data->year == 0) {
printf("Date not set yet.\n");
}
else {
printf("Date: %d/%d/%d", date->day, date->month, date->year);
}
// more stuff
return option;
}
int
main(int argc,char **argv)
{
typeData main_data;
char option;
while (1) {
readData(&main_data);
option = menuPrincipal(&main_data);
switch (option) {
case 'a': // do something
break;
case 'b': // do something else
break;
default:
printf("unknown option: '%c'\n",option);
break;
}
}
return 0;
}
UPDATE #3:
Based on your latest comment, I think I see what you're having trouble with. I've taken your latest code snippet and updated:
// your original code -- this no longer works because readData is now void
if (data->ano == 0 && data->mes == 0 && data->dia == 0) {
Blah[*Bleh].date = readData(*data);
}
// one possibility -- but it does _not_ update "data"
if (data->ano == 0 && data->mes == 0 && data->dia == 0) {
readData(&Blah[*Bleh].date);
}
// this is more likely what you want -- it updates _both_:
if (data->ano == 0 && data->mes == 0 && data->dia == 0) {
readData(data);
Blah[*Bleh].date = *data;
}
It works now, I was using
val = validateDate(&date)
on the original function for readData, now I changed it to
val = validateDate(date)
and it works!
I just don't know why I need to use date instead of &date, I thought that if I was passing the parameters by reference I needed a '&' symbol.
I'm writing a program that should read equations from a txt file and fill them in a linked-list, check their validity and then convert each valid equation to post-fix notation and calculate the final result. Then write them to a file or print them on the console depends on the user choice. Following is what I've already done, I know my code is really long but I posted it all in order to make my question more clear:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node *ptr;
struct node
{
char eq[100];
char pstfix[100];
double result;
ptr next;
int topPST;
int topOP;
int validity;
};
typedef ptr list;
typedef ptr position;
list l;
void menu(); // prints the menu
void readFile(list l); //reads data from a file
int opPriority(char operators[],char operation,int top) ; // check the priority of a given operation
void isValid(position p);//Function to check the validity of each equation.
void convert(list l); // to convert from infix to postfix
void getResult(list l); // to calculate the result of an equation
double calculate(char operation, int op1,int op2);//To return the value in each step when getting the result
void showValidity(list l); // print the equations and show the ones that have errors
void acceptEq(list l); // Let the user enter equations on the console screen
void fillInfix(position p, char c[]);//A function to fill the array of infix in the node.
int isNum(char val);//returns if the value passed to it is a number or character.
void writeToFile(list l);//Write to the file
void showConsole(list l);//Show the final results on the console
int main()
{
printf("\t\t\t*Data Structure\tSecond project*\n\n\t\t\t*Convert from infix to postfix*\n\n");
menu();
l=(list)malloc(sizeof(struct node));
return 0;
}
//Function to print the menu and let the program work depending on the choice.
void menu()
{
system("cls");
int choice;
printf("\t\t\t\tMenu\n\n\t\t\t1.Read equations from file.\n\t\t\t2.Check validity.\n\t\t\t3.Convert to postfix.\n\t\t\t4.Add more equations to the file.\n\t\t\t\n\t\t\t5.Calculate Results.\n\t\t\t6.Write results to file.\n\t\t\t7.Show results on the console.\n\t\t\t8.End.\n\n\t\t\tEnter Your choice number please\n\t\t\t");
scanf("%d",&choice);
switch (choice)
{
case 1: readFile(l);
break;
case 2: isValid(l);
break;
case 3: convert(l);
break;
case 4: acceptEq(l);
break;
case 5: getResult(l);
break;
case 6: writeToFile(l);
break;
case 7: showConsole(l);
break;
case 8: exit(0);
}
}
//The following function should read equations from a file specified by the user
void readFile(list l)
{
system("cls");
char fileName[50];
FILE *eqFile;
printf("\t\t\tEnter the title of the file please\n\t\t\t");
scanf("\t\t\t%s",fileName);
eqFile=fopen(fileName,"r");
//To ensure the existence of the requested file.
while (eqFile == NULL)
{
printf("\t\t\tThe file you asked for does not exist. Enter another name or enter 'back' to return to menu\n\t\t\t");
scanf("\t\t\t%s",fileName);
if(strcmp(fileName,"back")==0) menu();
else eqFile=fopen(fileName,"r");
}
(l)->next=(position)malloc(sizeof (struct node));
position temp=(l)->next;
char line[100];
while (temp != NULL){
while (fgets(line,sizeof line, eqFile) != NULL)
{
isValid(temp);
if ((temp)->validity) fillInfix(temp,line);
temp=(temp)->next;
(temp)->next=NULL;
}
}
fclose(eqFile);
int choice;
printf("\t\t\tData Read Successfully\n\t\t\tEnter 0 to exit or 1 to return to menu\n\t\t\t");
scanf("%d",&choice);
if (choice) menu();
else exit(0);
}
void isValid(list l)
{
system("cls");
position temp;
temp=l;
int i,count=0;
while((temp)->next!=NULL)
{
for (i=0;i<100;i++)
{
if (((l)->eq[i]=='+' && (l)->eq[i+1]=='*') || ((l)->eq[i]=='-' && (l)->eq[i+1]=='*')|| ((l)->eq[i]=='*' && (l)->eq[i+1]=='/') || ((l)->eq[i]=='/' && (l)->eq[i+1]=='+')|| ((l)->eq[i]=='/' && (l)->eq[i+1]=='-') || (l)->eq[i]==' ')
count++;
}
if (count!=0) (temp)->validity=0;
temp=(temp)->next;
}
int choice;
printf("\t\t\tChecking validity is done enter 0 to quite or 1 to return to menu\n\t\t\t");
scanf("%d",&choice);
if(choice) menu();
else exit(0);
}
void fillInfix(position p, char line[])
{
int i;
for (i=0;i<100;i++)
{
while (line[i]!='\0')
{
(p)->eq[i]=line[i];
}
}
}
void push(char st[],char element, int top)
{
++top;
st[top]=element;
}
char pop(char st[],int top)
{
char elemnt=st[top];
--top;
return elemnt;
}
int opPriority(char operators[], char operation, int top)
{
if ((operation=='*' && operators[top]=='-') || (operation=='*' && operators[top]=='+') || (operation=='*' && operators[top]=='/') || (operation=='/' && operators[top]=='-')|| (operation=='/' && operators[top]=='+') || (operation=='+' && operators[top]=='-')) return 0;
else
if ((operation=='(' && operators[top]=='*') || (operation=='(' && operators[top]=='/') || (operation=='(' && operators[top]=='+') || (operation=='(' && operators[top]=='-')) return 0;
else if (operation==')') return 2;
else
return 1;
}
int isNum(char val)
{
if (val!='+' && val!='-' && val!='*' && val!='/') return 1;
else return 0;
}
void convert(list l)
{
position temp=l;
int i;
char operators[100];
while ((temp)->next != NULL)
{
temp=(temp)->next;
if ((temp)->validity)
{
for (i=0;i<100;i++)
{
if (isNum((temp)->eq[i])) push((temp)->pstfix,(temp)->eq[i],(temp)->topPST);
else
{
int priority=opPriority(operators,(temp)->eq[i],(temp)->topOP);
if (priority==1)
{
push((temp)->pstfix,pop(operators,(temp)->topOP),(temp)->topPST);
push(operators,(temp)->eq[i],(temp)->topOP);
}
else
if (priority ==0) push(operators,(temp)->eq[i],(temp)->topOP);
else
if (priority==2)
{
while (operators[(temp)->topOP]!='(')
{
push((temp)->pstfix,pop(operators,(temp)->topOP),(temp)->topPST);
}
char trash=pop(operators,(temp)->topOP);//Unwanted closed bracket
}
}
}
}
}
int choice;
printf("\t\t\tConversion Done successfully. Enter 0 to quite or 1 to return to menu\n\t\t\t");
scanf("%d",&choice);
if(choice) menu();
else exit(0);
}
void acceptEq(list l)
{
system("cls");
char newEq[100];
printf("\t\t\t Enter your equation please. Note that your equation must not exceed the 100 characters length.\n\t\t\t");
scanf("\t\t\t%s",newEq);
position temp=l;
position p=(position)malloc(sizeof (struct node));
while ((temp)->next!=NULL)
{
temp=(temp)->next;
}
(temp)->next=p;
isValid(p);
if ((p)->validity)
{
fillInfix(p,newEq);
convert(p);
}
}
void getResult(list l)
{
system("cls");
position temp=l;
while ((temp)->next != NULL)
{
temp=(temp)->next;
int i=0;
while ((temp)->pstfix[i]!= '\0')
{
if ((temp)->pstfix[i]=='+' || (temp)->pstfix[i]=='-' || (temp)->pstfix[i]=='*' || (temp)->pstfix[i]=='/')
(temp)->result = calculate((temp)->pstfix[i],(temp)->pstfix[i-2],(temp)->pstfix[i-1]);
push((temp)->pstfix,(temp)->result,(temp)->topPST);
printf("\n\t\t\t%c",(temp)->pstfix[i]);
i++;
}
printf("=%f",(temp)->result);
}
}
double calculate (char operation,int op1,int op2)
{
double result;
if (operation=='+') result=op1+op2;
if (operation=='-') result=op1-op2;
if (operation=='*') result=op1*op2;
if (operation=='/') result=op1/op2;
return result;
}
void writeToFile(list l)
{
system("cls");
char fileWName[50];
printf("\n\t\t\tEnter the name of the file you want to print on please\n\t\t\t");
scanf("\t\t\t%s",fileWName);
FILE* resultFile;
resultFile=fopen(fileWName,"w");
position temp=l;
fprintf(resultFile,"Infix Notation:\t\t");
fprintf(resultFile,"Validity:\t\t");
fprintf(resultFile,"Postfix Notation:\t\t");
fprintf(resultFile,"Value:\t\t\n");
while ((temp)->next != NULL)
{
temp=(temp)->next;
int i=0;
while ((temp)->eq[i]!='/0')
{
fprintf(resultFile,"%c",(temp)->eq[i]);
i++;
}
fprintf(resultFile,"\t\t");
i=0;
while ((temp)->pstfix[i]!='/0')
{
fprintf(resultFile,"%c",(temp)->pstfix[i]);
i++;
}
fprintf(resultFile,"\t\t");
if ((temp)->validity == 0) fprintf(resultFile,"INVALID");
else
{
fprintf(resultFile,"VALID\t\t");
fprintf(resultFile,"%f",(temp)->result);
}
}
fclose(resultFile);
int choice;
printf("\t\t\tDATA WRITTEN TO FILE SUCCESSFULLY. Press 1 to return to menu or 0 to quite\n\t\t\t");
scanf("%d",&choice);
if (choice) menu(l);
else exit(0);
}
void showConsole(list l)
{
system("cls");
position temp=l;
printf("Infix Notation:\t\t");
printf("Validity:\t\t");
printf("Postfix Notation:\t\t");
printf("Value:\t\t\n");
while ((temp)->next != NULL)
{
temp=(temp)->next;
int i=0;
while ((temp)->eq[i]!='/0')
{
printf("%c",(temp)->eq[i]);
i++;
}
printf("\t\t");
i=0;
while ((temp)->pstfix[i]!='/0')
{
printf("%c",(temp)->pstfix[i]);
i++;
}
printf("\t\t");
if ((temp)->validity == 0) printf("INVALID");
else
{
printf("VALID\t\t");
printf("%f",(temp)->result);
}
}
int choice;
printf("\t\t\tDATA WRITTEN SUCCESSFULLY. Press 1 to return to menu or 0 to quite\n\t\t\t");
scanf("%d",&choice);
if (choice) menu();
else exit(0);
}
I've already used debugger to find out where my problem is. And now I know that there's a compiling error in this statement:
(l)->next=(position)malloc(sizeof (struct node));
I'm wondering what's wrong with this statement? I'm trying to allocate space for a node in order to be able to create more nodes for each line (equation).
In this case it's easy to see what's wrong: You try to dereference a NULL pointer.
To understand why, you should know that all global variables, like the variable l in your program, are zero-initialized. That basically means that the pointer l is initialized to NULL.
The problem arise because memory for l is not allocated until after you call the menu function. So any function called from menu will have l equal NULL.
There are a few other problems with your code. One is that memory you allocate with malloc is not initialized at all, so for example when you later in the readFile function call isValid with the newly allocated node, and in isValid dereference the temp->next pointer, the value of that next pointer is indeterminate (and in reality will be seemingly random). Accessing uninitialized data like that will lead to undefined behavior. This of course goes for all data inside the structure, not just pointers.
You also don't seem to set temp->validity to non-zero anywhere.
Yesterday I was able to make a program (ASCII converter etc etc) that had the same problem [ Every function had a missing prototype error when I build the program ] I was able to fix it through random trial and error having no idea how I did it. Here's my arithmetic quiz practice program. I also tried putting int initialize(),clear(),exit(),additionquiz(),subtractionquiz(),divisionquiz(),multiplicationquiz(); and it still gave me a missing prototype.
#include <stdio.h>
/* Main Menu */
int numbers[10];
int main()
{
while(1==1)
{
int choice;
initialize();
printf("Arithmetic Quiz Program\n");
printf("1 - Addition\n2 - Subtraction\n3 - Multiplication\n4 - Division\n5 - Exit\n");
scanf("%d",&choice);
if(choice==1)
{
clear();
additionquiz();
}
else if(choice==2)
{
clear();
subtractionquiz();
}
else if(choice==3)
{
clear();
multiplicationquiz();
}
else if(choice==4)
{
clear();
divisionquiz();
}
else if(choice==5)
{
exit();
}
else
{
printf("%cPlease choose a number from 1 - 5",7);
clear();
continue;
}
}
return 0;
}
/* For clearing the page */
int clear()
{
int i;
for(i=0;i<25;i++)
{
printf("\n");
}
}
/* Assigns the array */
int initialize()
{
numbers[0]=6;
numbers[1]=0;
numbers[2]=2;
numbers[3]=5;
numbers[4]=3;
numbers[5]=1;
numbers[6]=9;
numbers[7]=4;
numbers[8]=7;
numbers[9]=8;
return 0;
}
/* addition quiz */
int addition()
{
int a,diff,b,answer,choice;
a=0;
diff=1;
b=a+diff;
while(1==1)
{
if(a>9)
{
a=0;
diff++;
}
if(b>9)
{
b=0;
}
if(diff>9)
{
diff=0;
}
printf("%d + %d = ",number[a],number[b]);
scanf("%d",&answer);
if(answer==number[a]+number[b])
{
printf("\nCORRECT!!!\n");
a++;
}
else
{
printf("\nWRONG!!!\n");
clear();
additionquiz();
}
printf("\nWhat do you want to do next?\n1 - Answer another addition Question\n2 - Go back to main menu\n3 - Exit program\n");
scanf("%d",&choice);
if(choice==1)
{
clear();
additionquiz();
}
else if(choice==2)
{
clear();
main();
}
else if(choice==3)
{
exit();
}
else
{
printf("%cPlease choose a number from 1 to 3",7);
}
}
return 0;
}
/* The subtraction quiz */
int subtraction()
{
int a,diff,b,answer,choice;
a=0;
diff=1;
b=a+diff;
while(1==1)
{
if(a>9)
{
a=0;
diff++;
}
if(b>9)
{
b=0;
}
if(diff>9)
{
diff=0;
}
if(numbers[a]-numbers[b]<0)
{
a++;
subtraction();
}
printf("%d - %d = ",numbers[a],numbers[b]);
scanf("%d",&answer);
if(answer==numbers[a]-numbers[b])
{
printf("CORRECT!!!\n\n");
}
else
{
printf("WRONG!!!\n\n");
clear();
subtractionquiz();
}
printf("\nWhat do you want to do next?\n1 - Answer another subtraction Question\n2 - Go back to main menu\n3 - Exit program\n");
scanf("%d",&choice);
if(choice==1)
{
clear();
subtractionquiz();
}
else if(choice==2)
{
clear();
main();
}
else if(choice==3)
{
exit();
}
else
{
printf("%cPlease choose a number from 1 to 3",7);
}
}
return 0;
}
/* multiplication quiz */
int multiplicationquiz()
{
int a,diff,b,answer,choice;
a=0;
diff=1;
b=a+diff;
while(1==1)
{
if(a>9)
{
a=0;
diff++;
}
if(b>9)
{
b=0;
}
if(diff>9)
{
diff=0;
}
printf("%d * %d = ",number[a],number[b]);
scanf("%d",&answer);
if(answer==number[a]*number[b])
{
printf("\nCORRECT!!!\n");
a++;
}
else
{
printf("\nWRONG!!!\n");
clear();
multiplicationquiz();
}
printf("\nWhat do you want to do next?\n1 - Answer another multiplication Question\n2 - Go back to main menu\n3 - Exit program\n");
scanf("%d",&choice);
if(choice==1)
{
clear();
multiplicationquiz();
}
else if(choice==2)
{
clear();
main();
}
else if(choice==3)
{
exit();
}
else
{
printf("%cPlease choose a number from 1 to 3",7);
}
}
return 0;
}
/* Division quiz */
int divisionquiz()
{
int a,diff,b,answer,choice,remain;
a=0;
diff=1;
b=a+diff;
while(1==1)
{
if((numbers[a]<numbers[b])||numbers[b]==0)
{
a++;
clear();
divisionquiz();
}
if(a>9)
{
a=0;
diff++;
}
if(b>9)
{
b=0;
}
if(diff>9)
{
diff=0;
}
printf("%d % %d = \n",numbers[a],numbers[b]);
printf("What is the whole number?\n");
scanf("%d",&answer);
printf("What is the remainder? (0 if none\n)");
scanf("%d",&remain);
if(answer==numbers[a]/numbers[b] && remain==numbers[a]%numbers[b])
{
printf("\nCORRECT!!!");
a++;
}
else
{
printf("\nWRONG!!!");
clear();
divisionquiz();
}
printf("\nWhat do you want to do next?\n1 - Answer another division Question\n2 - Go back to main menu\n3 - Exit program\n");
scanf("%d",&choice);
if(choice==1)
{
clear();
divisionquiz();
}
else if(choice==2)
{
clear();
main();
}
else if(choice==3)
{
exit();
}
else
{
printf("%cPlease choose a number from 1 to 3",7);
}
}
return 0;
}
exit is an external function and you need to include its header at the top of your source code:
#include <stdlib.h> // exit
Please notice that in the function call the addition function is called addition and in the function definition additionquiz. Same for the substraction.
For the other functions, you should declare them before you call them: that is before the main function definition.
int initialize(void);
int clear(void);
int additionquiz(void);
int subtractionquiz(void);
int divisionquiz(void);
int multiplicationquiz(void);
int main(void)
{
/* ... */
Note that declaring all the functions in one go like this:
int initialize(void), clear(void), additionquiz(void),
subtractionquiz(void), divisionquiz(void), multiplicationquiz(void);
is permitted but it is not very readable and may surprise the reader.
Finally, if these functions are not called from another source code, you should tell the reader (and the compiler) by adding a static specifier at the beginning of the declaration like this:
static int clear(void); // the function is only called in this source code
The C compiler works from top-to-bottom. It must know that your functions exist before you attempt to call them. So you have two choices:
Define your functions above main (i.e. move the entire function bodies).
Declare your functions above main. i.e. put int initialize();, etc. above main.
Note also that in C, int initialize() is different to int initialize(void). You should be using the second version.
More information on what the guy above me just said can be found here. This page gives you an overview of how to suppress or enable different kinds of warnings in your code:
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Also another tip. You wrote a couple while loops in your code with this syntax:
while (1==1)
{
...
}
this will do the same thing
while(1)
{
}
Here's why: A while loop, an if statement, else statement, and an else if statement will
all perform the code beneath them if the code inside the parenthesis is true. Since 1 in C is true and 0 is false, my while loop above works the same as yours.
First, learn to compile with all warnings enabled and with debugging information (e.g. with gcc -Wall -g on Linux). Then improve your program till no warnings are given by the compiler (trust the compiler).
Then, learn to have a declaration for each of your function. Start your sole source file with them, or, if you have several source files, make a header file with them.
So you could add just after your #include lines:
// clear the screen
void clear(void);
// initialize the numbers
int initilize(void);
// addition quiz
int addition(void);
// subtraction quiz
int subtraction(void);
// multiplication quiz
int multiplicationquiz(void);
// division quiz
int divisionquiz(void);
By the way, your functions might be better named, and you could have formal arguments in them (else use void as the argument list). And I don't understand why they all return an int which you don't use.
I'm writing a code for a simple text based game, and when I purchase a car, the HP and TOPSPEED are registering for integers different than specified.
I've looked over the code myself, perhaps I'm not seeing it, but the Dodge Intrepid should register at 214hp and 140mph top speed, however when I enter the race menu, it registers for 320hp and 160mph top speed, which are the settings of the Mitsubishi 3000GT and the Dodge Stealth of the last beta. I imported the "race" code from the previous beta, being careful to omit any information about the cars used in the previous beta. If you can find my mistake or point anything out, it would be greatly appreciated (I'm including the code with my post). Thanks for your time. (I'm probably overlooking something) (Written in C, compiled and linked with DevC++)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/*HP at RACE is malfunctioning, look over code.*/
int rnd(int range);
void seedrnd(void);
int main()
{
char name[15];
char ocar;
char exit;
char partsA;
char partsB;
char partsC;
char choice;
char dealer;
char model;
int bhp;
int ohp;
int tspd;
int otspd;
int score;
int oscore;
int cash;
int bonus;
int parts1;
int parts2;
int parts3;
int car1;
int car2;
int car3;
int car;
int hp1;
int hp2;
int hp3;
int tspd1;
int tspd2;
int tspd3;
printf("What is your name?\n");
scanf("%s",name);
parts1=1;
parts2=1;
parts3=1;
hp1=214;
tspd1=140;
hp2=490;
tspd2=190;
hp3=320;
tspd3=160;
car=0;
car1=0;
car2=0;
car3=0;
cash=40000;
while(exit!='-')
{
printf("\nMenu:\n1.Garage\n2.Race\n3.Parts Shop\n4.Dealerships\n\n");
choice=getch();
if(choice=='1')
{
printf("Welcome to %s's garage:\n\n",name);
if(car1>0)
{
printf("1.Dodge Intrepid\n");
}
if(car2>0)
{
printf("2.1988 Vector M12\n");
}
if(car3>0)
{
printf("3.Mitsubishi 3000GT\n");
}
car=getch();
if(car=='1')
{
if(car1>0)
{
printf("You are now driving a Dodge Intrepid\n");
car=1;
}
if(car1<1)
{
printf("You do not yet own this vehicle\n");
}
}
if(car=='2')
{
if(car2>0)
{
printf("You are now driving a 1988 Vector M12\n");
car=2;
}
if(car2<1)
{
printf("You do not yet own this vehicle\n");
}
}
if(car=='3')
{
if(car3>0)
{
printf("You are now driving a Mitsubishi 3000GT\n");
car=3;
}
if(car<1)
{
printf("You do not yet own this vehicle\n");
}
}
}
if(choice=='2')
{
if(car=1)
{
bhp=hp1;
tspd=tspd1;
}
if(car=2)
{
bhp=hp2;
tspd=tspd2;
}
if(car=3)
{
bhp=hp3;
tspd=tspd3;
}
/*Begin Race Mechanism*/
printf("Your selected car has %dhp and %dmph top speed\n\n",bhp,tspd);
printf("Now choose your opponent:\n");
printf("1.Rachel (150-250hp 110-130mph)\n");
printf("2.Kyle (250-350hp 130-170mph)\n");
printf("3.Darrian (350-450hp 170-210mph)\n");
printf("4.Chelsea (450-550hp 210-220mph)\n");
ocar=getch();
seedrnd();
if(ocar=='1')
{
ohp=rnd(100)+151;
otspd=rnd(20)+111;
bonus=500;
}
else if(ocar=='2')
{
ohp=rnd(100)+251;
otspd=rnd(40)+131;
bonus=1000;
}
else if(ocar=='3')
{
ohp=rnd(100)+351;
otspd=rnd(40)+171;
bonus=1500;
}
else if(ocar=='4')
{
ohp=rnd(100)+451;
otspd=rnd(10)+211;
bonus=2000;
}
else
{
printf("Haha, you're racing Eli\nNo contest here\n");
ohp=2;
otspd=25;
}
printf("Match-up:%s %dhp %dmph top speed\n",name,bhp,tspd);
printf(" vs \n");
printf("Opponent: %dhp %dmph top speed\n",ohp,otspd);
getch();
score=bhp*tspd;
oscore=ohp*otspd;
printf("Let the race begin\n");
sleep(1000);
printf("3\n");
sleep(1000);
printf("2\n");
sleep(1000);
printf("1\n");
sleep(1000);
printf("!\n\n");
sleep(2000);
printf("The race is over, and the winner is!!!\n\n\n\n");
sleep(3000);
if(score>oscore)
{
printf("YOU!!!\n");
cash=cash+(bonus);
}
else if(score<oscore)
{
printf("Your Opponent...\n");
}
else
{
printf("...neither of you, it was a tie!\n");
cash=cash+(bonus/2);
}
printf("You now have$%d.\n\n",cash);
}/* Closes choice 2*/
if(choice=='3')
{
/* Parts Shop*/
printf("Under Construction\n");
}
if(choice=='4')
{
printf("Press 'y' to exit\n");
printf("Please Select a Dealership\n");
printf("1.Dodge\n2.Vector\n3.Mitsubishi\n\n");
while(dealer!='y')
{
dealer=getch();
if(dealer=='1')
{
printf("DODGE:\n");
if(car1<1)
printf("1.Dodge Intrepid (214hp 140mph) $21,000\n\n");
model=getch();
if(model=='1')
{
if(cash<21000)
{
printf("You cannot afford this vehicle\n\n");
}
if(cash>=21000)
{
if(car1>0)
{
printf("You have already purchased this vehicle\n\n");
}
if(car1<1)
{
car1=car1+1;
cash=cash-21000;
printf("Thank You for purchasing this Dodge Intrepid\n\n");
}
}
}
}
if(dealer=='2')
{
printf("VECTOR:\n");
if(car2<1)
printf("1.1988 Vector M12 (490hp 190mph)$180,000\n\n");
model=getch();
if(model=='1')
{
if(cash<180000)
{
printf("You cannot afford this vehicle\n\n");
}
if(cash>=180000)
{
if(car2>0)
{
printf("You have already purchased this vehicle\n\n");
}
if(car2<1)
{
car2=car2+1;
cash=cash-180000;
printf("Thank You for purchasing this 1988 Vector M12\n\n");
}
}
}
}
if(dealer=='3')
{
printf("MITSUBISHI:\n");
if(car3<1)
printf("1.Mitsubishi 3000GT (320hp 160mph) $60,000\n\n");
model=getch();
if(model=='1')
{
if(cash<60000)
{
printf("You cannot afford this vehicle\n\n");
}
if(cash>=60000)
{
if(car3>0)
{
printf("You have already purchased this vehicle\n\n");
}
if(car3<1)
{
car3=car3+1;
cash=cash-60000;
printf("Thank You for purchasing this Mitsubishi 3000GT\n\n");
}
}
}
}
}
}
exit=getch();
}
return(0);
}
int rnd(int range)
{
int i;
i=rand()%range;
return(i);
}
void seedrnd(void)
{
srand((unsigned)time(NULL));
}
if(car=1)
{
bhp=hp1;
tspd=tspd1;
}
You probably mean if( car == 1 ) { ... this just sets car to 1, and "returns" 1 to the if. Then you do the same for car == 2 and car == 3.
= is the Assignment operator, while == is the comparison operator! The first assigns a value to a variable, while the latter returns true if the are the same (note, for char* you need strcmp()).
Generally you should break your program into small functions and also check for the unhappy case (e.g. what happens if user inputs something not acceptable?)
Another thing that you should pay some attention to is this
scanf("%s",name);
what if someone types in more than 15 characters? You will start righting in memory you do not own and this invokes Undefined Behaviour. One easy trick for that is to do
scanf("%14s", name);
This will restrict the input to 14 characters (and will keep the 15th for the nul terminator). Read more here: http://www.cplusplus.com/reference/clibrary/cstdio/scanf/
As others have noted in the comments, consider using structs to make your life easier. I haven't read the program in too detail to understand the exact structure of your game, but you could have for example a struct for the user:
struct player
{
char name[15];
car* owned_cars; //Linked List!
}
Where car is defined like that:
struct car
{
int max_speed;
int colour; //or even better an enum here
int seats;
//... etc.
car* next_car; //Make the Linked List's next node here!
}
Also! If you make a LinkedList, one mistake that usually happens is that they forgot to initialize thieir pointers to NULL. So :
car* new_car = malloc( sizeof(car) );
new_car->next_car = NULL;
If you don't do that, next_car will contain a random/garbage number! So when you try to go through the List
while(new_car->next_car != NULL)
{
//....
}
You will access memory you do not own.
Good luck and have fun!
There's also an issue in the following code:
if(car=='3')
{
if(car3>0)
{
printf("You are now driving a Mitsubishi 3000GT\n");
car=3;
}
if(car<1) // SHOULD BE car3<1
{
printf("You do not yet own this vehicle\n");
}
}
The integer distribution is wrong, because
int rnd(int range)
{
int i;
i=rand()%range;
return(i);
}
is wrong. That ought to be
int rnd(int range)
{
return rand() / ( RAND_MAX / range + 1 );
}
Read more here: Eternally Confuzzled: using rand()
Edit to the comment:
With this, I specifically respond to your question integer distribution error: the random distribution will not be uniform. Meaning, some numbers will appear significantly less frequently than others, not the property of a true (pseudo) random sequence.
The linked article contains more elaborate explanation of precisely what happens.
You are using the rnd() function defined at the bottom of in quite some places, and to be honest I haven't gone through all the code to understand the implications on what the program does, so I don't know whether it also answers some of the other questions you (vaguely) desscribe in the OP.
This section:
if(car=1)
{
bhp=hp1;
tspd=tspd1;
}
if(car=2)
{
bhp=hp2;
tspd=tspd2;
}
if(car=3)
{
bhp=hp3;
tspd=tspd3;
}
You are assigning car to 1, then 2, then 3: Use == instead of =.