In: Computer Science
Please edit the code with linked lists in C++
Please provide your BookData.txt file as well
BookRecord.cpp file
#include "BookRecord.h"
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fstream>
using namespace std;
BookRecord::BookRecord() {
strcpy_s(m_sName, "");
m_lStockNum = 0;
m_iClassification = 0;
m_dCost = 0.0;
m_iCount = 0;
}
BookRecord::BookRecord(const char* name, long sn, int cl, double
cost) {
strcpy_s(m_sName, name);
m_lStockNum = sn;
m_iClassification = cl;
m_dCost = cost;
m_iCount = 1;
}
BookRecord::~BookRecord() {
}
void BookRecord::getName(char* name) {
for (int i = 0; i < 128; ++i)
*name++ = m_sName[i];
}
void BookRecord::setName(const char* name) {
strcpy_s(m_sName, name);
}
long BookRecord::getStockNum() {
return m_lStockNum;
}
void BookRecord::setStockNum(long sn) {
m_lStockNum = sn;
}
void BookRecord::getClassification(int& cl) {
cl = m_iClassification;
}
void BookRecord::setClassification(int cl) {
m_iClassification = cl;
};
void BookRecord::getCost(double* c) {
*c = m_dCost;
};
void BookRecord::setCost(double c) {
m_dCost = c;
};
int BookRecord::getNumberInStock() {
return m_iCount;
}
void BookRecord::setNumberInStock(int count) {
m_iCount = count;
}
void BookRecord::printRecord(char FileOut[128]) {
ofstream outFile;
outFile.open(FileOut, std::ios_base::app);
getName(m_sName);
getClassification(m_iClassification);
getCost(&m_dCost);
cout << endl << "Name: " << m_sName
<< " " << "Stock Num: " << getStockNum() <<
" " << "Classification: " << m_iClassification <<
" " << "Cost: " << m_dCost << " " <<
"Count: " << getNumberInStock() << " ";
outFile << endl << "Name: " <<
m_sName << " " << "Stock Num: " << getStockNum()
<< " " << "Classification: " << m_iClassification
<< " " << "Cost: " << m_dCost << " "
<< "Count: " << getNumberInStock() << " ";
}
BookRecord.h file
#pragma once
class BookRecord {
private:
char m_sName[128]; // stores the name of the book or
periodical
long m_lStockNum; // stores a unique stock number for
the book or periodical
int m_iClassification; //codes spefic information
about the book or periodical
double m_dCost; //stores the cost of the book or
periodical
int m_iCount; //stores the number of copies of the
item currently in the inventory
public:
BookRecord(); //constructor
BookRecord(const char* name, long sn, int cl, double
cost);
~BookRecord(); //destructor
void getName(char* name);
void setName(const char* name);
long getStockNum();
void setStockNum(long sn);
void getClassification(int& cl);
void setClassification(int cl);
void getCost(double* c);
void setCost(double c);
int getNumberInStock();
void setNumberInStock(int count);
void printRecord(char outFile[128]);
};
All requirements stated and illustrated in the excerpt from the Software Requirements Specification (see below) shall be followed.
You will be required to meet ALL of the requirements stated below.
2.1 System Organization
2.1.1
This program shall be implemented in C++ as a sorted (ordered) linked list. With nodes ordered by stock number.
2.1.2
The class used to store information on each book shall shall be the BookRecord class developed in Programming Assignment 1 with appropriate modifications so that it can be used in a linked list.
2.1.3
All list functions shall be defined in a C++ class called Book_Inventory. The class shall be defined as follows:
//----------------------------------------------------------------------------- // File: Book_Inventory.h // Header file for a book inventory program implemented as a sorted linked list // // Note: All functions which print data on a book must print an appropriate // message if it fails to find any book(s) meeting the search criteria //----------------------------------------------------------------------------- #pragma once; #include<iostream> // This header lets you use cout and cin #include<fstream> // This header gives you all the file I/O functions #include<string.h> #include<stdlib.h> #include "BookRecord.h" using namespace std; // This command lets you use all the I/O function and include headers w/o the ".h" class Book_Inventory { private: BookRecord *m_pHead; // Pointer to the head of the list ifstream m_InFile; // File containing the inventory public: Book_Inventory(); // Class constructor ~Book_Inventory(); // Class destructor. Must free all list memory void ClearList(); // Remove all items from the list bool readInventory(const char *filename); // Read inventory file and build the list bool addBook(BookRecord *br); // Add the given book to the list BookRecord *removeBook(long stockNum); // Remove a book from the list or print message if not found BookRecord *searchByStockNumber(long stockNum); // Search by stock number return pointer to node or NULL if not found void searchByClassification(int cl); // Search for all books given classification, print all data void searchByCost(double min, double max); // Search for all books within the given cost range int getNumberInStock(long sn); // Get number of books in stock for the given stock number void printAll(); // Print all information on all books in the inventory. private: bool getNextLine(char *line, int lineLen); // read next line from a file };
2.1.4
The BookRecord class shall have the private variable BookRecord *m_pNext, and the public functions void setNext(BookRecord *next) and BookRecord *getNext() added to it
2.1.5
When data on a book is printed on the screen it shall be all on a single line in the following format:
Title Stock_Num Classification
Cost In Stock
For example:
Introduction to
C++ 12345
613 49.95 5
2.1.6
Format of the data file to be read shall be as follows:
# Any line beginning with a pound sign shall
be ignored as a comment line
# First non-comment line will give the number of
books in the file
# Remaining lines will give the stock number,
Title, classification,
# cost and number in stock. Each shall be on a
separate line.
# Example:
25
12345
CS221 A Programming Challenge
613
23.95
15
# etc. for the remaining books in this list.
Note: Do not assume that the data file that will be used to test your program will be the same as the example provided.
2.1.7
Source code which can be adapted for use in the readInventory() function will be provided from the company Code Reuse Library.
2.1.8
The getClassification function in BookRecord shall be modified so that it functions as a "normal" get function, that is it shall return the classification value. Prototype the function as follows:
int getClassification();
2.1.9
The getCost function in BookRecord shall be modified so that it
functions as a "normal" get function, that is it shall
return the cost value. Prototype the function as follows:
double
getCost();
Source Code Reuse Library
The following function fragment shows how to open a file and
start to read lines from the file
using the getNextLine() function. Either the Book_Inventory.h file
or the Book_Inventory.cpp
file will have to #include <string.h>,
<stdlib.h>, <iostream> and
<fstream> and include
the line using namespace std for this to work.
//-------------------------------------------- // Function: readInventory() // Purpose: Read the inventory data file and // build the list. // Returns: True if successful read //-------------------------------------------- bool Book_Inventory::readInventory(const char *filename) { char line[128]; int numBooks; // define other variables here as needed m_InFile.open(filename, ifstream::in); if(!m_InFile.is_open()) { // m_InFile.is_open() returns false if the file could not be found or // if for some other reason the open failed. cout << "Unable to open file" << filename << "\nProgram terminating...\n"; return false; } // Read number of books getNextLine(line, 128); numBooks = atoi(line); for(int i=0; i<numBooks; i++) { // ------------------------------------------ // Your code to read the inventory goes here // ------------------------------------------ } return true; }
The atoi() (Ascii TO Integer) function is found
in stdlib.h. It takes a string
(character array) as an argument. The string must be a string
representation of an
integer value. For example: "25". The function then parses the
string and returns
the int value represented by the string. There are also two other
functions in stdlib.h
which may be useful. These are atof() (Ascii TO
Float) which returns a double
value and atol() (Ascii TO Long) which returns a
long value.
The following function can be added to your Book_Inventory class as
a private function.
It uses a class variable called m_InFile that is a reference to an
open text file (opened by
the readInventory() function) and will read the next line from the
file storing it in the
character array pointed to by line which should be a minimum of 128
characters in length.
The lineLen argument gives the length of the array.
getNextLine() will skip any comment lines
(those starting with #) and blank lines. It returns an empty string
after the last line in
the file has been read.
//-------------------------------------------- // Function: getNextLine() // Purpose: Read a line from a data file. // The next non-comment line read from file // is stored in line char array. // An empty string is stored if the end of // file is reached. // Returns: bool - true if a valid line was // read, false if end of file is reached. //-------------------------------------------- bool Book_Inventory::getNextLine(char *line, int lineLen) { int done = false; while(!done) { m_InFile.getline(line, lineLen); if(m_InFile.good()) // If a line was successfully read { if(strlen(line) == 0) // Skip any blank lines continue; else if(line[0] == '#') // Skip any comment lines continue; else return true; // Got a valid data line so return with this line } else // No valid line read, meaning we reached the end of file { strcpy(line, ""); // Copy empty string into line as sentinal value return false; } } // end while return false; // Cannot reach this point but include a return to avoid compiler warning // that not all paths return a value. }
Here I am attaching code for these files:
main.cpp
BookRecord.cpp
BookRecord.h
Book_Inventory.cpp
Book_Inventory.h
main.cpp:
#include "Book_Inventory.h"
using namespace std;
int main()
{
Book_Inventory *Store = new Book_Inventory();
BookRecord *Book1 = new BookRecord("Hello World!",
2345, 343, 56.45);
BookRecord *Book2 = new BookRecord("Text", 4561, 2342,
3.45);
BookRecord *Book3 = new BookRecord("The virtues of
stuff", 2345, 443, 3.99);
BookRecord *Book4 = new BookRecord();
BookRecord *book = new BookRecord();
Store->readInventory("BookData.txt");
Store->addBook(Book1);
Store->addBook(Book3);
Store->addBook(Book2);
Store->printAll();
cout<<"\n";
book = Store->searchByStockNumber(2345);
book->printRecord();
return 0;
}
BookRecord.cpp:
#include "BookRecord.h"
#include <string.h>
using namespace std;
//Default BookRecord Constructor
//Sets each value to null.
BookRecord::BookRecord()
{
strcpy(m_sName, "");
m_lStockNum = 0;
m_iClassification = 0;
m_dCost = 0.0;
m_iCount = 0;
m_pNext = NULL;
}
//Overloaded BookRecord Constructor
//Sets each value to respected argument.
BookRecord::BookRecord(char *name, long sn, int cl, double
cost)
{
strcpy(m_sName, name);
m_lStockNum = sn;
m_iClassification = cl;
m_dCost = cost;
m_iCount = 1;
m_pNext = NULL;
}
//BookRecord Destructor
//Deletes BookRecord instance.
BookRecord::~BookRecord()
{
}
//BookRecord setName
//Sets book name to given argument
void BookRecord::setName(char *name)
{
strcpy(m_sName, name);
}
//BookRecord getName
//Returns value m_sName
void BookRecord::getName(char *name)
{
strcpy(name, m_sName);
}
//BookRecord setStockNum
//Sets the book stock number to given argument.
void BookRecord::setStockNum(long sn)
{
m_lStockNum = sn;
}
//BookRecord getStockNum
//Returns value m_lStockNum
long BookRecord::getStockNum()
{
return m_lStockNum;
}
//BookRecord setClassification
//Sets the book classification to given argument
void BookRecord::setClassification(int cl)
{
m_iClassification = cl;
}
//BookRecord getClassification
//Returns value m_iClassification
void BookRecord::getClassification(int& cl)
{
cl = m_iClassification;
}
//BookRecord setCost
//Sets the book cost to the given argument
void BookRecord::setCost(double c)
{
m_dCost = c;
}
//BookRecord getCost
//Returns the value m_dCost
double BookRecord::getCost()
{
return m_dCost;
}
//BookRecord setNumberInStock
//Sets number in stock to given argument
void BookRecord::setNumberInStock(int count)
{
m_iCount = count;
}
//BookRecord getNumberInStock
//Returns the value m_iCount
int BookRecord::getNumberInStock()
{
return m_iCount;
}
//BookRecord printRecord
//Prints the information about the book
void BookRecord::printRecord()
{
cout<<m_sName<<" ";
cout<<m_lStockNum<<" ";
cout<<m_iClassification<<" ";
cout<<m_dCost<<" ";
cout<<m_iCount<<endl;
}
void BookRecord::setNext(BookRecord *next)
{
m_pNext = next;
}
BookRecord* BookRecord::getNext()
{
return m_pNext;
}
BookRecord.h:
#ifndef BOOKRECORD_H
#define BOOKRECORD_H
#include <iostream>
class BookRecord
{
private:
char m_sName[128];
long m_lStockNum;
int m_iClassification;
double m_dCost;
int m_iCount;
BookRecord *m_pNext;
public:
BookRecord();
BookRecord(char *name, long
sn, int cl, double cost);
~BookRecord();
void getName(char
*name);
void setName(char
*name);
long getStockNum();
void setStockNum(long
sn);
void
getClassification(int& cl);
void setClassification(int
cl);
double getCost();
void setCost(double c);
int getNumberInStock();
void setNumberInStock(int
count);
void printRecord();
void setNext(BookRecord
*next);
BookRecord *getNext();
};
#endif
Book_Inventory.cpp:
#include "Book_Inventory.h"
using namespace std;
//This is the constructor for the class.
//It sets head to null.
Book_Inventory::Book_Inventory()
{
m_pHead = NULL;
}
//This is the destructor for the class.
//It clears the list.
Book_Inventory::~Book_Inventory()
{
ClearList();
}
//The function ClearList removes each book from the list.
void Book_Inventory::ClearList()
{
BookRecord *temp;
if(m_pHead != NULL)//Checks to make sure the list
isn't empty.
{
temp = m_pHead;
while(m_pHead != NULL)//Goes
through the list until it ends.
{
temp =
m_pHead;
m_pHead = m_pHead->getNext();//Sets the head to the next
node.
delete
temp;//Removes the node.
}
}
}
//This function reads the file and sets each line to their
appropriate value.
//Except for the nested for loop, this function was taken from the
code reuse library.
bool Book_Inventory::readInventory(char *filename)
{
char line[128];
int numBooks;
// define other variables here as needed
m_InFile.open(filename, ifstream::in);
if(!m_InFile.is_open())
{
// m_InFile.is_open() returns false if the file could not be found
or
// if for some other reason the open failed.
cout << "Unable to open file" << filename <<
"\nProgram terminating...\n";
return false;
}
// Read number of books
getNextLine(line, 128);
numBooks = atoi(line);
for(int i=0; i<numBooks; i++)
{
//The first loop creates a new
Book Record for each book in the file.
//The nested for loop to reach
the five lines that create a Book Record.
//The if statements sort out
each line and set them to their appropriate values.
//When the last line is
reached, the book is added to the list.
BookRecord *Book = new
BookRecord();
for(int j=0; j<=4;
j++)
{
getNextLine(line, 128);
if(j
== 0)
{
Book->setStockNum(atol(line));
}
else
if(j == 1)
{
Book->setName(line);
}
else
if(j == 2)
{
Book->setClassification(atoi(line));
}
else
if(j == 3)
{
Book->setCost(atof(line));
}
else
if(j == 4)
{
Book->setNumberInStock(atoi(line));
addBook(Book);
}
}
}
return true;
}
//The addBook function adds a Book Record to the end of the
list.
bool Book_Inventory::addBook(BookRecord *br)
{
BookRecord *temp, *back, *newNode = br;
long key = newNode->getStockNum();
newNode->setNext(NULL);
if(newNode == NULL)
return false;
//If the head of the list is empty, the head is set to
the book.
if(m_pHead == NULL)
{
m_pHead = newNode;
}
else //If head exists, the function searches for the
end of the list and attaches the book there.
{
temp = m_pHead;
back = NULL;
while((temp != NULL)
&& (temp->getStockNum() < key))
{
back =
temp;
temp =
temp->getNext();
}
if(back == NULL)
{
newNode->setNext(m_pHead);
m_pHead = newNode;
}
else
{
back->setNext(newNode);
newNode->setNext(temp);
}
}
return true;
}
//The function removeBook searches for the stock number
//of a Book Record and removes that book from the list.
bool Book_Inventory::removeBook(long stockNum)
{
BookRecord *temp, *back;
if(m_pHead == NULL)
return false;
temp = m_pHead;
back = NULL;
while((temp != NULL) && (stockNum !=
temp->getStockNum()))//The function moves down the list
{
//until it find the right stock number or reaches the end.
back = temp;
temp =
temp->getNext();
}
//If the list has reached the end and no book is
found, a message is printed.
if(temp == NULL)
{
cout<<"Book Not
Found.\n";
return false;
}
else if(back == NULL)//If the book is at the
head,
{
// head points to the next node and the book is removed.
m_pHead =
m_pHead->getNext();
delete temp;
}
else//If the book is not at the head,
{ // the node before the target is set to
the node after the target.
back->setNext(temp->getNext());
delete temp;//The target is
deleted.
}
return true;
}
//The function searchByStockNumber searches the list for
books
//with the given stock number and prints their information.
BookRecord* Book_Inventory::searchByStockNumber(long
stockNum)
{
BookRecord *temp;
bool isFound = false;
temp = m_pHead;
//The function searches the list until it reaches the
end.
while(temp != NULL)
{
if(stockNum ==
temp->getStockNum())//The book information is printed if it's
found.
{
return
temp;
}
temp =
temp->getNext();
}
if(isFound == false)//If the target is not found, a
message is printed.
{
cout<<"Item not found."<<endl;
return
NULL;
}
}
//The function searchByClassification searches
//for a book by the given classification number
//and prints the information.
void Book_Inventory::searchByClassification(int cl)
{
BookRecord *temp;
int tempCL;//Since BookRecord::getClassification() is
a
//pass
by reference function, tempCL is used to
//obtain the classification number of the book.
temp = m_pHead;
temp->getClassification(tempCL);
//This for loop searches the list until it
ends.
for( ; temp !=NULL; temp=temp->getNext())
{
temp->getClassification(tempCL);
if(tempCL == cl) //If the
classification numbers match,
temp->printRecord();//the information is printed.
}
}
//The function searchByCost searches
//for each book that falls within the given
//price range.
void Book_Inventory::searchByCost(double min, double max)
{
BookRecord *temp;
temp = m_pHead;
while((temp != NULL))//The list is searched until
it ends.
{
//Checks to see if the if the
cost of the book falls between min and max.
if((temp->getCost() >=
min) && (temp->getCost() <= max))
{
temp->printRecord();//If it
does, the information is printed.
}
temp =
temp->getNext();
}
}
//The function getNumberInStock searches
//for a specific book by its stock number.
//If the book is found, its information is printed.
long Book_Inventory::getNumberInStock(long sn)
{
BookRecord *temp;
temp = m_pHead;
//The function searches the list until it ends or
the matching stock number is found.
while((temp != NULL) && (sn !=
temp->getStockNum()))
{
temp =
temp->getNext();
}
if(temp == NULL)//If the match isn't found, a message
is printed.
{
cout<<"Item not
found."<<endl;
}
else//If there is a match, the number in stock is
printed.
{
cout<<temp->getNumberInStock()<<"\n";
}
return 0;
}
//The function printAll goes through
//the list and prints off each book Record.
void Book_Inventory::printAll()
{
BookRecord *temp;
temp = m_pHead;
while(temp != NULL)//The while loop runs through the
list until it ends.
{
temp->printRecord();
temp =
temp->getNext();
}
}
//This function is nessessary to get each line in the
file.
//It was taken from the code reuse library.
bool Book_Inventory::getNextLine(char *line, size_t lineLen)
{
int done = false;
while(!done)
{
m_InFile.getline(line, lineLen);
if(m_InFile.good()) // If a line was successfully read
{
if(strlen(line) == 0) // Skip any blank lines
continue;
else if(line[0] == '#') // Skip any comment lines
continue;
else return true; // Got a valid data line so return with this
line
}
else // No valid line read, meaning we reached the end of
file
{
strcpy(line, ""); // Copy empty string into line as sentinal
value
return false;
}
} // end while
return false; // Cannot reach this point but include a return to
avoid compiler warning
// that not all paths return a value.
}
Book_Inventory.h:
#ifndef BOOK_INVENTORY_H
#define BOOK_INVENTORY_H
#include<iostream> // This header lets you use cout and
cin
#include<fstream> // This header gives you all the file I/O
functions
#include<string.h>
#include<stdlib.h>
#include "BookRecord.h"
using namespace std; // This command lets you use all the I/O function and include headers w/o the ".h"
class Book_Inventory
{
private:
BookRecord *m_pHead; // Pointer to the head of the list
ifstream m_InFile; // File containing the inventory
public:
Book_Inventory(); // Class constructor
~Book_Inventory(); // Class destructor. Must free all list
memory
void ClearList(); // Remove all items from the list
bool readInventory(char *filename); // Read inventory file and
build the list
bool addBook(BookRecord *br); // Add the given book to the
list
bool removeBook(long stockNum); // Remove a book from the list or
print message if not found
BookRecord* searchByStockNumber(long stockNum);// Search by stock
number, print all data or message if not found
void searchByClassification(int cl); // Search for all books given
classification, print all data
void searchByCost(double min, double max);// Search for all books
within the given cost range
long getNumberInStock(long sn); // Get number of books in stock for
the given stock number
void printAll(); // Print all information on all books in the
inventory.
private:
bool getNextLine(char *line, size_t lineLen); // read next line
from a file
};
#endif
Sample Output Screenshot:-
-----------------------------------------------------