Using free() for char-pointer in struct - c

typedef struct inventory
{
char *name;
int quantity;
double price;
struct inventory* next_inventory;
} invent;
int main(void)
{
invent *one=malloc(sizeof(invent));
invent *two=malloc(sizeof(invent));
invent *three=malloc(sizeof(invent));
one->next_inventory=two;
two->next_inventory=three;
three->next_inventory=NULL;
one->name=malloc(256);
...(repeat two->name, three->name)
printf("name: ");
scanf("%s", one->name);
printf("qunatity: ");
scanf("%d", &one->quantity);
printf("price: ");
scanf("%lf", &one->price);
...(repeat scanf() for two, three)
while(one!=NULL)
{
printf("%s %d %.0f\n", one->name, one->quantity, one->price);
printf("check\n");
one=one->next_inventory;
}
free(one->name);
free(two->name);
free(three->name);
free(one);
free(two);
free(three);
return 0;
free(one->name); doesn't work. I checked another free(), using printf("check");, two->name, three->name, one ... its worked. Why only free(one->name) doesn't work? What can I do for solve this problem? Give me the advice.

You are using your actual 'one' variable to do the iteration, in the end you are trying to free(one) where one points to NULL.
You should not lose track of the address of the memory you requested to allocate, to be able to release that memory later with free.
I would use a temporary pointer to iterate:
invent* tmp = one;
while(tmp!=NULL)
{
printf("%s %d %.0f\n", tmp->name, tmp->quantity, tmp->price);
printf("check\n");
tmp=tmp->next_inventory;
}
// free all names and one, two, three.
In alternative:
you can define a function for printing:
void printAll(invent* one)
{
while(one!=NULL)
{
printf("%s %d %.0f\n", one->name, one->quantity, one->price);
one=one->next_inventory;
}
}
then in the main, call
printAll(one)
This works as the pointer is passed by value in the function and you won't lose the original address.

Here is a improved version of your program that includes also checking malloc return code:
#include <stdlib.h>
#include <stdio.h>
typedef struct invent
{
char *name;
int quantity;
double price;
struct invent* next_inventory;
} invent;
void enter(invent **s)
{
printf("name: ");
scanf("%s", (*s)->name);
printf("quantity: ");
scanf("%d", &(*s)->quantity);
printf("price: ");
scanf("%lf", &(*s)->price);
}
void *alloc(size_t size)
{
void *p;
p = malloc(size);
if (p == NULL)
{
perror("malloc");
exit(1);
}
return p;
}
int main(void)
{
invent *start;
invent *one;
invent *two;
invent *three;
one = alloc(sizeof(invent));
two = alloc(sizeof(invent));
three = alloc(sizeof(invent));
start = one;
one->next_inventory=two;
two->next_inventory=three;
three->next_inventory=NULL;
one->name=alloc(256);
two->name=alloc(256);
three->name=alloc(256);
enter(&one);
enter(&two);
enter(&three);
while(one != NULL)
{
printf("%s %d %.0f\n", one->name, one->quantity, one->price);
printf("check\n");
one=one->next_inventory;
}
free(start->name);
free(two->name);
free(three->name);
free(start);
free(two);
free(three);
return 0;
}

Related

How to allocate a struct dynamically in C to avoid a segmentation fault?

I'm having a problem to allocate a structure dynamically.
I'm making a program that works as a contact book, but I'm getting the
following error: Segmentation fault (core dumped).
The structure declaration, following the functions to add a contact
and print all contacts:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct contact{
int number;
char name[80];
}contact;
void addContact(contact **contacts, int position){
int aux=position;
printf("Enter the name: ");
setbuf(stdin, 0);
fgets(contacts[position]->name,80,stdin);
printf("Enter the telephone number: ");
scanf("%d",&contacts[position]->number);
return;
}
void printAllContacts(contact **contacts, int size){
for(int i;i<size;i++){
printf("Contact %d:\n",i);
printf("Name: %s\n",contacts[i]->name);
printf("Telephone number: %d \n",contacts[i]->number);
}
}
// Main function:
int main(){
int size;
printf("Enter the list size: ");
scanf("%d",&size);
contact *contacts= (contact*)malloc(sizeof(contact)*size);
int counter=0;
int x;
do{
printf("------------MENU-----------\n");
printf("1-Add contact\n");
printf("2-Print contacts list\n");
printf("0-Exit\n");
printf("----------------------------\n");
printf("Enter an option: ");
scanf("%d",&x);
switch (x){
case 1:
addContact(&contacts,counter);
counter++;
break;
case 2:
printAllContacts(&contacts,counter);
break;
case 0:
break;
}
}while(x!=0);
return 0;
}
Can anyone help?
The basic problem is that you're allocating an array of struct contact objects, but your addContact and printAllContacts expect an array of pointers to struct contact. You need to choose one or the other.
The easiest fix is probably to change the functions -- change the argument type to contact * instead of contact **, remove the & at the call site in main, and change the -> to . in the functions where needed.
Pass in a pointer (contacts *) instead of pointer to pointer (contacts **) to addContact() & printAllContacts(). Updated caller, and partially updated called code which already assumed it was operating on an array.
Initialize i in printAllContacts().
Removed the unnecessary cast of malloc() return value.
Removed the name of the struct as you use only use the typedef.
Introduced a NAME_LEN macro instead of the magic 80 value.
Minor reformatting for readability & consistency.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_LEN 80
typedef struct {
int number;
char name[NAME_LEN];
} contact;
void addContact(contact *contacts, int position) {
printf("Enter the name: ");
setbuf(stdin, 0);
fgets(contacts[position].name, NAME_LEN, stdin);
printf("Enter the telephone number: ");
scanf("%d", &contacts[position].number);
return;
}
void printAllContacts(contact *contacts, int size) {
for(int i=0; i<size;i++) {
printf("Contact %d:\n", i);
printf("Name: %s\n", contacts[i].name);
printf("Telephone number: %d\n", contacts[i].number);
}
}
int main() {
int size;
printf("Enter the list size: ");
scanf("%d", &size);
contact *contacts = malloc(sizeof(contact)*size);
int counter=0;
int x;
do {
printf("------------MENU-----------\n");
printf("1-Add contact\n");
printf("2-Print contacts list\n");
printf("0-Exit\n");
printf("----------------------------\n");
printf("Enter an option: ");
scanf("%d", &x);
switch (x) {
case 1:
addContact(contacts, counter++);
break;
case 2:
printAllContacts(contacts, counter);
break;
case 0:
break;
}
} while(x!=0);
return 0;
}
I would add additional structure holding all the contacts and also keeping the number of contacts stored. You do not need to know the size of the list - it will grow with any added contact.
When you test the idea I would advise you to not use user input functions, only fixed data. It makes debugging and testing faster and easier. Especially function which adds data should not communicate with the external world. Caller is the correct place to do it
Also use function return values to return result or status codes. You tend to use void everywhere - it is not a good idea.
typedef struct contact{
unsigned number;
char name[80];
}contact;
typedef struct
{
size_t size;
contact contacts[];
}constactList;
constactList *addContact(constactList *list, const char *name, const unsigned number)
{
size_t newsize = list ? list -> size + 1 : 1;
list = realloc(list, sizeof(*list) + sizeof(list -> contacts[0]) * newsize);
if(list)
{
strncpy(list -> contacts[list -> size].name, name, sizeof(list -> contacts[0].name));
list -> contacts[list -> size].name[sizeof(list -> contacts[0].name) - 1] = 0;
list -> contacts[list -> size].number = number;
list -> size = newsize;
}
return list;
}
void printContacts(const constactList *list)
{
if(list)
{
for(size_t i = 0; i < list -> size; i++) printf("[%3zu] %s, %u\n", i, list -> contacts[i].name, list -> contacts[i].number);
}
}
int main(void)
{
constactList *list = NULL;
list = addContact(list, "James Bond", 7);
if(!list) {/* error handling*/}
list = addContact(list, "Mata Hari", 99);
if(!list) {/* error handling*/}
list = addContact(list, "Wladymir Putin", 666);
if(!list) {/* error handling*/}
printContacts(list);
free(list);
}

Why does printing from this struct give a segmentation fault?

I'm trying to create an array of Product structs and then print the name and code of each Product in the array, but I keep getting a segmentation fault. I have tried to insert each value without a loop and then printing, and it works, but I'd like to automate it. The function fill_products fills the products array according to the user's input, and the select_products prints each name-code pair for the entire array.
This is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int code;
char *name;
float price;
} Product;
void select_products(Product *products, int len)
{
int i;
printf("%-30s%s\n", "Name", "Code");
for (i = 0; i < len; i++)
{
printf("%-30s%d\n", products[i].name, products[i].code);
}
return;
}
void fill_products(Product *products, int len)
{
int i, code;
char *name;
float price;
for (i = 0; i < len; i++)
{
printf("Insert product name (%d / %d): ", i + 1, len);
scanf("%s", &name);
printf("Insert product price (%d / %d): ", i + 1, len);
scanf("%f", &price);
products[i].code = i;
products[i].name = name;
products[i].price = price;
}
return;
}
int is_alloc(Product *products)
{
if (products == NULL)
{
printf("Error: memory allocation unsuccessful.\n");
}
return products != NULL;
}
int main(void)
{
int len, n_bytes;
Product *products;
printf("Insert length of array: ");
scanf("%d", &len);
n_bytes = sizeof *products * len;
products = malloc(n_bytes);
if(!is_alloc(products))
{
exit(0);
}
fill_products(products, len);
select_products(products, len);
free(products);
return 0;
}
I keep getting a segmentation fault.
Please enable compiler warnings, and pay attention to them.
This code:
char *name;
...
scanf("%s", &name);
is bogus and doesn't do at all what you intend.
You must either allocate space for name separately (and then not forget to free() it), or make that space available in the Product structure like so:
typedef struct
{
int code;
char name[100];
float price;
} Product;
(this assumes there is a reasonable limit on name length).

Why am I getting garbage value after displaying the data

I am getting garbage value when I display the records.
I have to create a database of students in C using array of structures and without pointers.
Is there any other way of doing this?
How to use array of structures?
#include <stdio.h>
struct student {
char first_name[10],last_name[10];
int roll;
char address[20];
float marks;
};
void accept(struct student);
void display(struct student);
void main() {
struct student S[10];
int n, i;
printf("Enter the number of records to enter : ");
scanf("%d", &n);
for (i = 0; i < n; i++) {
accept(S[i]);
}
for (i = 0; i < n; i++) {
display(S[i]);
}
}
void accept(struct student S) {
scanf("%s", S.first_name);
scanf("%s", S.last_name);
scanf("%d", &S.roll);
scanf("%s", S.address);
scanf("%f", &S.marks);
}
void display(struct student S) {
printf("\n%s", S.first_name);
printf("\n%s", S.last_name);
printf("\n%d", S.roll);
printf("\n%s", S.address);
}
Everything in C is pass-by-value. Which means you are modifying variable copy in stack frame, while real variable passed as parameter remains untouched.
You have to pass an pointer to variable which you want to modify in function.
// Function declaration
void accept(struct student *);
// Call
accept(&S[i]);
// Usage in function via dereference operator
scanf("%s",S->first_name);
If you would like to enter unknown amount of records, you should use VLA (since c99) or dynamically allocate structures.
VLA
scanf("%d",&n);
struct student S[n];
Dynamic callocation
scanf("%d",&n);
struct student * S = malloc(sizeof(struct student) * n);
Because in your case, if user input more that 9 records you are touching outside of bounds, which has undefined behavior.
There are multiple issues in your code:
The standard prototype for main without arguments is int main(void)
You should allocate the array dynamically with calloc.
you should pass structure pointers to the accept and display functions instead of passing structures by value. Passing the destination structure by value is incorrect as the accept function cannot modify the structure in the main function, which remains uninitialized and causes garbage to be displayed. Note that it is actually undefined behavior to access uninitialized data so the program could behave in even worse ways.
You should provide scanf() with the maximum number of arguments to store into character arrays to avoid potential buffer overflows.
you should verify the return values of scanf() to avoid undefined behavior on invalid input.
you could use the %[^\n] scan set to allow embedded spaces in the address field.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct student {
char first_name[10], last_name[10];
int roll;
char address[20];
float marks;
};
void accept(struct student *sp);
void display(const struct student *sp);
int main(void) {
struct student *S;
int n, i, j;
printf("Enter the number of records to enter : ");
if (scanf("%d", &n) != 1)
return 1;
S = calloc(sizeof(*S), n);
if (S == NULL) {
return 1;
}
for (i = 0; i < n; i++) {
accept(&S[i]);
}
for (i = 0; i < n; i++) {
display(&S[i]);
}
free(S);
return 0;
}
void accept(struct student *sp) {
if (scanf("%9s%9s&d %19[^\n]%f",
sp->first_name, sp->last_name, &sp->roll,
sp->address, &sp->marks) != 5) {
printf("missing input\n");
exit(1);
}
}
void display(const struct student *sp) {
printf("%s\n", sp->first_name);
printf("%s\n", sp->last_name);
printf("%d\n", sp->roll);
printf("%s\n", sp->address);
printf("%f\n", sp->marks);
printf("\n");
}

Printing Names using Circular Linked List

I was working on a circular linked list problem and solved it.But i got stuck in other problem. The program takes names of persons in circular linked list nodes and prints them.
My question is that program works fine if and only if the names are 4 characters or less.If the length of the names exceeds 4,it shows weird behaviour.
If the length of name is 5 characters,then the program is stuck on second iteration of the for loop of the initiate function.
If the length of name is 6 characters or more then program terminates immediately showing the names entered.
The source code is:
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#define SIZE 10
#define NUM_PER_LINE 3
typedef struct node
{
char name[SIZE];
struct node * next;
} CListNode;
void get_name(char *a);
void print_list(CListNode *end_ptr);
CListNode *initiate(int n);
CListNode *insert_at_end(CListNode *first,CListNode *end_ptr, char *a);
int main(void)
{
CListNode *list_end_ptr;
int n=6;
list_end_ptr=initiate(n);
print_list(list_end_ptr);
return 0;
}
void get_name(char *a)
{
char *aa=(char *)malloc(10*sizeof(char));
a=aa;
scanf("%s", a);
}
CListNode *insert_at_end(CListNode *first,CListNode *end_ptr, char *a)
{
CListNode *temp, *head=NULL;
head=first;
temp=(CListNode *) malloc(sizeof(CListNode));
end_ptr->next=temp;
strcpy(temp->name, a);
temp->next=head;
return temp;
}
CListNode *initiate(int n)
{
CListNode *end, *first=NULL,*ptr=NULL;
int i;
char new_name;
end=(CListNode *) malloc(sizeof(CListNode));
if (end==0) {
printf("Allocation error...\n");
exit(0); }
end->next=end;
for (i=0; i<n; i++) {
if (i<1) {
printf("Enter the name of the %d person: ", i+1);
get_name(&new_name);
strcpy(end->name, &new_name);
first=end;
}
else
{
printf("Enter the name of the %d person: ", i+1);
get_name(&new_name);
ptr=insert_at_end(first,end, &new_name);
end=ptr;
}
}
return end;
}
void print_list(CListNode *end_ptr)
{
int i=1;
CListNode *str_ptr;
if (end_ptr == NULL)
printf("\n List is empty");
else
{
str_ptr = end_ptr->next;
while (str_ptr != end_ptr)
{
printf("%s \t", str_ptr->name);
str_ptr = str_ptr->next;
if (i%NUM_PER_LINE==0) {
printf("\n");
}
i++;
}
printf("%s\n", str_ptr->name);
}
}
The problem is in your get_name function and the way you use it. Its signature assumes that the storage is already allocated, because you take a pointer, not a pointer to pointer. Your code ignores the allocation completely; on top of that, it passes a pointer to character.
Since you allocate name within the node, remove malloc, remove new_name, and pass name array to get_name:
void get_name(char *a) {
scanf("%9s", a); // Limit the size to 9 chars
}
...
printf("Enter the name of the %d person: ", i+1);
get_name(end->name);

Program with array of structs crashes

I have an array with multiple structs. When i ask the user to enter data the first time everything works but when i ask again for the next position in the array the program crashes. If this method doesn't work souldn't the program crash in the beginning? Is something wrong with malloc?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student {
char name[50];
int semester;
};
struct prof {
char name[50];
char course[50];
};
struct student_or_prof {
int flag;
int size;
int head;
union {
struct student student;
struct prof prof;
}
}exp1;
struct student_or_prof *stack;
void init(int n)
{
stack = malloc(n);
}
int push(struct student_or_prof **pinx,int *head,int n)
{
char name[50];
printf("\nn= %d\n",n);
printf("\nhead= %d\n",*head);
if(*head==n)
{
printf("Stack is full.\n");
return 1;
}
char x;
printf("Student or Professor? [s/p] ");
getchar() != '\n';
scanf("%c",&x);
if(x=='s')
{
getchar() != '\n';
pinx[*head]->flag = 0;
printf("\n\nGive student's name: ");
fgets(pinx[*head]->student.name,sizeof(pinx[*head]->student.name),stdin);
printf("\nGive student's semester: ");
scanf("%d",&(pinx[*head]->student.semester));
printf("\nName = %s\tSemester = %d",pinx[*head]->student.name,pinx[*head]->student.semester);
}
else if(x=='p')
{
getchar() != '\n';
pinx[*head]->flag = 1;
printf("\n\nGive professor's name: ");
fgets(pinx[*head]->prof.name,sizeof(pinx[*head]->prof.name),stdin);
printf("\nGive course: ");
fgets(pinx[*head]->prof.course,sizeof(pinx[*head]->prof.course),stdin);
printf("\nName = %s\tCourse = %s\n",pinx[*head]->prof.name,pinx[*head]->prof.course);
}
(*head)++;
printf("\nhead= %d\n",*head);
}
int main()
{
int n,i;
printf("Give size: ");
scanf("%d",&n);
init(n);
for(i=0;i<n;i++)
push(&stack,&exp1.head,n);
return 0;
}
You need to malloc the structure not n
malloc(sizeof(struct student_or_prof)*n)
EDIT:
And your code crashes again because pinx is a double pointer, so this operation is not valid:
pinx[*head]->flag = 0;
this is equivalent to:
*(pinx + *head)->flag = 0;
Since you are not changing what stack points to, you are better off using a single pointer instead of a double pointer.
So instead you should change your push API:
int push(struct student_or_prof *pinx,int *head,int n)
and call it like:
push(stack,&exp1.head,n);
malloc allocates the given number of bytes.
You have to multiply n with the size of your struct, to allocate enough memory.
pinx does not point to an array, so pinx[*head] is going to access invalid memory unless *head is zero.
I think you meant (*pinx)[*head] , which accesses the N-th element of the array you allocated via malloc. For example (*pinx)[*head].prof.name etc.
BTW, your head number doesn't seem to be used at all, except for exp1.head, maybe it'd be better to remove head from the struct, and just have a single variable head?

Resources