undefined reference to a function call? - c

I think my only problem this undefined reference to...well all of my function calls. I've done functions and pointers before and tried to follow the same format but I'm lost as to what I'm doing wrong :/ I voided them all, defined my pointers, and gave them the correct types...It just says 4 errors stating "undefined reference to __menuFunction" etc...
#include<stdio.h>
void menuFunction(float *);
void getDeposit(float *, float *);
void getWithdrawl(float *, float *);
void displayBalance(float );
int main()
{
float menu, deposit,withdrawl, balance;
char selection;
menuFunction (& menu);
getDeposit (&deposit, &balance);
getWithdrawl(&withdrawl, &balance);
displayBalance(balance);
void menuFunction (float *menup)
{
printf("Welcome to HFCC Credit Union!\n");
printf("Please select from the following menu: \n");
printf("D: Make a Deposit\n");
printf("W: Make a withdrawl\n");
printf("B: Check your balance\n");
printf("Or Q to quit\n");
printf("Please make your slelction now: ");
scanf("\n%c", &selection);
}
switch(selection)
{
case'd': case'D':
*getDeposit;
break;
case 'W': case'w':
*getWithdrawl;
break;
case'b': case'B':
*displayBalance;
}
void getDeposit(float *depositp, float *balancep)
{
printf("Please enter how much you would like to deposit: ");
scanf("%f", *depositp);
do
{
*balancep = (*depositp + *balancep);
} while (*depositp < 0);
}
void getWithdrawl(float *withdrawlp, float *balancep)
{
printf("\nPlease enther the amount you wish to withdraw: ");
scanf("%f", *withdrawlp);
do
{
*balancep = (*withdrawlp - *balancep);
} while (*withdrawlp < *balancep);
}
void displayBalance(float balance)
{
printf("\nYour current balance is: %f", balance);
}
return 0;
}

Your menuFunction() getDeposit() and getWithdrawl() are defined in main()'s body. Nested functions aren't supported of ANSI-C. The easiest way to make your code work is to define functions in the global scope.
[Upd.] but don't forget to fix another bugs in your code (for example, statement variable in menuFunction() is an unresolved symbol, it must be declared as global variable or should be sent into the function as an argument. I advise you to read K&R, it is classics for C programmers!

Take your functions out of the main() function.
int main()
{
float menu, deposit,withdrawl, balance;
char selection;
menuFunction (& menu);
getDeposit (&deposit, &balance);
getWithdrawl(&withdrawl, &balance);
displayBalance(balance);
}
void menuFunction (float *menup)
{
...
...
Beside this your program has many errors. Correct them.

Related

Passing and returning a struct from a function

I have a function with a book struct array, but when i try to return it to my main it does not return the values and store them in the array. If the addBook function has to be void how would i work around that so that i can access the array elements later.
void addBook(struct Book book[], int *size) {
if (*size == MAX_BOOKS) {
printf("The inventory is full\n");
}
else {
printf("ISBN:");
scanf("%d", &book[*size]._isbn);
printf("Title:");
scanf("%s", book[*size]._title);
getchar();
printf("Year:");
scanf("%d", &book[*size]._year);
printf("Price:");
scanf("%f", &book[*size]._price);
printf("Quantity:");
scanf("%d", &book[*size]._qty);
*size++;
printf("The book is successfully added to the inventory.\n");
}
return book;
}
int main(void) {
struct Book book[MAX_BOOKS];
int size = 0;
int i;
int option;
printf("Welcome to the Book Store\n");
printf("=========================\n");
do {
menu();
printf("Select: ");
scanf("%d", &option);
switch (option) {
case 0:
printf("Goodbye!\n");
break;
case 1:
displayInventory(book, size);
break;
case 2:
addBook(book, &size);
break;
case 3:
//checkPrice();
break;
default:
printf("Invalid input, try again:\n");
}
} while (option != 0);
}
Your return statement isn't going to do what you're intending as the addBook's function signature says it returns void. I'm surprised that the code as is actually compiled without an error about this.
Anyways, the book data can be returned from the same way it was passed in - as an input and output parameter.
Essentially your code could look like the following (which is only meant to be an example of code that compiles and works to save info entered in from standard input into the book):
#include <stdio.h>
struct Book {
int value;
};
#define MAX_BOOKS 2
void addBook(struct Book book[], int *size) {
if (*size == MAX_BOOKS) {
printf("The inventory is full\n");
}
else {
printf("Value:");
scanf("%d", &book[*size].value);
(*size)++;
printf("The book is successfully added to the inventory.\n");
}
}
int main(void) {
struct Book book[MAX_BOOKS];
int size = 0;
addBook(book, &size);
printf("Book 1: Value=%d\n", book[0].value);
}
And here's how this looks when run:
$ ./main
Value:9
The book is successfully added to the inventory.
Book 1: Value=9
Hope this answers your question.
I think your problem is in the line *size++;. You should use parenthesis, otherwise you are modifying the pointer to size, not the value. It should be (*size)++.
Also, the addBook function should not return anything, since it is void, and it is changing the content of the array book already.

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.

Access writing violation location in c

Access writing violation in a function that is intended to take names and information of employees. When I open the function via a switch it asks for the name of the employee but when I press enter I get the error code.
Unhandled exception at 0x6559DBE9 (msvcr120d.dll) in Assignment4.exe:
0xC0000005: Access violation writing location 0x009A6858.
The code that I believe to be the cause
typedef struct person
{
char emplyName[5][SIZE];
float emplyHours[5];
float emplyRate[5];
float emplyGross[5];
float emplyBase[5];
float emplyOvrt[5];
float emplyTax[5];
float emplyNet[5];
float emplyTotal[5];
}input;
void menu(void);
void editEmployees(input* emply);
void print(input* emply);
void employeeInfo(input* emply);
int main(void)
{
struct person *payroll={""};
int choice = 0;
menu();
scanf_s("%c", &choice,1);
switch (choice){
case '1':{
employeeInfo(payroll);
break;
}
case '2':{
editEmployees(payroll);
break;
}
case '3':{
print(payroll);
break;
}
case '4':{
break;
}
default:
printf("Invalid entry\n");
}
system("pause");
}
void employeeInfo(input *emply)
{
int i = 0;
for (i=0;i<5;i++) {
printf("Enter employee name.\n");
scanf_s("%s", &emply->emplyName[i]);
printf("Enter employee hours.\n");
scanf_s("%f", &emply->emplyHours[i]);
printf("Enter Hourly rate.\n");
scanf_s("%f", &emply->emplyRate[i]);
}
}
The *emply pointer could be invalid. It could be null or point to random location.
Try this. It's not a complete answer as you do need to use a reference to retrieve the values, but it will get you moving
void employeeInfo(input emply)
{
int i = 0;
for (i=0;i<5;i++) {
printf("Enter employee name.\n");
scanf_s("%s", emply.emplyName[i]);
printf("Enter employee hours.\n");
scanf_s("%f", emply.emplyHours[i]);
printf("Enter Hourly rate.\n");
scanf_s("%f", emply.emplyRate[i]);
}
}

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.

Why does this give junk value?

I am getting garbage / junk values as output when my program is run and the data displayed.
Why is it so?
Can someone help me to understand how to properly pass by pointers and not get junk values?
This program is about stack creation of struct books type variables.
By default shouldn't the variable bks pass by pointer and change when b is changed?
bks is still storing garbage value.
Here is my code:
#include<stdio.h>
#include<stdlib.h>
struct books
{
int yrpub;
char name[100],author[50];
};
int top=-1;
int push(struct books b[],int top,int n)
{
if(top==n-1)
return -1;
else
{
++(top);
printf("Enter books info: \n");
printf("Enter name: ");
gets(b[top].name);
printf("Enter author: ");
gets(b[top].author);
printf("Enter Year of publish: ");
scanf("%d",&b[top].yrpub);
return top;
}
}
void display(struct books b[],int top)
{
int i;
if(top==-1)
printf("No books in the stack...");
for(i=0;i<=top;i++)
{
printf("Details of book %d: \n",i+1);
printf("Name: %s\nAuthor: %s\nYear of publish: %d\n",b[i].name,b[i].author,b[i].yrpub);
}
system("pause");
}
int main()
{
struct books bks[10];
int ch;
system("cls");
printf("Select an option:\n");
printf("1. Push book\n2. Pop book\n3. Peep book\n4. Display all books info\n5. Exit\n");
printf("Enter a choice: ");
scanf("%d",&ch);
fflush(stdin);
switch(ch)
{
case 1:
system("cls");
top=push(bks,top,10);
break;
case 4:
system("cls");
display(bks,top);
break;
case 5: exit(0);
default: printf("\nWrong choice...Please retry.");
long i,j;
for(i=0;i<1000000;i++)
for(j=0;j<100;j++);
}
main();
}
Each time you recursively call main(), you create a new array bk.
The information you entered in the previous invocation of main() is hidden from the new one.
To iterate is human; to recurse, divine.
In this context, give up divinity for humanity. Use iteration — in this context it is better.
This is your primary problem; there may also be other off-by-one or other errors.
push:
if(top==n-1)
return -1;
main:
top=push(bks,top,10);
top is reset when the stack is full
Edit:
And the second problem is main being called again, struct books bks[10] is reset in the next main, it is a recursion. Declare bks as global or go with a while loop instead of recursion.
while (1) {
getChoices();
if (exit)
/* exit from here */
process();
}

Resources