Memory error, access violation - c

I'm learning C on my own and as a exercise i have written a program but it does not work. The program is splitted into 3 parts. A header file, a main file for executing the program a file to define the functions. I'm not using all the functions yet but that shouldn't be the problem.
Here is my header file, nothing special in it.
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
struct Employee
{
char first[21];
char last[21];
char title[21];
int salary;
};
struct Employee* createEmployee(char*, char*, char*, int); // Creates a struct Employee object on the heap.
char* getfirstname (struct Employee*);
char* getlastname (struct Employee*);
char* gettitle (struct Employee*);
int getsalary (struct Employee*);
void setfirstname (struct Employee*, char*);
void setlastname (struct Employee*, char*);
void settitle (struct Employee*, char*);
void setsalary (struct Employee*, int);
void printEmployee(struct Employee*);
#endif
In this file i define the functions and how they work:
#include "7.1.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Employee* createEmployee(char* first, char* last, char* title, int salary) // Creates a struct Employee object on the heap.
{
struct Employee* p = (struct Employee*) malloc(sizeof(struct Employee));
if (p != NULL)
{
strcpy(p->first, first);
strcpy(p->last, last);
strcpy(p->title, title);
p->salary = salary;
}
return p;
}
char* getfirstname (struct Employee* p)
{
if (p != NULL)
return p ? p->first : "";
}
char* getlastname (struct Employee* p)
{
if (p != NULL)
return p ? p->last : "";
}
char* gettitle (struct Employee* p)
{
if (p != NULL)
return p ? p->title : "";
}
int getsalary (struct Employee* p)
{
if (p != NULL)
return p ? p->salary : 0;
}
void setfirstname (struct Employee* p, char* first)
{
if (p != NULL)
strcpy(p->first, first);
}
void setlastname (struct Employee* p, char* last)
{
if (p != NULL)
strcpy(p->last, last);
}
void settitle (struct Employee* p, char* title)
{
if (p != NULL)
strcpy(p->title, title);
}
void setsalary (struct Employee* p, char* salary)
{
if (p != NULL)
p->salary = salary;
}
void printEmployee(struct Employee* p)
{
if (p != NULL)
{
printf("%s, %s, %s, %d",
p->first,
p->last,
p->salary,
p->salary
);
}
}
And the last file is used to executed the program/functions:
#include "7.1.h"
#include <stdio.h>
#include <stdlib.h>
int main ()
{
char decision;
struct Employee emp;
struct Employee* emps[3];
for ( int i = 0; i < 1; i ++)
{
printf("Please type in the emplooyes data.\nFirstname:");
scanf("%s", emp.first);
printf("Lastname:");
scanf("%s", emp.last);
printf("Title:");
scanf("%s", emp.title);
printf("Salary:");
scanf("%d", &emp.salary);
emps[i] = createEmployee(emp.first, emp.last, emp.title, emp.salary);
}
printf("Do you want to print out your information? (Y/N):");
scanf("%c", &decision);
if (decision == 'y' || decision == 'Y')
{
printEmployee(emps[1]);
}
}
I don't know what the problem is. I 'm always getting the following error message after typing in first, last, title and salary for the first time. The error is written in german. It means:
Unhandled exception at 0x102de42e (msvcr100d.dll) in 7.1.exe: 0xC0000005: Access violation when writing to 0xCCCCCCCC position.
I could fix the first problem with the hints given below. Now when i want to print out the employee data using the function:printEmployee(emps[1]);, I get the same kind of error with access violation.

For scanf for a number you need to specify the pointer to the number not the number itself. I.e.
scanf("%d", &emp.salary);
There may be other problems, but that's the first one I saw.

Your printf() arguments look off:
printf("%s, %s, %s, %d",
p->first,
p->last,
p->salary, // did you mean title here rather than salary?
p->salary
);
Also, you'll want to include new line character at the end of your format string:
printf("%s, %s, %s, %d\n", // note the \n
...
Your createEmployee() definition is also questionable:
p->salary, salary; // did you mean p->salary = salary?

don't know, if it's the only issue, but one trouble is :
scanf("%d", emp.salary);
Which is wrong (forgot address on salary with &)
better try : scanf("%d", &emp.salary);
++

This is how you're calling scanf():
scanf("%s", emp.salary);
This is how you're supposed to call scanf():
scanf("%s", &emp.salary); // note the address to the location you want
EDIT: As AlstairG points out, your strings (the char* members) are pointers and thus have the address already.

Related

Segmentation fault when trying to print out a struct

I'm trying to make a code that will allow the user to input any amount of entries he wants, and then print them out (and other functions, still have to get to that). But when I try to launch the code it allows me to input the entries, but when I want to print them out, it doesn't register current.name or current.telNo (only prints out 1: has tel. No. ) and a segmentation error follows after it. Any idea how I can fix that.
#include <stdio.h>
#include <stdlib.h>
int listSize;
int counter = 0;
struct Entry {
char name[20];
char telNo[9];
struct Entry *next;
} current;
int main()
{
struct Entry *linkedList = (struct Entry * )malloc(sizeof(struct Entry));
struct Entry *current = linkedList;
first(current);
print(current);
return 0;
}
void first(struct Entry linkedList)
{
int i;
printf("enter list size: ");
scanf("%d", &listSize);
printf("Now enter entries one by one: \n");
for (i = 0; i < listSize; i++) {
counter++;
printf("Name: ");
scanf("%s", linkedList.name);
printf("Telephone: ");
scanf("%s", linkedList.telNo);
if (i != listSize -1) {
linkedList.next = (struct Entry *)malloc(sizeof(struct Entry));
linkedList = *linkedList.next;
} else {
linkedList.next = NULL;
}
}
}
void print(struct Entry linkedList)
{
int nr = 1;
printf("\nTelephone book is:\n");
while (current.name != NULL) {
printf("%d: %s has tel. No.\t%s\n", nr, current.name, current.telNo);
current = *current.next;
nr++;
}
}
Instead of . you should have used -> and in your print() you were traversing current instead of linkedList which was causing the issue. Also your functions definitions should come before its usage. Please check the below snippet, i have made the corresponding changes.
#include <stdio.h>
#include <stdlib.h>
int listSize;
int counter = 0;
struct Entry {
char name[20];
char telNo[9];
struct Entry *next;
} current;
void print(struct Entry *linkedList)
{
int nr = 1;
printf("\nTelephone book is:\n");
while (linkedList->name != NULL) {
printf("%d: %s has tel. No.\t%s\n", nr, linkedList->name, linkedList->telNo);
linkedList = linkedList->next;
nr++;
}
}
void first(struct Entry *linkedList)
{
int i;
printf("enter list size: ");
scanf("%d", &listSize);
printf("Now enter entries one by one: \n");
for (i = 0; i < listSize; i++) {
counter++;
printf("Name: ");
scanf("%s", linkedList->name);
printf("Telephone: ");
scanf("%s", linkedList->telNo);
if (i != listSize -1) {
linkedList->next = (struct Entry *)malloc(sizeof(struct Entry));
linkedList = linkedList->next;
} else {
linkedList->next = NULL;
}
}
}
int main()
{
struct Entry *linkedList = (struct Entry * )malloc(sizeof(struct Entry));
struct Entry *current = linkedList;
first(current);
print(current);
return 0;
}
while (current.name != NULL)
should be
while (current != NULL)
otherwise current = *current.next will become NULL and crash on the while condition
current.name is a pointer to reserved 20-byte area, which is always non-NULL.
I would initialize *next with NULL every time I allocate it (there are few ways to do that, easiest: assign NULL to it right after malloc). And do the check like that: if (current.next != NULL).
You also can check for current.name[0] != 0, but the first option is cleaner.
There are a number of errors in your code but, essentially two main 'points of confusion':
First, you seem to be confusing a structure (struct Entry) with a pointer-to-structure (as in, for example, struct Entry *next;).
Second, you have two different variables called current - one defined globally (which is the only one that is 'visible' to your print function), and another one defined locally inside main (this one will 'hide' the former).
Here is a corrected version of your code, with triple-slash (///) comments wherever I've made changes. Feel free to ask for further clarification and/or explanation.
#include <stdio.h>
#include <stdlib.h>
int listSize;
int counter = 0;
struct Entry {
char name[20];
char telNo[9];
struct Entry* next;
} *current; /// Here, we define a GLOBAL variable, "current" that is a POINTER to the struct
void first(struct Entry* linkedList); /// Put "Function Prototypes* here, so that "main" knows what they are
void print(struct Entry* linkedList); /// You need to pass POINTERS to structures, not the actual structures
int main()
{
struct Entry* linkedList = (struct Entry*)malloc(sizeof(struct Entry));
// struct Entry* current = linkedList; /// This declaration 'hides' the global variable
current = linkedList; /// Here, we (properly) assign the global pointer's value
first(current);
print(current);
return 0;
}
void first(struct Entry* linkedList) /// Pointer (see above)
{
int i;
printf("enter list size: ");
scanf("%d", &listSize);
printf("Now enter entries one by one: \n");
for (i = 0; i < listSize; i++) {
counter++;
printf("Name: ");
scanf("%s", linkedList->name); /// Use "->" instead of "." to get a pointer's member (and elsewhere)
printf("Telephone: ");
scanf("%s", linkedList->telNo); /// See above
if (i != listSize - 1) {
linkedList->next = (struct Entry*)malloc(sizeof(struct Entry)); /// See above
linkedList = linkedList->next; /// Again - changed here to use pointers!
}
else {
linkedList->next = NULL; /// See above
}
}
}
void print(struct Entry* linkedList) /// Pointer (see above)
{
int nr = 1;
printf("\nTelephone book is:\n");
while (current != NULL) { /// You need to check if "current" is not NULL before trying to access any of its members...
// while (current.name != NULL) {
printf("%d: %s has tel. No.\t%s\n", nr, current->name, current->telNo); /// Same "." to "->" changes as before
current = current->next; /// And again!
nr++;
}
}
There are other ways to 'fix' your code (and also improve it): for example, you never use the argument you pass to print, relying instead on the 'global' variable I mentioned earlier.

C structs and linked lists struggle

So, we just started learning linked lists and data structures in my online class, but I have been really struggling with this topic. I have a general understanding of pointers but when you combine everything, I get completely lost.
So for this program, I am supposed to process employee data and access it through the use of structs and pointers. However, I think I am not passing the correct values into the functions because the data is not being saved and I can't access it. Any help would be appreciated.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct address {
char street[49];
char city[29];
char state[2];
char zip[5];
};
struct data{
char name[39];
struct address addy;
float salary;
struct data *next;
} emp;
void LIST(struct data* head);
void INSERT(struct data* head, char* name, struct address addr, float salary);
void DELETE(char* name, struct data* head);
void EDIT(struct data* head, char* name, struct address addr, float salary);
void CALCPAYROLL(struct data* head);
void HELP();
int main()
{
char input[15];
int quitter = 1;
struct data *head = NULL;
head = malloc(sizeof(emp));
if (head == NULL){
return 1;
}
while(quitter == 1)
{
printf(" enter command: \n");
fgets(input,15, stdin);
input[strlen(input) -1] = '\0';
if((strcmp(input, "List") == 0) || (strcmp(input, "list") == 0))
{
LIST(head);
}
if((strcmp(input, "Insert") == 0) || (strcmp(input, "insert") == 0))
{
scanf("%s-%s-%s-%s-%s-%f", head->name, head->addy.street, head->addy.city, head->addy.state, head->addy.zip, &head->salary);
INSERT(head, head->name, head->addy, head->salary);
}
if ((strcmp(input, "Delete") == 0) || (strcmp(input, "delete") == 0))
{
DELETE(head->name, head);
}
if ((strcmp(input, "Edit") == 0) || (strcmp(input, "edit") == 0))
{
EDIT(head, head->name, head->addy, head->salary);
}
if ((strcmp(input, "Payroll") == 0) || (strcmp(input, "payroll") == 0))
{
CALCPAYROLL(head);
}
if ((strcmp(input, "Help") == 0) || (strcmp(input, "help") == 0))
{
HELP();
}
if ((strcmp(input, "Quit") == 0) || (strcmp(input, "quit") == 0))
{
printf("============\nGood bye!\n");
quitter = 0;
}
}
return 0;
}
void LIST(struct data* head)
{
struct data* temp = head;
while (temp) {
printf("%s\n%s\n%s, %2s %5s\n%9.2f\n-----\n", temp->name, temp->addy.street, temp->addy.city, temp->addy.state, temp->addy.zip, temp->salary);
temp = temp->next;
printf("%s\n%s\n%s, %2s %5s\n%9.2f\n-----\n", temp->name, temp->addy.street, temp->addy.city, temp->addy.state, temp->addy.zip, temp->salary);
temp = temp->next;
}
}
void INSERT(struct data* head, char* name, struct address addr, float salary)
{
struct data* newEmployee = NULL;
newEmployee = (struct data*)malloc(sizeof(emp));
strcpy(newEmployee->name, head->name);
newEmployee->salary = head->salary;
strcpy(newEmployee->addy.street, head->addy.street);
strcpy(newEmployee->addy.city, head->addy.city);
strcpy(newEmployee->addy.state, head->addy.state);
strcpy(newEmployee->addy.zip, head->addy.zip);
struct data* temp = head;
while(temp->next && temp->next->name > newEmployee->name)
{
temp = temp->next;
}
newEmployee->next = temp->next;
temp->next = newEmployee;
}
void DELETE(char* name, struct data* head)
{
char del[39];
scanf("%39s", del);
struct data * toBeDeleted = NULL;
struct data * temp = head;
while (strcmp(del, temp->name) == 0)
{
strcpy(temp->next->name, temp->name);
temp->addy = temp->next->addy;
temp->salary = temp->next->salary;
toBeDeleted = temp->next;
temp->next = temp->next->next;
free(toBeDeleted);
printf("RECORD DELETED\n");
}
temp = temp->next;
printf("RECORD NOT FOUND\n");
}
void EDIT(struct data* head, char* name, struct address addr, float salary)
{
char edit[39];
scanf("%39s", edit);
struct data* temp = head;
while (strcmp(edit, temp->name) == 0)
{
temp->addy = addr;
temp->salary = salary;
printf("RECORD EDITED\n");
return;
}
temp = temp->next;
printf("RECORD NOT FOUND\n");
}
void CALCPAYROLL(struct data* head)
{
struct data* temp = head;
float total;
while (temp)
{
total += temp->salary;
temp = temp->next;
}
printf("total payroll: %f", total);
}
void HELP()
{
printf("commands:\n");
printf("List - shows the list of employees\n");
printf("Insert - Creates a new employee record\n");
printf("Delete - Deletes an existing employee record\n");
printf("Edit - Modifies the contents of an employee record\n");
printf("Payroll - Calculates and displays the total payroll\n");
printf("Help - Displays the set of available commands\n");
printf("Quit - Prints the message ""good bye!"" and exits the program" );
}
First of all, I have to commend you for a very neat presentation. The code is readable and easy to follow. The only fault I find with it is that all uppercase names are usually reserved for macros and constants declared with #define.
Here:
struct data{
char name[39];
struct address addy;
float salary;
struct data *next;
} emp; // declaring a variable at the same time as the structure? Not very nice.
I see an issue that happens when you create your first list item, the head. Insert must have a way to modify the head parameter. This needs an extra level of indirection. INSERT should also return an error code, in case malloc fails, a common way to do this is to return a negative value (-1) on error.
void INSERT(struct data* head, char* name, struct address addr, float salary)
// should be
int INSERT(struct data** head, char* name, struct address addr, float salary)
You'll have to change the logic a little bit to set head with the newly allocated buffer when head is NULL on entry. Calling INSERT then becomes.
if (INSERT(&head, name, &addr, salary) < 0)
{
// error !
}
I see a problem in data allocation in INSERT.
struct data* newEmployee = NULL;
//newEmployee = (struct data*)malloc(sizeof(emp)); // ?? you allocate a struct data, what's emp?
// should read
newEmployee = (struct data*)malloc(sizeof(struct data));
DELETE and EDIT do not work. They cannot find the employee as written. You should consider using a find() function, something like this:
data* FindEmployeeData(data* head, const char* name)
{
while (head)
{
if (strcmp(head->name, name) == 0)
break;
head = head->next;
}
return head;
}
This could be a time saver when writing new operations on employees.
In INSERT:
while(temp->next && temp->next->name > newEmployee->name)
I thought strings were supposed to be compared with strcmp()...
In DELETE: same as for INSERT, the function could change the head of the list
int DELETE(data** head, const char* name); // returns -1 on error.
Here:
scanf("%s-%s-%s-%s-%s-%f", head->name, head->addy.street, head->addy.city, head->addy.state, head->addy.zip, &head->salary);
Terrible things will happen when the user enters a name, address, state, street, city or zip that are too long for the space you have allocated.
You can't access to the data because in INSERT function head must be a double pointer, because when you want to insert something in the head of a linked list you have to change the address stored in head. In your code you're modifying a copy of head. remember that in C everything is passed for value. This mean that for modify the address content in a pointer you have to pass the address of the pointer at your function.

Not able to write information into linear linked list

The processFilefunction scans the information from the file correctly to p, however the addNodeLast function doesn't add the information from p to the linked list employees because it crashes.
Can someone help me fix the crashing, so that it will link each node together?
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
void processFile(NODEPTR *employees, FILE *fp);
void outputPayFile(NODEPTR employees);
FILE *fp;
int main(void) {
NODEPTR employees;
if (fopen_s(&fp, "payfile2.txt", "r") != 0) {
printf("Failed to open payfile.txt for reading\n");
exit(0);
}
...missing code...
}
void processFile(NODEPTR *employees, FILE *fp) {
int i = 0;
NODEPTR p;
while(i < 5) {
printf("Entered Loop\n");
p = (NODEPTR) malloc(sizeof(node));
fscanf(fp, "%s %s %c %d %c %f\n", p->firstName, p->lastName, &(p->gender),
&(p->tenure), &(p->rate), &(p->rate), &(p->salary));
addNodeLast(employees, p);
i++;
}
}
In list.h:
void addNodeLast(NODEPTR *list, NODEPTR t) {
NODEPTR p;
if (*list == NULL)
*list = t;
else {
p = *list;
while (p->next)
p = p->next;
p->next = t;
}
}
Definition of NODEPTR:
typedef struct node {
char firstName[11];
char lastName[16];
char gender;
int tenure;
char rate;
float salary;
struct node *next;
} node, *NODEPTR;
You never initialise the next pointer. This is a common mistake. The call to malloc does not zero your memory. As a result, when you add a node to a non-empty list, you are likely to run straight off the end because the first node's next pointer could be non-null.
You need to at least do this:
p = malloc(sizeof(node));
if( p != NULL ) p->next = NULL;
You could consider using calloc, which does zero:
p = calloc(1, sizeof(node));

Need help in pure c list implementation

I am trying to do linked list of persons in c.
All my methods work in main() until I put them into while loop (for reading commands from user). Everything compiles, but when I try to run it, it crashes returning random values.
Here are parts of my code.
Structure:
struct Person{
const char* name;
const char* sex;
int age;
struct Person* next;
} *head;
Method insert:
void insert(struct Person* h, char*n, char* s, int a){
for(; h->next != NULL; h=h->next){}
struct Person* p = (struct Person*) malloc(sizeof(struct Person));
p->name=n;
p->age=a;
p->sex=s;
p->next=NULL;
h->next=p;
}
and main in which it doesn't work:
int main()
{
struct Person Maciek={"Maciek", "Male", 20, NULL};
head = &Maciek;
int comand = 0;
while(comand != 6){
printf("Choose command:\n 1-insert person \n 2-delete by index \n 3-delete by name \n 4-display by index \n 5-print whole list \n 6-exit\n");
scanf("%d", &comand);
if(comand == 1){
printf("Name, Gender, Age\n");
char* name;
char* sex;
int age;
scanf("%s, %s, %d", &name, &sex, &age);
printf("Name %s, Sex %s, Age %d", name, sex, age);
insert(head, name, sex, age);
}
if(comand == 2){
printf("2\n");
}
if(comand == 3){
printf("3\n");
}
if(comand == 4){
printf("4\n");
}
if(comand == 5){
printf("5\n");
}
}
return 0;
}
I am quite new to C/C++, and I would really appreciate any help.
if(comand == 1){
printf("Name, Gender, Age\n");
char* name;
char* sex;
int age;
scanf("%s, %s, %d", &name, &sex, &age);
Here you are using dangling pointers (which are pointing anywhere in memory), you should use malloc to allocate some memory or use char arrays, and as Carl Norum pointed out you shouldn't have & in your scanf call as you need to provide some char* and not char**. You can do it like this (this code is vulnerable to buffer overflow, don't use that in production code, consider using fgets+sscanf):
char name[50];
char sex[20];
int age = 0;
scanf("%s, %s, %d", name, sex, &age);
In your insert function:
struct Person* p = (struct Person*) malloc(sizeof(struct Person));
p->name=n;
p->age=a;
p->sex=s;
You are replacing p->name with n, instead of copying the content of n into p->name. You want:
struct Person *p = malloc(sizeof(struct Person));
p->name = malloc(strlen(n)+1);
if(p->name == NULL) {
//error handling...
}
strcpy(p->name, n);
p->sex = malloc(strlen(s)+1);
if(p->sex == NULL) {
//error handling...
}
strcpy(p->sex, s);
p->age = a;
You're reading strings into pointers that have not been initialized with allocated memory.

hash table - linked lists - segmentation fault

I am trying to implement a hash table with linked list chaining. The following code below works -
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TABSIZ 200
struct record {
struct record *next;
char name[BUFSIZ];
int data;
};
static struct record *htable[TABSIZ];
unsigned hash(char *s)
{
unsigned h;
for (h = 0; *s; s++)
h = *s;
//printf("%d", h%TABSIZ);
//I know its not a good hash function but i wanted to check chaining
return h % TABSIZ;
}
struct record *find(char *name)
{
struct record *item;
for (item = htable[hash(name)]; item; item = item->next)
{
if (strcmp(name, item->name) == 0)
return item;
}
return NULL;
}
struct record *insert(char *name,int value)
{
struct record *item;
unsigned h;
if ((item = find(name)) == NULL)
{
if ((item = malloc(sizeof (*item))) == NULL)
return NULL;
strcpy(item->name, name);
item->data=value;
h = hash(name);
item->next = htable[h];
htable[h] = item;
}
return item;
}
void printTable()
{
int i=0;
struct record *temp;
for(i=0;i<=TABSIZ;i++)
{
temp=htable[i];
while(temp!=NULL)
{
printf("\n%d - %s - %d\n", i,temp->name, temp->data);
temp=temp->next;
}
}
}
int main(void)
{
char buf[BUFSIZ];int value;
struct record *item;
do{
printf("Enter the name of the student:\n");
scanf("%s", buf);
if(strcmp(buf,"stop")==0) break;
printf("Enter the marks of the student:\n");
scanf("%d", &value);
if(insert(buf, value)==NULL)
{
break;
}
}while((strcmp(buf,"stop"))!=0);
printf("Enter a name to find: ");
scanf("%s", buf);
if((item=find(buf))!=NULL)
printf("The marks of the student is %d\n", item->data);
else printf("\n Not Found\n");
printTable();
return 0;
}
Now I am trying to remove the global variable and use local variable for the array of structures. I removed the global declaration of htable and declared it in main as
struct record *htable[TABSIZ];
and changed the functions to
struct record *find(struct record *htable, char *name);
struct record *insert(struct record *htable, char *name,int value);
and I'm calling the functions as
find(htable, name);
insert(htable,name,value);
but now my program is segfaulting. Am i passing the array of structures right? and have I declared it correctly. Any help would be greatly appreciated.
I was going down the wrong path with my earlier answer.
When it's a global, it's automatically initialized to 0.
When it's declared on the stack of main, it's not initialized.
Add a memset( htable, 0, sizeof(htable)) in main(), and that should return it to the previous behavior.
In printTable():
for(i=0;i<=TABSIZ;i++)
looks suspect. You prabably want:
void printTable()
{
unsigned int i;
struct record *temp;
for(i=0; i < TABSIZ;i++)
{
for (temp=htable[i]; temp!=NULL; temp=temp->next )
{
printf("\n%d - %s - %d\n", i,temp->name, temp->data);
}
}
}

Resources