Question on Inventory Management System using C++

HI everyone,

I am doing my first programming project using C++ and found out a sample project from Jeremy Sam’s github. I would love to understand it more thoroughly. In this project, he designed an inventory management system for a book shop which is used for Seller (can update price and stock, check transactions) and Customers (can view book detail, purchase book) . Could anyone explain more in detail some of my concerns as below:

  • Line 35, 36: Why should we use the constructor for these public variables here?
class book
{
private:
    int bookcode;
    string author;
    string title;
    double price;
    string publisher;
    int stock;
public:
    book(int u,string x,string y,string z, double w, int v)            //constructor
    {
        bookcode=u;
        title=x;
        author=y;
        publisher=z;
        price=w;
        stock=v;
  • Should we define functions such as Update (price and stock of a book) in private variables because those should not be accessible without an authorized person (seller), and we define functions such as Search Book (current searching method by Author and Book’s title) and function Show Book Detail in public variables because those should be publicly accessible (from both Customer and Seller side)?

  • Line 174: Our data has 5 books (p1, p2, p3, p4, p5). The search function for books available for purchase is given as below. Does that mean the process will be (1) combine the book p6 constructor with user-input of author and name, (2) get a search function from that constructor object and compare author and publisher name with each book from p1 to p5 and (3) return the result accordingly.

{
            string a;
            string b;
            cout<<"Enter author name: ";
            cin>>a;
            cout<<"Enter publisher name: ";
            cin>>b;
            book p6(a,b);
            if(p6.search(p1)==1)
                p1.noOfcopies();

Currently this is how the book is searched from Customer’s side and declared in public:

public:
book(string x,string y)                                             //constructor
    {
        author=x;
        publisher=y;
    }
    int search(book x)                                                  //searching the book in the list
    {
        if(author==x.author&&publisher==x.publisher)
            return 1;
        else
            return 0;

    book p1(111,"Computer_Architecture","William_Stallings","Pearson",211.5,10);
    book p2(112,"Operating_Systems","Abraham_Silberchatz","Wiley",250,14);
    book p3(113,"C++","Herbert_Shildt","McGraw_Hill",312.5,14);
    book p4(114,"Digital_Electronics","Morris_Mano","Pearson",156,7);
    book p5(115,"Data_Structures","Ellis_Horowitz","University_Press",235,4);

Thank you

1 Like

This is useful so you can initialize variables as you create the Book object. Its not necessary but a lot more convenient than creating setters for these variables later on.

Not really. The public/private definition of functions defines the scope visibility of these functions. If you define them as private you would only be able to call these functions within the Book class object.
If you want to make these function available to sellers then you would need to call it from within the Seller class object therefore you need to make it public.
For example having an updateBook(Book b) function in the Seller class.

From the code its not entirely visible how the search function works exactly. I imagine this is a new class (like Library) that contains a list of books and recursively loops through all the books in a list and counts matches?

1 Like

Thank you!

I should have included the whole code, please refer as below

Regarding the search function which search for a book based on author and publisher name, if I want to design the data table in the format of dictionary (key-value pair with key = Book ID, Value = Book title) and search the book based on key, then how should I code this? Besides, is this approach considered better than the normal search function below or is there any other search method that perform better in term of simplicity and speed?

Thank you

#include <iostream>
using namespace std;

int failure=0;
int success=0;
void Trans(int a)                                 //counts the total failed and successful transaction
{
    if(a==0)
        failure++;
    else
        success++;
}
class book
{
private:
    int bookcode;
    string author;
    string title;
    double price;
    string publisher;
    int stock;

    void priceUpdate()                                           //to update price
    {
        cout<<"\nEnter the new price: ";
        cin>>price;
        cout<<endl;
    }
    void stockUpdate()                                             //to update stock
    {
        cout<<"\nEnter the new stock: ";
        cin>>stock;
        cout<<endl;
    }
public:
    book(int u,string x,string y,string z, double w, int v)            //constructor
    {
        bookcode=u;
        title=x;
        author=y;
        publisher=z;
        price=w;
        stock=v;
    }
    book(string x,string y)                                             //constructor
    {
        author=x;
        publisher=y;
    }
    int search(book x)                                                  //searching the book in the list
    {
        if(author==x.author&&publisher==x.publisher)
            return 1;
        else
            return 0;
    }
         void noOfcopies()                             //checking no. of copies and calculating the total price
    {
        int n;
        cout<<"\nBook Details: "<<endl;
        showdetail();
        cout<<"Enter required number of copies: ";
        cin>>n;
        if(n>stock)
        {
            cout<<"Required copies is not in stock"<<endl;
            Trans(0);
        }
        else
        {
            cout<<"Total cost of the books: "<<n*price<<endl;
            stock=stock-n;
            cout<<"\nRemaining stock: "<<stock<<endl;
            Trans(1);
        }
    }
   void showdetail()                                                     //display book details
    {
        cout<<"Book code: "<<bookcode<<endl;
        cout<<"Author: "<<author<<endl;
        cout<<"Publisher: "<<publisher<<endl;
        cout<<"Title: "<<title<<endl;
        cout<<"Price: "<<price<<endl;
        cout<<"The stocks available: "<<stock<<endl;
        cout<<endl;
    }
    void update()                                                           //update price and stock
    {
        int x;
        cout<<"Select what to update\n1.Price\n2.Stock"<<endl;
        cin>>x;
        if(x==1)
            priceUpdate();
        else
            stockUpdate();
    }
};

    book p1(111,"Computer_Architecture","William_Stallings","Pearson",211.5,10);
    book p2(112,"Operating_Systems","Abraham_Silberchatz","Wiley",250,14);
    book p3(113,"C++","Herbert_Shildt","McGraw_Hill",312.5,14);
    book p4(114,"Digital_Electronics","Morris_Mano","Pearson",156,7);
    book p5(115,"Data_Structures","Ellis_Horowitz","University_Press",235,4);


void seller()                                                    // seller options
{
    int a,n;
    while(1){
    cout<<"Enter ur choice: \n1.Show books\n2.Update\n3.Transactions\n4.Exit"<<endl;
    cin>>a;
    cout<<endl;
    switch(a)
    {
        case 1: cout<<"\nBook Details: "<<endl;
                p1.showdetail();
                p2.showdetail();
                p3.showdetail();
                p4.showdetail();
                p5.showdetail();
                break;

        case 2: cout<<"Book Update"<<endl;
                cout<<"Enter the book code which has to be updated: ";
                cin>>n;
                if(n==111)
                    p1.update();
                else if(n==112)
                    p2.update();
                else if(n==113)
                    p3.update();
                else if(n==114)
                    p4.update();
                else if(n==115)
                    p5.update();
                else
                    cout<<"Invalid"<<endl;
                    break;

        case 3: cout<<"Total failed transaction: "<<failure<<endl;
                cout<<"Total successful transaction: "<<success<<endl;
                cout<<endl;
                break;
        case 4:
                return;
    }
   }
}
void customer()                                             //customer options
{
    int x;
    while(1)
    {
        cout<<"\nEnter a option \n1.Show Books\n2.Purchase a book\n3.Exit"<<endl;
        cin>>x;
        if(x==1)
        {
            cout<<"\nBook Details: "<<endl;
            p1.showdetail();
            p2.showdetail();
            p3.showdetail();
            p4.showdetail();
            p5.showdetail();
        }

        else if(x==2)
        {
            string a;
            string b;
            cout<<"Enter author name: ";
            cin>>a;
            cout<<"Enter publisher name: ";
            cin>>b;
            book p6(a,b);
            if(p6.search(p1)==1)
                p1.noOfcopies();
            else if(p6.search(p2)==1)
                p2.noOfcopies();
            else if(p6.search(p3)==1)
                p3.noOfcopies();
            else if(p6.search(p4)==1)
                p4.noOfcopies();
            else if(p6.search(p5)==1)
                p5.noOfcopies();
            else
            {
                cout<<"This book is not available"<<endl;
                Trans(0);
            }
        }
        else
            return;
    }
}

int main()
{
    int a;
    while(1)
    {
        cout<<"\nSelect any one\n1.Seller\n2.Customer\n3.Exit"<<endl;
        cin>>a;
        cout<<endl;
        if(a==1)
            seller();
        else if(a==2)
                customer();
        else
            return 0;
    }
}

Thank you!

I should have included the whole code, please refer as below

Regarding the search function which search for a book based on author and publisher name, if I want to design the data table in the format of dictionary (key-value pair with key = Book ID, Value = Book title) and search the book based on key, then how should I code this? Besides, is this approach considered better than the normal search function below or is there any other search method that perform better in term of simplicity and speed?

Thank you

#include <iostream>
using namespace std;

int failure=0;
int success=0;
void Trans(int a)                                 //counts the total failed and successful transaction
{
    if(a==0)
        failure++;
    else
        success++;
}
class book
{
private:
    int bookcode;
    string author;
    string title;
    double price;
    string publisher;
    int stock;

    void priceUpdate()                                           //to update price
    {
        cout<<"\nEnter the new price: ";
        cin>>price;
        cout<<endl;
    }
    void stockUpdate()                                             //to update stock
    {
        cout<<"\nEnter the new stock: ";
        cin>>stock;
        cout<<endl;
    }
public:
    book(int u,string x,string y,string z, double w, int v)            //constructor
    {
        bookcode=u;
        title=x;
        author=y;
        publisher=z;
        price=w;
        stock=v;
    }
    book(string x,string y)                                             //constructor
    {
        author=x;
        publisher=y;
    }
    int search(book x)                                                  //searching the book in the list
    {
        if(author==x.author&&publisher==x.publisher)
            return 1;
        else
            return 0;
    }
         void noOfcopies()                             //checking no. of copies and calculating the total price
    {
        int n;
        cout<<"\nBook Details: "<<endl;
        showdetail();
        cout<<"Enter required number of copies: ";
        cin>>n;
        if(n>stock)
        {
            cout<<"Required copies is not in stock"<<endl;
            Trans(0);
        }
        else
        {
            cout<<"Total cost of the books: "<<n*price<<endl;
            stock=stock-n;
            cout<<"\nRemaining stock: "<<stock<<endl;
            Trans(1);
        }
    }
   void showdetail()                                                     //display book details
    {
        cout<<"Book code: "<<bookcode<<endl;
        cout<<"Author: "<<author<<endl;
        cout<<"Publisher: "<<publisher<<endl;
        cout<<"Title: "<<title<<endl;
        cout<<"Price: "<<price<<endl;
        cout<<"The stocks available: "<<stock<<endl;
        cout<<endl;
    }
    void update()                                                           //update price and stock
    {
        int x;
        cout<<"Select what to update\n1.Price\n2.Stock"<<endl;
        cin>>x;
        if(x==1)
            priceUpdate();
        else
            stockUpdate();
    }
};

    book p1(111,"Computer_Architecture","William_Stallings","Pearson",211.5,10);
    book p2(112,"Operating_Systems","Abraham_Silberchatz","Wiley",250,14);
    book p3(113,"C++","Herbert_Shildt","McGraw_Hill",312.5,14);
    book p4(114,"Digital_Electronics","Morris_Mano","Pearson",156,7);
    book p5(115,"Data_Structures","Ellis_Horowitz","University_Press",235,4);


void seller()                                                    // seller options
{
    int a,n;
    while(1){
    cout<<"Enter ur choice: \n1.Show books\n2.Update\n3.Transactions\n4.Exit"<<endl;
    cin>>a;
    cout<<endl;
    switch(a)
    {
        case 1: cout<<"\nBook Details: "<<endl;
                p1.showdetail();
                p2.showdetail();
                p3.showdetail();
                p4.showdetail();
                p5.showdetail();
                break;

        case 2: cout<<"Book Update"<<endl;
                cout<<"Enter the book code which has to be updated: ";
                cin>>n;
                if(n==111)
                    p1.update();
                else if(n==112)
                    p2.update();
                else if(n==113)
                    p3.update();
                else if(n==114)
                    p4.update();
                else if(n==115)
                    p5.update();
                else
                    cout<<"Invalid"<<endl;
                    break;

        case 3: cout<<"Total failed transaction: "<<failure<<endl;
                cout<<"Total successful transaction: "<<success<<endl;
                cout<<endl;
                break;
        case 4:
                return;
    }
   }
}
void customer()                                             //customer options
{
    int x;
    while(1)
    {
        cout<<"\nEnter a option \n1.Show Books\n2.Purchase a book\n3.Exit"<<endl;
        cin>>x;
        if(x==1)
        {
            cout<<"\nBook Details: "<<endl;
            p1.showdetail();
            p2.showdetail();
            p3.showdetail();
            p4.showdetail();
            p5.showdetail();
        }

        else if(x==2)
        {
            string a;
            string b;
            cout<<"Enter author name: ";
            cin>>a;
            cout<<"Enter publisher name: ";
            cin>>b;
            book p6(a,b);
            if(p6.search(p1)==1)
                p1.noOfcopies();
            else if(p6.search(p2)==1)
                p2.noOfcopies();
            else if(p6.search(p3)==1)
                p3.noOfcopies();
            else if(p6.search(p4)==1)
                p4.noOfcopies();
            else if(p6.search(p5)==1)
                p5.noOfcopies();
            else
            {
                cout<<"This book is not available"<<endl;
                Trans(0);
            }
        }
        else
            return;
    }
}

int main()
{
    int a;
    while(1)
    {
        cout<<"\nSelect any one\n1.Seller\n2.Customer\n3.Exit"<<endl;
        cin>>a;
        cout<<endl;
        if(a==1)
            seller();
        else if(a==2)
                customer();
        else
            return 0;
    }
}

Ahh I see, this search is not really good. It just compares books that are predefined in the code. If you would want to make it more dynamic you would like to search newly created books as well.
For this you would need to implement a list of some sort. This can be done in many ways like linked lists or trees but can get quite complex. For starters you can try implementing a simple linked list as a Library class containing Books. I found a good example how to implement it here:
https://www.bogotobogo.com/cplusplus/linkedlist.php

Alternatively you could also use a predefined structure like a vector
https://www.cplusplus.com/reference/vector/vector/

If you are willing to learn I would go with the first approach because it will give you an in depth knowledge of data structures and its quite a good skill to learn in programming :slight_smile:

Thanks!

So I use the first example in your suggested reading (pls refer full code below)

and I get this error

apple@192 Game % g++ search.cpp
search.cpp:46:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^

The error is from this block of code


struct Node *searchNode(struct Node *head, int n) {
	Node *cur = head;
	while(cur) {
		if(cur->data == n) return cur;
		cur = cur->next;
	}
	cout << "No Node " << n << " in list.\n";
}

So I google and it says

Problem: I received the following warning:

warning: control reaches end of non-void function

Copy code

Solution: This warning is similar to the warning described in Return with no value. If control reaches the end of a function and no return is encountered, GCC assumes a return with no return value. However, for this, the function requires a return value. At the end of the function, add a return statement that returns a suitable return value, even if control never reaches there.

Can you please explain in detail this block of code for searchNode (what does it say, how it processes) and what is the return value should I define here?

Thanks

Full code is as below

#include <iostream>

using namespace std;

struct Node {
	int data;
	Node* next;
};

// only for the 1st Node
void initNode(struct Node *head,int n){
	head->data = n;
	head->next =NULL;
}

// apending
void addNode(struct Node *head, int n) {
	Node *newNode = new Node;
	newNode->data = n;
	newNode->next = NULL;

	Node *cur = head;
	while(cur) {
		if(cur->next == NULL) {
			cur->next = newNode;
			return;
		}
		cur = cur->next;
	}
}

void insertFront(struct Node **head, int n) {
	Node *newNode = new Node;
	newNode->data = n;
	newNode->next = *head;
	*head = newNode;
}

struct Node *searchNode(struct Node *head, int n) {
	Node *cur = head;
	while(cur) {
		if(cur->data == n) return cur;
		cur = cur->next;
	}
	cout << "No Node " << n << " in list.\n";
}

bool deleteNode(struct Node **head, Node *ptrDel) {
	Node *cur = *head;
	if(ptrDel == *head) {
		*head = cur->next;
		delete ptrDel;
		return true;
	}
	
	while(cur) {
		if(cur->next == ptrDel) {
			cur->next = ptrDel->next;
			delete ptrDel;
			return true;
		}
		cur = cur->next;
	}
	return false;
}

/* reverse the list */
struct Node* reverse(struct Node** head) 
{
	Node *parent = *head;
	Node *me = parent->next;
	Node *child = me->next;

	/* make parent as tail */
	parent->next = NULL;
	while(child) {
		me->next = parent;
		parent = me;
		me = child;
		child = child->next;
	}
	me->next = parent;
	*head = me;
	return *head;
}

/* Creating a copy of a linked list */
void copyLinkedList(struct Node *node, struct Node **pNew)
{
	if(node != NULL) {
		*pNew = new Node;
		(*pNew)->data = node->data;
		(*pNew)->next = NULL;
		copyLinkedList(node->next, &((*pNew)->next));
	}
}

/* Compare two linked list */
/* return value: same(1), different(0) */
int compareLinkedList(struct Node *node1, struct Node *node2)
{
	static int flag;

	/* both lists are NULL */
	if(node1 == NULL && node2 == NULL) {
		flag = 1;
	}
	else {
		if(node1 == NULL || node2 == NULL) 
			flag = 0;
		else if(node1->data != node2->data) 
			flag = 0;
		else
			compareLinkedList(node1->next, node2->next);
	}

	return flag;
}

void deleteLinkedList(struct Node **node)
{
	struct Node *tmpNode;
	while(*node) {
		tmpNode = *node;
		*node = tmpNode->next;
		delete tmpNode;
	}
}

void display(struct Node *head) {
	Node *list = head;
	while(list) {
		cout << list->data << " ";
		list = list->next;
	}
	cout << endl;
	cout << endl;
}

int main() 
{
	struct Node *newHead;
	struct Node *head = new Node;
	
	initNode(head,10);
	display(head);

	addNode(head,20);
	display(head);

	addNode(head,30);
	display(head);

	addNode(head,35);
	display(head);

	addNode(head,40);
	display(head);

	insertFront(&head,5);
	display(head);

	int numDel = 5;
	Node *ptrDelete = searchNode(head,numDel);
	if(deleteNode(&head,ptrDelete)) 
		cout << "Node "<< numDel << " deleted!\n";
	display(head);

	cout << "The list is reversed\n";
	reverse(&head);
	display(head);

	cout << "The list is copied\n";
	copyLinkedList(head,&newHead);
	display(newHead);

	cout << "Comparing the two lists...\n";
	cout << "Are the two lists same?\n";
	if(compareLinkedList(head,newHead)) 
		cout << "Yes, they are same!\n";
	else
		cout << "No, they are different!\n";
	cout << endl;

	numDel = 35;
	ptrDelete = searchNode(newHead,numDel);
	if(deleteNode(&newHead,ptrDelete)) {
		cout << "Node "<< numDel << " deleted!\n";
		cout << "The new list after the delete is\n";
		display(newHead);
	}
	cout << "Comparing the two lists again...\n";
	cout << "Are the two lists same?\n";
	if(compareLinkedList(head,newHead)) 
		cout << "Yes, they are same!\n";
	else
		cout << "No, they are different!\n";
    
	cout << endl;
	cout << "Deleting the copied list\n";
	deleteLinkedList(&newHead);
	display(newHead);
	return 0;
}

Hi @Alko89 could you provide a specific example when the constructor is more convenient than the setter? I read about setters and understand this is used when you want to update/ validate the variables. Thanks

Ahh I see the error, the function has a case where it might not return a value, you could either return null or the head node at the end of the function.

You can validate variables in both cunstructor or setter functions, the benefit of using a constructor is you can initialize the variables when you initialize the class. You can even use setters within the constructor.

The simplest example would be:

class ConstructorSetter {
    int a;
    int b;
    
public:
    // Constructors are declared with the same name as the class name
    ConstructorSetter(int _a, int _b) {
        // You can set a value in the constructor using a setter function
        setA(_a);
        // You can also validate _b in constructor but can only set it once you initialize your class
        b = _b;
    }
    
    void setA(int _a) {
        // You can have some validation here and can later set a differrent value to the variable a
        a = _a;
    }
    
    void printVals() {
        cout<< a << "\t" << b << "\n";
    }
};

int main()
{
    ConstructorSetter *cs = new ConstructorSetter(1, 2);
    
    cs->printVals();
    
    cs->setA(3);
    
    cs->printVals();
    
    return 0;
}