Error in printing the stack - c

I am trying to implement a program using stacks.But the stack is not getting displayed
#include<stdio.h>
int size=0,count=1,test=0;
struct Car
{
int registrationNo;
char *name;
};
struct ParkingLot
{
struct Car C[10];
};
struct stack
{
struct ParkingLot P;
int top;
} st;
int stfull()
{
if(st.top >= size-1)
return 1;
else
return 0;
}
void push(struct Car item) {
st.top++;
st.P.C[st.top] = item;
}
int stempty() {
if (st.top == -1)
return 1;
else
return 0;
}
void display() {
int i;
if (stempty())
printf("\nStack Is Empty!");
else {
//printf("%d\n",st.top);
for (i = 0; i<=st.top; i++)
printf("\n%s", st.P.C[i].name);
}
}
void Enter_ParkingLot()
{
struct Car CC;
int checkFull=stfull();
if(checkFull==1)
printf("Parking Lot is FUll\n");
else
{
CC.registrationNo=count;count++;
char ch[100];
printf("Enter name of owner\n");
scanf("%s",ch);
CC.name=ch;
push(CC);
}
}
int main()
{
printf("Enter size of Parking Lot\n");
st.top=-1;
scanf("%d",&size);
Enter_ParkingLot();
Enter_ParkingLot();
display();
return 0;
}
This was my input on terminal-
Enter size of Parking Lot
2
Enter name of owner
ABCD
Enter name of owner
EFGH
This was my output-
`#
`#
There was a blank line before first # in the output.

If you assign the pointer field in struct Car to a local variable, it will not work, you need to redeclare your struct Car like this
struct Car
{
int registrationNo;
char name[100];
};
and then instead of
CC.name=ch;
do it this way
strcpy(CC.name, ch);
also, it's better to write
scanf("%99s",ch);
to prevent overflowing ch, and in your case it would be even better to do
scanf("%99s", CC.name);
I fixed your code
#include <stdio.h>
#include <string.h>
struct Car
{
int registrationNo;
char name[100];
};
struct ParkingLot
{
struct Car C[10];
};
struct stack
{
struct ParkingLot P;
int top;
} st;
int stfull(int size)
{
if(st.top >= size - 1)
return 1;
return 0;
}
void push(struct Car item)
{
st.P.C[++(st.top)] = item;
}
int stempty()
{
if (st.top == -1)
return 1;
return 0;
}
void display()
{
int i;
if (stempty() != 0)
printf("\nStack Is Empty!");
else {
for (i = 0 ; i <= st.top ; i++)
printf("\n%s", st.P.C[i].name);
}
}
int Enter_ParkingLot(int count, int size)
{
struct Car CC;
if (stfull(size) == 1)
printf("Parking Lot is FUll\n");
else
{
CC.registrationNo = count;
printf("Enter name of owner\n");
scanf("%99s", CC.name);
push(CC);
}
return count + 1;
}
int main()
{
int size = 0, count = 1;
printf("Enter size of Parking Lot\n");
st.top = -1;
scanf("%d", &size);
count = Enter_ParkingLot(count, size);
count = Enter_ParkingLot(count, size);
display();
return 0;
}
I removed global variables, they where not needed.
I fixed some if/else's which made no sense.
I also applied my previously suggested fixes related to your original problem.

The Problem:
You store the name of the car into an array that is allocated on the stack.
You then copy the pointer to that array to your car object.
The original array then goes out of scope.
You then try to print that array, which no longer exists, via the pointer.
Undefined behavior occurs.
The Solution:
You need to allocate memory for the name of the car with malloc() and use strcpy() to copy it to the car object.

Related

Function to add struct to another struct in C

so I have 3 structs here:
typedef struct {
char *name; // allocated
int commonality;
int weight;
} monster;
typedef struct {
char *name; // allocated
char *description; // allocated
double area;
int monsters;
monster **monsters; // allocated
} region;
typedef struct {
char *name; // allocated
double diameter;
int regions;
region **regions; // allocated
} planet;
I already have function:
monster *new_monster(char *name, int commonality, int weight);
I am trying to create these functions:
void add_monster_to_region(region *r, char *mname, int mcommonality, int weight);
void delete_region_from_planet(planet *p, char *rname);
This is what I have so far, but I don't believe it's right, can anyone tell me what I'm doing wrong and how I can fix it?
void add_monster_to_region(region *r, char *mname, int mcommonality, int mweight)
{
for (int i = 0; i < mcommonality; i++)
{
if (strcmp(mname, r->monsters[i]->name) == 0)
{
r->monsters[i]->name = mname;
}
}
}
Thank you
It would be very helpful to have a minimal reproducible example. It would also clarify what was meant with fully allocated NOT a reference array.
Nevertheless, here is my take on how to create a planet, two regions and how to populate the regions with monsters:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char *name; // allocated
int commonality;
int weight;
} monster;
typedef struct {
char *name; // allocated
char *description; // allocated
double area;
int monster_count;
monster **monsters; // fully allocated, NOT a reference array
} region;
typedef struct {
char *name; // allocated
double diameter;
int region_count;
region **regions; // fully allocated, NOT a reference array
} planet;
monster *new_monster(char *name, int commonality, int weight) {
monster *new_monster = calloc(sizeof(monster), 0);
if (new_monster != NULL) {
new_monster->name = strdup(name);
if (new_monster->name == NULL) {
free(new_monster);
return NULL;
}
new_monster->commonality = commonality;
new_monster->weight = weight;
}
return new_monster;
}
void free_monster(monster *the_monster) {
if (the_monster != NULL) {
if (the_monster->name != NULL) {
free(the_monster->name);
}
free(the_monster);
}
}
void add_monster_to_region(region *r, char *mname, int mcommonality, int mweight)
{
monster *a_monster = new_monster(mname, mcommonality, mweight);
if (a_monster == NULL) return; // no memory
monster **monsters = NULL;
if (r->monsters != NULL) {
monsters = realloc(r->monsters, (r->monster_count + 1) * sizeof(monster *));
} else {
monsters = calloc(sizeof(monster *), 0);
}
if (monsters == NULL) {
free_monster(a_monster);
return; // no memory
}
r->monsters = monsters;
r->monsters[r->monster_count] = a_monster;
r->monster_count++;
}
void delete_region_from_planet(planet *p, char *rname) {
// TODO
}
int main() {
region desert = {"Desert", "Sunny and warm place.", 50.0, 0, NULL};
region ocean = {"Ocean", "Huge wet place.", 500.0, 0, NULL};
region *regions[] = {&desert, &ocean};
planet mud = {"Mud", 100.00, 2, regions};
add_monster_to_region(&desert, "Bug", 100, 100);
add_monster_to_region(&desert, "Zombie", 10, 20);
add_monster_to_region(&ocean, "Shark", 20, 40);
for (int i = 0; i < mud.region_count; i++) {
for (int j = 0; j < mud.regions[i]->monster_count; j++) {
printf("%s %d %d\n",
mud.regions[i]->monsters[j]->name,
mud.regions[i]->monsters[j]->commonality,
mud.regions[i]->monsters[j]->weight
);
}
}
// TODO: release allocated memory
return 0;
}
We can see all monsters in all regions of the defined planet:
$ gcc -Wall monsters.c
$ ./a.out
Bug 100 100
Zombie 10 20
Shark 20 40
$

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).

Trouble with a pointer not being initialized

I'm trying to make a program that asks for a users name and the amount of money they owe to the company. The problem is, every time I try to compile the program I get this warning saying that "user may not be initialized." I'm not quite sure what that means. Any help to out what I'm doing wrong? Thanks!
#define END '\0'
#define LENGTH 20
struct info
{
char lastName[LENGTH];
float payment;
};
int customerS();
void accounts(struct info *userStart, int amount);
void changeNames(struct info *userStart, int amount);
void sort(struct info *userStart, int amount);
void results(struct info *userStart, int amount);
int main()
{
struct info *user;
int amount;
while((amount = customers()) != 0)
{
accounts(user, amount);
changeNames(user, amount);
sortNames(user, amount);
results(user, amount);
free(user);
}
return 0;
}
int customers()
{
int choice;
do
{
printf("\nHow many customers do you have (2 to 300, 0=quit): ",
scanf("%d", &choice);
}
while((choice < 2|| choice > 300) && choice != 0);
return choice;
}
void accounts(struct info *userStart, int amount)
{
struct info *user;
char *name[LENGTH];
float owed;
for(user = userStart; (user - userStart) < amount; user++)
{
scanf (" %s", name[LENGTH]);
getchar();
do
{
name[LENGTH] = getchar();
name[LENGTH]++;
}
while(!('\n'));
user->lastName[LENGTH + 1] = END;
scanf("%f", &owed);
user->payment = owed;
}
return;
}
void changeNames(struct info *userStart, int amount)
{
char *fast = &userStart->lastName[LENGTH],
*slow = &userStart->lastName[LENGTH];
if(tolower(*fast))
*slow++ = toupper(*fast);
while(*fast != END)
{
if(!isspace(*fast) || isalpha(*fast))
*slow++ = tolower(*fast);
fast++;
}
*slow = END;
return;
}
void sort(struct info *userStart, int amount)
{
struct info *user;
char *in,
*out,
temp;
for(out = user->lastName; (out - userStart->lastName) < amount; out++)
{
for(in = out + 1; (in - userStart->lastName) < amount; in++)
{
if(strcmp(user->lastName, userStart->lastName))
{
temp = *out;
*out = *in;
*in = temp;
}
}
}
return;
}
void results(struct info *userStart, int amount)
{
struct info *user;
printf("\nName: %s Payment: $%.2f", user->lastName, user->payment);
return;
}
struct info *user;
This allocates a pointer to a user struct, not the struct itself.
So, you can allocate it on the stack via struct info user; and pass &user to the functions, or dynamically allocated it via user = (struct info*)malloc( sizeof(struct info) ).
Either way should avoid your segmentation fault (because the pointer is not initialized).
..)

How to print string into an array after used the isdigit?

I'm very new to isdigit and the string. I really need help from you guys. I want to print string into an array 'food[f]'.But can you guys help me to check where is my problem ? Here is my code.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main()
{
char foo[20];
float price;
int number=1;
int f=0,i=0;
char *food[f];
adding_food :
food[f] = (char*)malloc(25);
printf("Adding food into Menu (0 to Main Menu): ");
scanf("%s", foo);
{
if(isdigit(foo[0])== 0)
{
foo[i] = *food[f]; //something wrong here
printf("Enter price (RM) : ");
scanf("%f",&price);
printf("\n%-16d%-19s%6.2f\n\n",number,foo,price);
printf("\n%-16d%-19s%6.2f\n\n",number,food[f],price);
number++;
i++;
f++;
goto adding_food;
}
else
return 0;
}
}
I would like my output be like this
Adding food into Menu (0 to Main Menu) : Cake
Enter price (RM) : 10
1 Cake 10 //foo[0]
1 Cake 10 //food[0]
There are several mistakes in your code. Example:
char *food[f];
is similar to
char *food[0];
as f is zero. That makes no sense.
Also the use of goto is not considered good style.
So let me show you another approach. Something like:
// Make a type that can hold both a name and a price
struct item
{
char name[25];
float price;
};
#define MAX_ITEMS 100
struct item* addItems(int* n)
{
*n = 0;
struct item* items = malloc(MAX_ITEMS * sizeof *items);
if (items == NULL) return NULL;
while (*n != MAX_ITEMS)
{
scanf("%24s", items[*n].name);
if (items[*n].name[0] == '0') break;
scanf("%f", &items[*n].price);
*n += 1;
}
return items;
}
void print_all(struct item* my_items, int num_items)
{
for (int i = 0; i < num_items; ++i)
printf("%s %f\n", my_items[i].name, my_items[i].price);
}
int main()
{
int num_items;
struct item* my_items = addItems(&num_items);
print_all(my_items, num_items);
free(my_items);
}

C Programming: Read from file and print on screen

I am trying to read a file test.txt via fscanf and store it in a array of struct. I have posted the code that I have tried. Looks like problem here is with load function
This is what I have in test.txt:
205,11.20,John Snow
336,23.40,Winter is coming
220,34.20,You know nothing
load function uses loadinput function to read test.txt file into the “item” array and sets the target of the “NoPtr” to the number of Items read from the file (which in this case should be 3).
After reading the file, I am also trying to print it on screen, but it won't work. Nothing is displayed at all.
This program compiles. What is it that I am doing wrong here?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Item {
double value;
int unit;
char name[50];
};
int load(struct Item* item, char Name[], int* NoPtr);
int loadinput(struct Item* item, FILE* data);
void display(struct Item item, int variableA);
int main(void)
{
struct Item FIN[3];
int i, n;
load(FIN, "test.txt", &n);
for (i = 0; i < n; i++)
{
display(FIN[i],0);
}
return 0;
}
int load(struct Item* item, char Name[], int* NoPtr)
{
struct Item ARR[3];
int flagcheck;
FILE* fl;
fl = fopen("Name[]", "r");
while (fl)
{
flagcheck = loadinput(&ARR, fl);
if (flagcheck < 0)
{
fclose(fl);
break;
}
else
{
*NoPtr++;
}
fclose(fl);
}
return 0;
}
int loadinput(struct Item* item, FILE* data)
{
int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value);
if (ret != 2) {
return -1;
}
fgets(item->name, sizeof item->name, data);
item->name[strlen(item->name)-1] = '\0';
return 0;
}
void display(struct Item item, int variableA)
{
printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name);
return;
}
see fix demo – BLUEPIXY
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Item {
double value;
int unit;
char name[50];
};
int load(struct Item* item, char Name[], int* NoPtr);
int loadinput(struct Item* item, FILE* data);
void display(struct Item item, int variableA);
int main(void) {
struct Item FIN[3];
int i, n;
load(FIN, "test.txt", &n);
for (i = 0; i < n; i++) {
display(FIN[i],0);
}
return 0;
}
int load(struct Item* item, char Name[], int* NoPtr){
*NoPtr = 0;
int flagcheck;
FILE* fl;
fl = stdin;//fopen(Name, "r");//for ideone
while (fl){
flagcheck = loadinput(&item[*NoPtr], fl);
if (flagcheck < 0){
fclose(fl);
break;
} else {
++*NoPtr;
}
}
return 0;
}
int loadinput(struct Item* item, FILE* data){
int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value);
if (ret != 2) {
return -1;
}
fgets(item->name, sizeof item->name, data);
item->name[strlen(item->name)-1] = '\0';
return 0;
}
void display(struct Item item, int variableA){
printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name);
return;
}

Resources