Shoppinglist program, structs, malloc() and functions - c

I started with an assignment which should include a program that can add remove print, edit, save list.
I am stuck on the first function that should add an item to my grocery list. As you can see, this function (and all other functions) receives a pointer to a shopping list. This is a pointer to the shopping list defined in main(), and my functions should make changes directly to the shopping list that the argument list is pointing to.
The function should ask the user for a name, amount and unit of an item. It should then place it last in the shopping list. The “length” field should always be containing the index to the last position of the array, so this is where the item should be placed. For instance, length is zero when the list is empty, so the first time this function is called, the item should be placed at index zero in list->itemArray.
This function is also responsible for increasing the length of the list. Since we just added one item, the list is now one item longer. Just remember that it should not be possible to add more than 5 items to the list.
If the user enters a non-positive number for amount, the program should tell the user that the input is invalid and repeat the question until a correct answer has been given.
How should I limit the size list to just 5 products?
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include "ShoppingList.h"
int main(void)
{
struct ShoppingList shoppingList;
shoppingList.length = 0; // The shopping list is empty at the start
int option;
do
{
printf("\n\nWelcome to the shopping list manager!\n");
printf("=====================================\n\n");
printf("1. Add an item\n");
printf("2. Display the shopping list\n");
printf("3. Remove an item\n");
printf("4. Change an item\n");
printf("5. Save list\n");
printf("6. Load list\n");
printf("7. Exit\n");
printf("What do you want to do? ");
scanf("%d", &option);
switch (option)
{
case 1: addItem(&shoppingList); break;
case 2: printList(&shoppingList); break;
case 3: removeItem(&shoppingList); break;
case 4: editItem(&shoppingList); break;
case 5: saveList(&shoppingList); break;
case 6: loadList(&shoppingList); break;
case 7: break;
default:
printf("Please enter a number between 1 and 7");
}
} while (option != 7);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include"ShoppingList.h"
#include<stdio.h>
#include<stdlib.h> // For malloc() and free()
void addItem(struct ShoppingList* list)
{
list = (struct ShoppingList*)malloc(sizeof(struct ShoppingList) * 5);
printf("Name for product: ");
scanf("%s", list->itemList[list->length].productName);
do
{
printf("Enter the amount: ");
scanf("%f", &list->itemList[list->length].amount);
if (list->itemList[list->length].amount <= 0.0)
{
printf("Input is invalid.\n");
}
} while (list->itemList[list->length].amount <= 0.0);
printf("Enter unit of item: ");
scanf("%s", list->itemList[list->length].unit);
list->length++;
}
void printList(struct ShoppingList *list)
{
int i;
printf("\nName:\tAmount:\tUnit:\n\n");
for (i = 0; i < list->length; i++) {
printf("%s\t%d\t%s\n", list->itemList[i].productName, list->itemList[i].amount, list->itemList[i].unit);
}
printf("\n\n");
}
void editItem(struct ShoppingList *list)
{
}
void removeItem(struct ShoppingList *list)
{
}
void saveList(struct ShoppingList *list)
{
}
void loadList(struct ShoppingList* list)
{
}
#ifndef SHOPPING_LIST_H
#define SHOPPING_LIST_H
// Struct definitions
struct GroceryItem
{
char productName[20];
float amount;
char unit[10];
};
struct ShoppingList
{
int length;
struct GroceryItem itemList[5];
};
// Function declarations
void addItem(struct ShoppingList *list);
void printList(struct ShoppingList *list);
void editItem(struct ShoppingList *list);
void removeItem(struct ShoppingList *list);
void saveList(struct ShoppingList *list);
void loadList(struct ShoppingList* list);
#endif

Related

Limit items in a shopping list using malloc()?

I am struggling with the function that should add items to a shopping list. I wrote code that works, but I am wondering if there is another way to limit items to 5 by using malloc()?
The length field should always be containing the index to the last position of the array, so this is where the item should be placed. For instance, length is zero when the list is empty,
So the first time this function is called, the item should be placed at index zero in list->itemArray.
This function is also responsible for increasing the length of the list.
Since we just added one item, the list is now one item longer.
Just remember that it should not be possible to add more than 5 items to the list.
#ifndef SHOPPING_LIST_H
#define SHOPPING_LIST_H
// Struct definitions
struct GroceryItem
{
char productName[20];
float amount;
char unit[10];
};
struct ShoppingList
{
int length;
struct GroceryItem itemList[5];
};
// Function declarations
void addItem(struct ShoppingList *list);
void printList(struct ShoppingList *list);
void editItem(struct ShoppingList *list);
void removeItem(struct ShoppingList *list);
void saveList(struct ShoppingList *list);
void loadList(struct ShoppingList* list);
#endif
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include "ShoppingList.h"
int main(void)
{
struct ShoppingList shoppingList;
shoppingList.length = 0; // The shopping list is empty at the start
int option;
do
{
printf("\n\nWelcome to the shopping list manager!\n");
printf("=====================================\n\n");
printf("1. Add an item\n");
printf("2. Display the shopping list\n");
printf("3. Remove an item\n");
printf("4. Change an item\n");
printf("5. Save list\n");
printf("6. Load list\n");
printf("7. Exit\n");
printf("What do you want to do? ");
scanf("%d", &option);
switch (option)
{
case 1: addItem(&shoppingList); break;
case 2: printList(&shoppingList); break;
case 3: removeItem(&shoppingList); break;
case 4: editItem(&shoppingList); break;
case 5: saveList(&shoppingList); break;
case 6: loadList(&shoppingList); break;
case 7: break;
default:
printf("Please enter a number between 1 and 7");
}
} while (option != 7);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include"ShoppingList.h"
#include<stdio.h>
#include<stdlib.h> // For malloc() and free()
/*
The “length” field should always be containing the index to the last position of the array,
so this is where the item should be placed. For instance, length is zero when the list is empty,
so the first time this function is called, the item should be placed at index zero in list->itemArray.
This function is also responsible for increasing the length of the list.
Since we just added one item, the list is now one item longer.
Just remember that it should not be possible to add more than 5 items to the list.
*/
void addItem(struct ShoppingList* list)
{
if (list->length > 4)
{
return 0;
}
printf("Name for product: ");
scanf("%s", list->itemList[list->length].productName);
do
{
printf("Enter the amount: ");
scanf("%f", &list->itemList[list->length].amount);
if (list->itemList[list->length].amount <= 0.0)
{
printf("Input is invalid.\n");
}
} while (list->itemList[list->length].amount <= 0.0);
printf("Enter unit of item: ");
scanf("%s", list->itemList[list->length].unit);
printf("%s was added to the shoppinglist.", list->itemList[list->length].productName);
list->length++;
}

Segmentation Fault with Pointers and Structures

This program is supposed to manipulate a student list. Every time I try to add more than one student I get a segmentation fault error. Also, when I try to print the list recursively I get a segmentation fault error. I think it has to do with how I am saving to the structure and/or calling it. I am very new to programming so I'm sure it is something simple. Any ideas?
//Header file declarations.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//Structure defintion.
struct student {
int ID;
char name[40];
struct student *next;
};
//Type definition.
typedef struct student Student;
//Function prototypes.
int getChoice();
Student *addToList(Student *List);
void printList(Student *List);
void printListRR(Student *List);
void searchList(Student *List);
/*main function
Objective: This function provides runs a function call based on an option selected the user in another function.
Input: This function recieves no input from the user directly but it is passed their menu selection.
Output: The function outputs error messages and a closing salutation to the user. It returns 0.
*/
int main(void) {
int choice = 0;
Student *SLIST = NULL;
//Call getChoice to get user's selection
choice = getChoice();
//Switch-case for the possible menu selections
while(choice >= 0) {
switch(choice) {
case 0 : printf("Bye...\n"); exit(0);
case 1 : SLIST = addToList(SLIST); break;
case 2 : printList(SLIST); break;
case 3 : printListRR(SLIST); break;
case 4 : searchList(SLIST); break;
default: printf("That is not a valid choice\n");
}
choice = getChoice();
}
if(SLIST) free(SLIST);
return 0;
}
int getChoice() {
int choice = 0;
printf("\n****** MENU ******\n");
printf("1. Add new student to list.\n");
printf("2. Print the student list, beginning to end.\n");
printf("3. Recursively print the student list from the end.\n");
printf("4. Search the list for a student.\n");
printf("0. Quit.\n");
printf("\nEnter your choice: ");
scanf("%d", &choice);
return choice;
}
Student *addToList(Student *List){
Student *studentPtr = (Student *) malloc(sizeof(Student));
printf("Student ID: ");
scanf("%d", &(studentPtr->ID));
printf("Student Name: ");
scanf(" %[^\n]", studentPtr->name);
if(List == NULL){
return studentPtr;
}
Student *nextStudent = List;
while (nextStudent->next != NULL){
nextStudent = nextStudent->next;
}
nextStudent->next = studentPtr;
return List;
}
void printList(Student *List){
while(List != NULL){
printf("%d %s\n", List->ID, List->name);
List = List->next;
}
}
void printListRR(Student *List){
if(List == NULL){
return;
}
printListRR(List->next);
}
void searchList(Student *List){
int idSearch;
printf("Enter student ID to search for: ");
scanf("%d", &idSearch);
while(List != NULL){
if(List->ID == idSearch){
printf("%d %s\n", List->ID, List->name);
return;
}
List = List->next;
}
printf("ID %d not found", idSearch);
}
Try initialising studentPtr->next to NULL in addToList()?

I need this queue to also display the student ID as well as the name how do I fix this?

So I'm creating a program that will display a student's ID as well as their name in a queue. I've finally got it to work displaying the users name, but I also need the ID displayed as well. I'm afraid to start messing around to much and mess everything up. Someone show me the way to the light ;).
EDIT: Thanks to Paul R for pointing this out. I didn't realize until now that I'm only going to be able to display one letter at a time for my students name, what did I do wrong here?
#include <stdio.h>
#include <stdlib.h>
struct queueNode
{
int data1;
char data;
struct queueNode *nextPtr;
};
typedef struct queueNode QueueNode;
typedef QueueNode *QueueNodePtr;
void printQueue (QueueNodePtr currentPtr);
int isEmpty (QueueNodePtr headPtr);
char dequeue (QueueNodePtr *headPtr, QueueNodePtr *tailPtr);
void enqueue (QueueNodePtr *headPtr, QueueNodePtr *tailPtr, char value);
void instructions (void);
int main (void)
{
QueueNodePtr headPtr=NULL;
QueueNodePtr tailPtr=NULL;
int choice;
char name;
int ID;
instructions();
printf("?");
scanf("%d",&choice);
while(choice !=3)
{
switch(choice)
{
case 1:
printf("Enter ID: ");
scanf("\n%d", &ID);
printf("Enter Name: ");
scanf("\n%c", &name);
//RETURN HERE TO ENTER LAST NAME
enqueue(&headPtr, &tailPtr, ID);
enqueue(&headPtr, &tailPtr, name);
printQueue(headPtr);
break;
case 2:
if (!isEmpty(headPtr))
{
ID=dequeue(&headPtr, &tailPtr);
name=dequeue(&headPtr, &tailPtr);
printf("%d %c has been dequeued.\n", ID, name);
}
printQueue(headPtr);
break;
default:
printf("Invalid choice.\n\n");
instructions();
break;
}
printf("?");
scanf("%d", &choice);
}
printf("End of Run\n");
return 0;
}
void instructions(void)
{
printf("Enter your choice: \n"
"1 to add to queue\n"
"2 to remove from queue\n"
"3 to exit\n");
}
void enqueue (QueueNodePtr *headPtr, QueueNodePtr *tailPtr, char value)
{
QueueNodePtr newPtr;
newPtr=malloc(sizeof(QueueNode));
if(newPtr!=NULL)
{
newPtr->data = value;
newPtr->nextPtr = NULL;
if(isEmpty (*headPtr))
{
*headPtr=newPtr;
}
else
{
(*tailPtr)->nextPtr=newPtr;
}
*tailPtr=newPtr;
}
else
{
printf("%c not inserted. No memory available.\n", value);
}
}
char dequeue (QueueNodePtr *headPtr, QueueNodePtr *tailPtr)
{
char value;
QueueNodePtr tempPtr;
value = (*headPtr)->data;
tempPtr = *headPtr;
*headPtr = (*headPtr)->nextPtr;
if(*headPtr==NULL)
{
*tailPtr = NULL;
}
free(tempPtr);
return value;
}
int isEmpty(QueueNodePtr headPtr)
{
return headPtr==NULL;
}
void printQueue (QueueNodePtr currentPtr)
{
if(currentPtr==NULL)
{
printf("Queue is empty. \n\n");
}
else
{
printf("The Queue is: \n");
while(currentPtr !=NULL)
{
printf("%c --> ", currentPtr ->data);
currentPtr = currentPtr->nextPtr;
}
printf("NULL\n\n");
}
}
Instead of char data; (a single character) you want e.g. char data[80]; (a char array, aka string). Ditto for char name;. You will need to use a string function such as strcpy to copy strings between your struct data field and your temporary variable name.

Inorder successor of Threaded Binary Tree

I am writing a c program to create threaded binary tree and then to find INORDER SUCCESSOR of a particular node. For this, i am displaying inorder sequence for the TBT constructed and then asking user to input the node to which successor is to be displayed.. I have written function to do this. But i am not getting successor for the FIRST NODE .. Last node's successor is 0 any ways its working fine.. Can any one help me fix this ?
Here is the whole program :
#include<stdio.h>
#include <stdlib.h>
struct tbtnode {
int data;
struct tbtnode *left,*right;
int lbit,rbit,flag;
int child;
}*root=NULL;
typedef struct tbtnode TBT;
TBT *insuc(TBT *t);
void inorder(TBT *);
void create(TBT *);
void create(TBT *root)
{
int x,op,flag,y;
flag=0;
char ch;
TBT *curr=root;
TBT *q,*p;
do
{
printf("\nCurrent node %d \n\n 1.Left Direction.\n\n2.Right Direction",curr->data);
printf("\nEnter ur choice :");
scanf("%d",&op);
switch(op)
{
case 1: if(curr->lbit==1)
{
printf("Enter left child of %d : ",curr->data);
scanf("%d",&x);
q=(TBT *)malloc(sizeof(TBT));
q->data=x;
q->lbit=q->rbit=1;
q->left=curr->left;
q->right=curr;
curr->left=q;
curr->lbit=0;
q->child=0;
flag=1;
}
else
curr=curr->left;
break;
case 2: if(curr->rbit==1)
{
printf("Enter right child of %d :",curr->data);
scanf("%d",&x);
q=(TBT *)malloc(sizeof(TBT));
q->data=x;
q->lbit=q->rbit=1;
q->left=curr;
q->right=curr->right;
curr->right=q;
curr->rbit=0;
q->child=1;
flag=1;
}
else
curr=curr->right;
break;
}
}while(flag==0);
}
void inorder(TBT *head)
{
TBT *t;
t=head->left;
printf("\n");
while(t->lbit==0)
t=t->left;
while(t!=head)
{
printf(" %d",t->data);
t=insuc(t);
}
}
TBT *insuc(TBT *t)
{
if(t->rbit==0)
{
t=t->right;
while(t->lbit==0)
t=t->left;
return(t);
}
else
return(t->right);
}
void inorder_successor(TBT *head,int x)
{
TBT *t;
t=head->left;
printf("\n");
while(t->lbit==0)
t=t->left;
while(t!=head)
{
t=insuc(t);
if(t->data==x)
{
t=insuc(t);
printf(" %d",t->data);
}
}
}
int main()
{
int op,x,n,i=0,item;
char ch;
TBT *head,*root,*succ; //here head indicates dummy variable
head=(TBT *)malloc(sizeof(TBT));
head->left=head;
head->right=head;
head->lbit=1;
head->rbit=1;
do
{
printf("\n****Threaded binary tree operations****");
printf("\n1)create\n2)inorder\n3)Successor\n4)exit");
printf("\nEnter ur choice: ");
scanf("%d",&op);
switch(op)
{
case 1:
printf("\nEnter Number Of Nodes :");
scanf("%d",&n);
printf("\nEnter root data: ");
scanf("%d",&x);
root=(TBT *)malloc(sizeof(TBT));
root->data=x;
root->lbit=root->rbit=1;
root->child=0;
root->left=head->left;
head->left=root;
head->lbit=0;
root->right=head->right;
for(i=0;i<n-1;i++)
create(root);
break;
case 2:
printf("\nInorder Traversal Is:\n");
inorder(head);
break;
case 3: printf("Enter the node to which successor is to be found\n");
scanf("%d",&item);
inorder_successor(head,item);
break;
case 4:
return(0);
break;
}
}while(op<=4);
return 0;
}
please fix - inorder_successor() function for me..
Thank you
You have many problems with your code. To start with you never check for NULL pointers. To continue, you have both a global and a local variable in main called root.
The last thing means that when you allocate memory for root in main, you allocate for the local variable, and the global variable will still be NULL.
There are also other things that look weird, like you assigning the left and right pointer of head to itself.
I think you need to lay it all out on paper first, both how you have it now and how you want it to be. It will help you to better visualize the tree.

Why my doubly linked list's C implementation creating duplicate values?

I coded for doubly linked list implementation in C. In that, after making insertion of values, i am getting duplication of values. i.e. the last value given by me duplicated in all list items.
My code is as follows
header.h
#include<stdio.h>
#include<stdlib.h>
typedef struct doubly_list
{
int id;
char *name;
struct doubly_list *next;
struct doubly_list *prev;
}node;
void insertfirst(node **,int ,char *);
void insertlast(node **,int ,char *);
doubly_list_insert.c
#include"header.h"
void insertfirst(node **head,int id,char *name)
{
node *tmp=(node *)malloc(sizeof(node));
if(NULL == tmp)
{
printf("\nMemory allocation failed\n");
exit(1);
}
tmp->id=id;
tmp->name=name;
tmp->prev=NULL;
if(*head== NULL)
{
tmp->next=NULL;
*head=tmp;
}
else
{
tmp->next=*head;
(*head)->prev=tmp;
*head=tmp;
}
}
void insertlast(node **head,int id,char *name)
{
if(*head==NULL)
{
insertfirst(head,id,name);
return;
}
node *last=*head;
node *tmp=(node *)malloc(sizeof(node));
if(NULL == tmp)
{
printf("\nMemory allocation failed\n");
exit(1);
}
tmp->id=id;
tmp->name=name;
tmp->next=NULL;
while(last->next!=NULL)
{
last=last->next;
}
last->next=tmp;
tmp->prev=last;
}
doubly_list_traverse.c
#include"header.h"
void traverse(node *head)
{
node *tmp=head;
if(head==NULL)
{
printf("\nList is empty\n");
exit(1);
}
while(tmp!=NULL)
{
printf("%d --> %s\n",tmp->id,tmp->name);
tmp=tmp->next;
}
}
And, here comes the main file,
main.c
#include"header.h"
int main()
{
int choice;
int id;
char name[15];
node *root=NULL;
system("clear");
while(1)
{
printf("\n1.Insert First\n");
printf("\n2.Insert Last\n");
printf("\n3.Traverse\n");
printf("\n4.Exit\n");
printf("\nEnter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("\nEnter the employee id : ");
scanf("%d",&id);
printf("\nEnter the employee name : ");
scanf("%s",name);
insertfirst(&root,id,name);
break;
case 2:
printf("\nEnter the employee id : ");
scanf("%d",&id);
printf("\nEnter the employee name : ");
scanf("%s",name);
insertlast(&root,id,name);
break;
case 3:
traverse(root);
break;
case 4:
return 0;
break;
default:
printf("\nPlease enter valid choices\n");
}
}
}
During execution its getting input from me properly,if i insert only one data either first or last.
But if i insert a second one, there comes the problem.
In my case, the id value remains the same. But the 2nd input's name value is duplicated in 1st value.
Why this is happening? Is it anything wrong in passing arguments?
When you create a new node, you set the node name by just copying the pointer to the name. You have to copy the string not the pointer. The strdup function is perfect for this:
tmp->name=strdup(name);
Remember to free the name when you free the nodes.
Edit
What happens when you call insertfirst the first time, is that the name field of the first node points to the name array in main. When you fetch the name for the second node, the contents of the array in main is updated with the new name, and since the pointer in the first node points to that array it seems like the name is duplicated.

Resources