Access writing violation location in c - 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]);
}
}

Related

Understanding references to members in a struct within a struct, as well as how to dynamically allocate memory for struct members

I've looked at a few different questions with regards to the problem I am facing and while I feel like I've gained some insight I definitely have questions that I could use help with, so I wanted to solve a problem and get some help with the issues I'm facing in solving it.
I have an employee registry, I want to create a structure "Employee" that contains the data fields that I need for each employee. Within those fields I want another structure for their "Date of Birth" which has 3 ints within the struct - referring to month/date/year of birth. (See below)
typedef struct DOB {
int month;
int day;
int year;
} Birthdate;
typedef struct EmployeeInfo {
int empID;
char *firstName;
char *lastName;
Birthdate date;
double salary;
} Employee;
Now I want my program to output a menu of choices and prompt the user for input that could lead to several options those being:
Insert a new employee
Update/change info about an employee
Search for a specific employee
Display all information about all employees
int main() {
//create the array of Items
Employee * employeeRecord = (Employee * ) malloc(N * sizeof(Employee));
Birthdate * birthRecord = (Birthdate * ) malloc(N * sizeof(Birthdate));
int empID;
double salary;
Employee Employee;
Birthdate Birthdate;
char opt;
while (1) {
dispayMenu();
printf("Enter your Choice: ");
scanf(" %c",&opt);
switch(opt) {
case 'i':
printf("\nEnter empID: ");
scanf("%d", & Employee.empID);
printf("Enter firstName: ");
scanf("%s", Employee.firstName);
printf("Enter lastName: ");
scanf("%s", & Employee.lastName);
printf("Enter Date of Birth (month/day/year format): ");
scanf("%d-%d-%d", &Employee.date.month,&Employee.date.day,&Employee.date.year);
printf("Enter Employee salary: ");
scanf("%lf", & Employee.salary);
insertItem(employeeRecord, Employee);
break;
case 'u':
printf("\nEnter empID to update: ");
scanf("%d", & empID);
updateItem(employeeRecord, empID);
break;
case 's':
printf("\nEnter empID to search: ");
scanf("%d", &empID);
searchItem(employeeRecord, empID);
break;
case 'd':
printData(employeeRecord);
break;
case 'q':
quit(employeeRecord);
break;
default:
printf("%c is not a valid choice", opt);
}
}
}
The first question I have is - how can I dynamically update the size of the array that contains all the employees? I get a segmentation fault currently; I don't want to globally create the size of the array; but I know I only need to update it when I have to add an Employee to the registry - so when I call the insert function - but I don't know how to keep a count for a variable in main that updates when insert is called.
The second question is in regards to changing the date of birth - I know I have to use -> operator somewhere so that I can access the fields within the second structure, but when I use it currently it tells me that the type is mismatched - its an int but expects type char*. So how do I access data within the structures to change from the update() function.
void updateItem(Employee * employeeRecord, int empID) {
int i;
char chng;
for (i = 0; i < current_size; i++)
{
if (employeeRecord[i].empID == empID)
{
printf("What data do you wish to update?: ");
scanf(" %c", &chng);
switch (chng)
{
case '1':
printf("\nEnter new First Name: ");
scanf("%s", &Employee.firstName);
break;
case '2':
printf("\nEnter new Last Name: ");
scanf("%s", &Employee.lastName);
break;
case '3':
printf("\nEnter new Date of Birth: ");
// scanf("%d", &empID);
// searchItem(employeeRecord, empID);
break;
case '4':
printf("\nEnter new salary: ") break;
case '5':
printf("\nReturning to main menu.");
break;
default:
printf("%c is not valid, try it again.", opt);
}
}
break;
}
else{
printf("Employee Not Found");
}
}
I've described it above, but essentially can't seem to reference the items within a struct correct and am having trouble correctly calling functions from main - says the implicit declaration doesn't match the type of the function, but that might have to do with errors within those functions themselves.
You store your Employees in a dynamically allocated array, then use realloc() to resize the array:
void insertItem(Enployee **employees, size_t *n, Employee e) {
Employee *tmp = realloc((n+1) * sizeof(Employee));
if (!tmp) {
// fail
}
*employees = tmp;
memcpy(*employees + *n, e, sizeof(Employee));
(*n)++;
}
int main(void) {
// ...
Employee *employees = NULL;
size_t n = 0;
// ...
case 'i': {
Employee *e = malloc(sizeof(Employee));
scanf("%d", e->empID);
// ...
insertItem(&employees, &n, e);
}
// ...
}
As employees and n belong together it would make sense to create a struct to hold them.
Within the Employee struct Birthdate date is also a struct. You use . to access members of a struct via a value, and -> if you have a pointer. In updateItem() you pass in an Employee *employeeRecord and use it as an array so you you either do:
employeeRecord[i].date.month = ...
// or
(employeeRecord + i)->date.month = ...
You can only reference functions already declared so you want main() last. The other good option is to add declarations for your functions at the top.

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.

undefined reference to a function call?

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.

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