(Edited version)
I am currently coding Binary Search Tree algorithm. (using xCode IDE)
I'm taking the data from txt file and insert it as binarysearchtree.
This is the sample of data from txt file.
3800 Lee, Victor; 2.8
3000 Brown, Joanne; 4.0
As you can see in student.h, there are 2 variables which are id and student. Id contains the data "3800" and student contains "Lee, Victor; 2.8". Each line of the txt consider as one root.
Now, I have to search by a unique key which is id(Ex. "3800") and print out if it is found in the tree.
I have 5 files, BinaryNode.h, BinaryTree.h, BinarySearchTree.h, Student.h, main.cpp.
All 3 of the binary header file are using template and Student.h has no template.
So, here is my int main.
int main()
{
BinarySearchTree<Student> tree;
getData(tree); (I didn't include getData part, but consider tree has txtfile data.)
bool found = false;
char input;
do
{
cout << "Enter a key letter to access to a corresponding menu." << endl << endl;
cout << "T – Print tree as an indented list" << endl;
cout << "S – Search by a unique key (student ID)" << endl;
cout << "B – Tree Breadth-First Traversal: Print by level" << endl;
cout << "D – Depth-First Traversals: inorder, preorder, postorder" << endl;
cout << "R – Find the longest branch and print it (from leaf to root)" << endl;
cout << "H – Help" << endl;
cout << "Q – Quit" << endl << endl;
cout << "Input: ";
cin >> input;
cout << endl;
if(input == 'T' || input == 'S' || input == 'B' || input == 'D' || input == 'R' || input == 'H' || input == 'Q' || input == 'A')
{
if(input == 'T')
{
//print tree as indented
}
else if(input == 'S')
{
//search by student ID
Student *result = new Student;
int id;
cout << "Enter the student ID to search the matching student." << endl;
cin >> id;
result->setId(id);
found = tree.getEntry(*result);
}
I cin the input data into result and tried to search for the data.
//My getEntry function in public function definition
template<class ItemType>
bool BinarySearchTree<ItemType>::getEntry(ItemType& anEntry)
{
BinaryNode<ItemType>* returnedItem = findNode(BinaryTree<ItemType>::rootPtr, anEntry);
if (returnedItem)
{
anEntry = returnedItem->getItem();
return true;
}
else return false;
}
//findNode function
template<class ItemType>
BinaryNode<ItemType>*
BinarySearchTree<ItemType>::findNode(BinaryNode<ItemType>* nodePtr,
ItemType & target)
{
ItemType result = result.getId(); <------- ******error here*******
ItemType root = nodePtr->getItem().getId();
if (nodePtr == nullptr)
return nullptr;
if (result == root)
return root;
if (result > root)
root = findNode(nodePtr->getRightPtr(), target);
else
root = findNode(nodePtr->getLeftPtr(), target);
return root;
}
I have an error on my findNode function.
->No viable conversion from 'int' to 'Student'
//Student.h
class Student
{
private:
int id;
std::string name;
public:
Student() { id = 0; name = ""; }
Student(int newId, std::string newName) { id = newId; name = newName; }
friend bool operator >= (const Student l, const Student& r)
{
return std::tie(l.id, l.name) < std::tie(r.id, r.name);
}
friend bool operator == (const Student l, const Student& r)
{
return std::tie(l.id, l.name) < std::tie(r.id, r.name);
}
friend bool operator < (const Student l, const Student& r)
{
return std::tie(l.id, l.name) < std::tie(r.id, r.name);
}
friend bool operator > (const Student l, const Student& r)
{
return std::tie(l.id, l.name) < std::tie(r.id, r.name);
}
/*
Student& operator = (Student& t_id)
{
if(this != &t_id)
id = t_id.getId();
return *this;
}
*/
void getStudent() { std::cin >> id; }
int getId() const { return id; }
void setId(int t_id) { id = t_id; }
std::string getName() const { return name; }
void setName(std::string t_name) { name = t_name; }
//ItemType getGpa() const { return gpa; }
//virtual void setGpa(std::string t_gpa) { gpa = t_gpa; }
Do I need = operator to fix that problem?
Actually, I created the = operator but if I enable that = operator code,
the other codes with equal sign that are in other functions
encounter errors. (no viable overloaded '=')
How can I fix this errors?
Thank you for your helping.
Just see this line.
ItemType root = nodePtr->getItem().getId();
Do you feel that something is wrong here?
Related
So I have a linked list of a class, and I am trying to delete one of the nodes, but when it reaches that line of code, the program freezes and crashes.
Here is the linked list classes I am using:
template <class Type>
struct nodeType {
Type info;
nodeType<Type>* link;
};
template <class Type>
class linkedListIterator {
public:
linkedListIterator();
linkedListIterator(nodeType<Type>* ptr);
Type operator*();
linkedListIterator<Type> operator++();
bool operator==(const linkedListIterator<Type>& right) const;
bool operator!=(const linkedListIterator<Type>& right) const;
private:
nodeType<Type>* current;
};
template <class Type>
class linkedListType {
public:
const linkedListType<Type>& operator=(const linkedListType<Type>&);
void initializeList();
bool isEmptyList() const;
void print() const;
int length() const;
void destroyList();
Type front() const;
Type back() const;
virtual bool search(const Type& searchItem) const = 0;
virtual void insertFirst(const Type& newItem) = 0;
virtual void insertLast(const Type& newItem) = 0;
virtual void deleteNode(const Type& deleteItem) = 0;
linkedListIterator<Type> begin();
linkedListIterator<Type> end();
linkedListType();
linkedListType(const linkedListType<Type>& otherList);
~linkedListType();
protected:
int count;
nodeType<Type>* first;
nodeType<Type>* last;
private:
void copyList(const linkedListType<Type>& otherList);
};
template <class Type>
class orderedLinkedList : public linkedListType<Type> {
using linkedListType<Type>::first;
using linkedListType<Type>::last;
using linkedListType<Type>::count;
public:
bool search(const Type& searchItem) const;
void insert(const Type& newItem);
void insertFirst(const Type& newItem);
void insertLast(const Type& newItem);
void deleteNode(const Type& deleteItem);
};
This is the function I am calling to delete the node:
template <class Type>
void orderedLinkedList<Type>::deleteNode(const Type& deleteItem)
{
nodeType<Type>* current; //pointer to traverse the list
nodeType<Type>* trailCurrent; //pointer just before current
bool found;
if (first == nullptr) //Case 1
cout << "Cannot delete from an empty list." << endl;
else
{
current = first;
found = false;
while (current != nullptr && !found) //search the list
if (current->info >= deleteItem)
found = true;
else
{
trailCurrent = current;
current = current->link;
}
if (current == nullptr) //Case 4
cout << "The item to be deleted is not in the "
<< "list." << endl;
else
if (current->info == deleteItem) //the item to be
//deleted is in the list
{
if (first == current) //Case 2
{
first = first->link;
if (first == nullptr)
last = nullptr;
delete current;
}
else //Case 3
{
trailCurrent->link = current->link;
if (current == last)
last = trailCurrent;
delete current;
}
count--;
}
else //Case 4
cout << "The item to be deleted is not in the "
<< "list." << endl;
}
}//end deleteNode
And here is where I call the deleteNode function:
void deleteBook(orderedLinkedList<bookType> books)
{
char choice = '\0';
char ans = '\0';
string title = "Delete Book";
int len = title.length();
int bookCount = bookType::getBookCount();
do {
system("cls");
cout << setfill(' ');
cout << setw((SIZE_MENUS / 2) + LEN_TITLE / 2) << right << TITLE << endl;
cout << setw((SIZE_MENUS / 2) + len / 2) << right << title << endl;
cout << endl;
cout << setw(SIZE_MENUS / 3) << "" << "Current Book Count: " << bookCount << endl;
cout << endl;
linkedListIterator<bookType> current = lookUpBook(books);
if (current != nullptr)
{
cout << setfill(' ');
cout << setw(SIZE_MENUS / 4) << "" << "Is this the book you would like to delete? (Y/N): ";
cin >> ans;
cin.ignore(100, '\n');
cout << endl;
while (ans != 'Y' && ans != 'y' && ans != 'N' && ans != 'n')
{
cout << setw(SIZE_MENUS / 4) << "" << "Please enter Y or N." << endl;
cout << setw(SIZE_MENUS / 4) << "" << "Is this the book you would like to delete? (Y/N): ";
cin >> ans;
cin.ignore(100, '\n');
cout << endl;
}
if (ans == 'Y' || ans == 'y')
{
cout << "found" << endl;
books.deleteNode(*current);
bookType::decBookCount();
bookCount = bookType::getBookCount();
cout << setw(SIZE_MENUS / 4) << "" << "Book Deleted." << endl;
cout << setw(SIZE_MENUS / 4) << "";
system("pause");
cout << endl;
cout << setw(SIZE_MENUS / 4) << "" << "Would you like to delete another book? (Y/N): ";
cin >> ans;
cin.ignore(100, '\n');
cout << endl;
if (ans == 'Y' || ans == 'y')
{
cout << endl;
}
if (ans == 'N' || ans == 'n')
{
break;
}
else {
cout << setw(SIZE_MENUS / 3) << "" << "Please enter Y or N." << endl;
cout << setw(SIZE_MENUS / 3) << "" << "Would you like to delete another book? (Y/N): ";
cin >> ans;
cin.ignore(100, '\n');
cout << endl;
}
}
else {
break;
}
}
else {
break;
}
} while (choice != 'n' && choice != 'N');
}
So in my deleteBook function, I search for a book in the lookUpBook function (not shows as it seems to be working perfectly), and it returns a linkedListIterator, which I store into current. I then allow the user to choose whether or not to delete the book. If they say 'Y' or 'y' for yes, it prints out a "found" statement (seen in deleteBook as a check to see if it enters the print statement), and then the program crashes.
I am having trouble figuring out how to get my input data into my queue... I am so close to getting this to work right.
I know I am just confused about how things are working. I have used example code and my instructions to come up with a working program that appears to be working correctly (other than not actually putting my input file data into the queue). I bypassed the function I was trying to make for this. In addition to this, I was trying to write a function to remove an employee from the queue (which I think does work), but I am not sure I was able to get it right...
I have not taken a programming class for over 10 years and really would love to get any help in understanding what I am doing and getting that darn data into the queue.
Below is my main driver file. I will provide my header file code if needed. Thanks in advance for any help you can provide on this.
//Program Assignment #3
//Creates Queue as a Linked Structure
#include<iostream>
#include<string>
#include<fstream>
#include"Employee.h"
#include"LinkedQ.h"
using namespace std;
struct Node
{
LinkedQ nodeQ;
Employee EmpNumber;
Employee LastName;
Employee FirstName;
Employee ServiceYears;
};
void loadFile(LinkedQ &);
void addEmp(LinkedQ &);
void delEmp(LinkedQ &);
int main()
{
LinkedQ empList;
int choice;
int numIn, yearsIn;
string LastName;
string FirstName;
LinkedQ empIn;
ifstream input;
input.open("Employee.txt");
while (input)
{
input >> numIn >> LastName >> FirstName >> yearsIn;
if (input)
{
cout << "this is where we load data from the file into the queue\n";
system("pause");
//empIn.Enqueue(numIn, LastName, FirstName, yearsIn);
//empList.addEmp(empIn);
}
}
input.close();
do
{
//display menu
system("cls");
cout << "\t\tMenu: \n"
<< "\t1. Add Employee\n"
<< "\t2. Remove Employee\n"
<< "\t3. Count of Employees\n"
<< "\t4. Quit\n\n";
cout << "Enter your choice and press return: ";
cin >> choice;
switch (choice)
{
case 1:
addEmp(empList); // call to function to add an employee to the queue
break;
case 2:
delEmp(empList); // call to fucntion to remove an employee from the queue
break;
case 3:
cout << endl << "Count of Employees: "
<< empList.GetLength() << endl; // See how many employees are in the queue
system("pause");
break;
case 4:
cout << "End of Program"; // End Program
break;
default:
cout << "Not a valid choice!" << endl;
cout << "Choose Again."; // Handling incorrect inputs
system("pause");
break;
}
} while (choice != 4); // If choice is not 4, continue running program
return 0;
}
//***********************************
//Loads the file (having trouble figuring out how to implement this part)
//***********************************
void loadFile(Employee &empList)
{
int numIn, yearsIn;
string LastName;
string FirstName;
LinkedQ empIn;
ifstream input;
input.open("Employee.txt");
while (input)
{
input >> numIn >> LastName >> FirstName >> yearsIn;
if (input)
{
cout << "this is where we load data from the file into the queue";
//empIn.setFields(numIn, LastName, FirstName, yearsIn);
//empList.addEmp(empIn);
}
}
input.close();
}
//***************************************
//add an employee
//***************************************
void addEmp(LinkedQ &empList)
{
Employee newEmp;
newEmp.user();
empList.Enqueue(newEmp);
}
//****************************************
//remove a employee
//****************************************
void delEmp(LinkedQ &empList)
{
Employee EmpToRemove;
int empNum;
// bool successful;
cout << "Please enter EMPLOYEE NUMBER of employee to remove:";
cin >> empNum;
EmpToRemove.setEmpNumber(empNum);
empList.Dequeue(EmpToRemove);
//successful = empList.Dequeue(EmpToRemove);
//if (successful == true)
//{
cout << "Removed" << endl << endl;
system("pause");
//}
//else
//{
// cout << "Emp Not found" << endl << endl;
//}
}
Here is the LinkedQ implementation file:
//LinkedQ class
#include "LinkedQ.h"
#include <cstddef>
#include <new>
struct NodeType
{
Employee info;
NodeType* next;
};
LinkedQ::LinkedQ(void)
{
newNode = nullptr;
front = NULL;
rear = NULL;
length = 0;
}
void LinkedQ::MakeEmpty()
{
NodeType* tempPtr;
while (front != NULL)
{
tempPtr = front;
front = front->next;
delete tempPtr;
}
rear = NULL;
}
LinkedQ::~LinkedQ(void)
{
MakeEmpty();
}
bool LinkedQ::IsFull() const
{
NodeType* location;
try
{
location = new NodeType;
delete location;
return false;
}
catch (std::bad_alloc exception)
{
return true;
}
}
bool LinkedQ::IsEmpty() const
{
return (front == NULL);
}
void LinkedQ::Enqueue(Employee newItem)
{
if (IsFull())
cout << "Queue is Full";
// throw FullQueue();
else
{
NodeType* newNode;
newNode = new NodeType;
newNode->info = newItem;
newNode->next = NULL;
if (rear == NULL)
{
front = newNode;
}
else
{
rear->next = newNode;
}
rear = newNode;
length++;
}
}
void LinkedQ::Dequeue(Employee& item)
{
if (IsEmpty())
{
//throw EmptyQueue();
cout << "Queue is empty";
}
else
{
NodeType* tempPtr;
tempPtr = front;
item = front->info;
front = front->next;
if (front == NULL)
{
rear = NULL;
}
delete tempPtr;
length--;
}
}
int LinkedQ::GetLength() const
{
return length;
}
And here is the Employee implementation file:
//employee Class
#include"Employee.h"
//Constructor
Employee::Employee()
{
EmpNum = 0;
}
//setters
void Employee::setEmpNumber(int eNum)
{
EmpNum = eNum;
}
void Employee::setEmpName(string LName)
{
LastName = LName;
}
void Employee::setEmpFirstName(string FName)
{
FirstName = FName;
}
void Employee::setYearsService(int years)
{
YearsService = years;
}
void Employee::setFields(int num, string LN, string FN, int years)
{
EmpNum = num;
LastName = LN;
FirstName = FN;
YearsService = years;
}
void Employee::user()
{
string inputString;
int intNumber;
cout << "Employee Number ";
cin >> intNumber;
while (intNumber <= 0)
{
cout << "Employee Number ";
cin >> intNumber;
}
EmpNum = intNumber;
cout << "Last Name: ";
cin >> inputString;
LastName = inputString;
cout << "First Name: ";
cin >> inputString;
FirstName = inputString;
cout << "Years of Service: ";
cin >> intNumber;
while (intNumber < 0)
{
cout << "Years of Service ";
cin >> intNumber;
}
cout << endl;
YearsService = intNumber;
}
//getters
const int Employee::getEmpNumber()
{
return EmpNum;
}
const string Employee::getLastName()
{
return LastName;
}
const string Employee::getFirstName()
{
return FirstName;
}
const int Employee::getYearsService()
{
return YearsService;
}
//overloads
bool Employee::operator == (const Employee &right)
{
bool status;
if ( EmpNum == right.EmpNum)
status = true;
else
status = false;
return status;
}
bool Employee::operator != (const Employee &right)
{
bool status;
if (EmpNum != right.EmpNum)
status = true;
else
status = false;
return status;
}
I think the parameter of loadFile should be of type LinkedQ, which, if I understand it correctly, is the queue class/struct, and the empIn variable should be of type Employee.
Edit:
The method you call on the empList object should be Enqueue, instead of addEmp.
Okay, I've been battling this for awhile and I don't understand what I need to do. This is my LinkedList header.
// Non templated version
#pragma once
#ifndef __LINKEDLIST_H__
#define __LINKEDLIST_H__
// Get access to size_t definitions
#include <cstddef>
using std::size_t;
// A type alias for the stored type. Changing this changes what is stored
typedef int ItemType;
// Nodes for a linked list in C++
class Node
{
// A friend declaration allows LinkedList class to access the Node's private data
friend class LinkedList;
public:
Node(const ItemType& data, Node* next = nullptr);
private:
ItemType _data;
Node* _next;
};
// An linked list for C++
class LinkedList
{
public:
LinkedList();
LinkedList(const LinkedList&);
~LinkedList();
LinkedList& operator=(const LinkedList&);
ItemType pop_front();
ItemType& front();
void push_front(const ItemType& value);
void insert(size_t index, ItemType& data); // Replace these w/ iterators
void remove(size_t index);
size_t getSize() const;
private:
// Helper methods
void copy(const LinkedList &src);
void dealloc();
Node* find(size_t index) const;
// data
size_t _size;
Node *_head;
};
void LinkedList::insert(size_t index, Dweller &data){
Node* temp = this->_head;
while (temp->_next != NULL){
temp = temp->_next;
}
Node newNode = Node(data);
temp->_next = &newNode;
}
#endif
And this is my vault.h file:
#include <string>
#include <vector>
#include "linked_list.h"
using namespace std;
class Dweller{
public:
Dweller(const string& name, int& strength, int& agility, int& perception);
int getStrength();
int getAgility();
int getPerception();
string getName();
private:
string name;
int strength;
int agility;
int perception;
};
Dweller::Dweller(const string& name, int& strength, int& agility, int& perception){
if ((strength > 10) || (strength < 1)){
cout << "Invalid number." << endl;
}
if ((agility > 10) || (strength < 1)){
cout << "Invalid number." << endl;
}
if ((perception > 10) || (perception < 1)){
cout << "Invalid number." << endl;
}
this->name = name;
this->strength = strength;
this->agility = agility;
this->perception = perception;
}
int Dweller::getStrength(){
return this->strength;
}
int Dweller::getAgility(){
return this->agility;
}
int Dweller::getPerception(){
return this->perception;
}
string Dweller::getName(){
return this->name;
}
class Room{
public:
Room(const string& name, const string& statistic);
void print();
void add(Dweller&);
private:
string name;
string statistic;
LinkedList dwellers = LinkedList();
};
Room::Room(const string& name, const string& statistic){
this->name = name;
this->statistic = statistic;
}
void Room::add(Dweller& person){
dwellers.insert(0, person);
}
And the driver.cpp file that I can't edit. This is an assignment.
// driver.cpp
// Testing driver for Assignment 2
#include <iostream>
#include <locale>
#include <string>
#include "vault.h"
using std::cin;
using std::getline;
using std::cout;
using std::endl;
using std::string;
using std::locale;
using std::tolower;
int main()
{
std::locale loc;
// We create three rooms: Power Generator (Strength), Water Processing (Perception),
// and Diner (Agility)
Room power("Power Generator", "Strength");
Room water("Water Processing", "Perception");
Room diner("Diner", "Agility");
string prompt;
do
{
string charName;
cout << "What is the Dweller's name? ";
getline(cin, charName);
int str = 0, per = 0, agl = 0;
char room;
do
{
cout << "What is the character's Strength [1-10]? ";
cin >> str;
}
while(str <= 0 || str > 10);
do
{
cout << "What is the character's Perception [1-10]? ";
cin >> per;
}
while(per <= 0 || per > 10);
do
{
cout << "What is the character's Agility [1-10]? ";
cin >> agl;
}
while(agl <= 0 || agl > 10);
do
{
cout << "Which room [(P)ower, (W)ater, (D)iner]? ";
cin >> room;
room = tolower(room, loc);
}
while(room != 'p' && room != 'w' && room != 'd');
if(room == 'p')
power.add(Dweller(charName, str, per, agl));
else if(room == 'w')
water.add(Dweller(charName, str, per, agl));
else
diner.add(Dweller(charName, str, per, agl));
cout << "Are there more Dwellers [Y/N]? " << endl;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Flush newlines
getline(cin, prompt);
}
while(tolower(prompt[0], loc) == 'y');
power.print();
water.print();
diner.print();
}
The problem I'm having is that I keep getting that I cannot convert from const Dweller to const ItemType.
What I'm trying to do is add a Dweller object to a linkedlist.
Is there a reason for the LinkList class? If not why not do something like this instead? Vector has pretty much everything you need on that. Some other advice is don't use std::endl unless you need to do a flush. instead use \n.
// Get access to size_t definitions
#include <vector>
#include <iostream>
#include <locale>
#include <string>
class Dweller{
public:
Dweller(const std::string name, int strength, int agility, int perception);
int getStrength();
int getAgility();
int getPerception();
std::string getName();
private:
std::string name_;
int strength_;
int agility_;
int perception_;
};
Dweller::Dweller(const std::string name, int strength, int agility, int perception) :
name_{name},
strength_{strength},
agility_{agility},
perception_{perception}
{
if (strength > 10 || strength < 1) {
std::cout << "Invalid number.\n";
}
if ((agility > 10) || (strength < 1)){
std::cout << "Invalid number.\n";
}
if ((perception > 10) || (perception < 1)){
std::cout << "Invalid number.\n";
}
}
int Dweller::getStrength(){
return strength_;
}
int Dweller::getAgility(){
return agility_;
}
int Dweller::getPerception(){
return perception_;
}
std::string Dweller::getName(){
return name_;
}
class Room{
public:
Room(const std::string name, const std::string statistic);
void print();
void add(Dweller&);
private:
std::string name_;
std::string statistic_;
std::vector<Dweller> dwellers_;
};
Room::Room(const std::string name, const std::string statistic) :
name_{name},
statistic_{statistic}
{}
void Room::print()
{
for (auto& iter : dwellers_) {
std::cout << "\nName: " << iter.getName()
<< "\nStrength: " << iter.getStrength()
<< "\nAgility: " << iter.getAgility()
<< "\nPerception: " << iter.getPerception();
}
}
void Room::add(Dweller& person)
{
dwellers_.push_back(person);
}
int main()
{
std::locale loc;
// We create three rooms: Power Generator (Strength), Water Processing (Perception),
// and Diner (Agility)
Room power("Power Generator", "Strength");
Room water("Water Processing", "Perception");
Room diner("Diner", "Agility");
std::string prompt;
do
{
std::string charName;
std::cout << "What is the Dweller's name? ";
std::getline(std::cin, charName);
int str = 0, per = 0, agl = 0;
char room;
do
{
std::cout << "What is the character's Strength [1-10]? ";
std::cin >> str;
} while (str <= 0 || str > 10);
do
{
std::cout << "What is the character's Perception [1-10]? ";
std::cin >> per;
} while (per <= 0 || per > 10);
do
{
std::cout << "What is the character's Agility [1-10]? ";
std::cin >> agl;
} while (agl <= 0 || agl > 10);
do
{
std::cout << "Which room [(P)ower, (W)ater, (D)iner]? ";
std::cin >> room;
room = tolower(room, loc);
} while (room != 'p' && room != 'w' && room != 'd');
if (room == 'p')
power.add(Dweller(charName, str, per, agl));
else if (room == 'w')
water.add(Dweller(charName, str, per, agl));
else
diner.add(Dweller(charName, str, per, agl));
std::cout << "Are there more Dwellers [Y/N]? \n";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Flush newlines
std::getline(std::cin, prompt);
} while (tolower(prompt[0], loc) == 'y');
power.print();
water.print();
diner.print();
std::cout << '\n';
system("PAUSE");
}
Start by making it possible to do what you want. Change the definition of Node to be templated
template <class ItemType>
class Node
{
//node, but with a few tweaks to replace the typedef of ItemType with the templating
}
Ditto with LinkedList
template <class ItemType>
class LinkedList
{
//lots of tweaks to replace node with templated node
...
Node<ItemType> *_head;
};
Then when you need to make the list:
LinkedList<Dweller> dwellers;
For a school programming assignment I built an application that stores a list of objects in a sequential list object. The sequential list class has a method to insert a new object into the list, it checks first to see if the list already has the maximum number of entries allowed and if it does returns an error. For some reason I'm unable to insert a new object into the list (I keep getting the "Max list size exceeded" error) even though there aren't any entries in it to start.
I ran it with a breakpoint to see if the size data member was increasing somehow but that doesn't seem to be the case here.
Please ignore the poor code quality, still just learning... Feel free to make any recommendations :)
Here's the main program:
#include<iostream>
#include<string>
#include "aseqlist.h"
using namespace std;
void PrintByGender (const SeqList& L, char gender)
{
int size = L.ListSize();
int count = 0;
while (count < size)
{
if (gender == L.GetData(count).getGender())
{
L.GetData(count).PrintEmployee();
}
count++;
}
}
int InList (const SeqList& L, char *lname, Employee& Emp)
{
int found = 0;
Emp.setLast(lname);
if (L.Find(Emp) == 1)
{
found = 1;
Emp.PrintEmployee();
}
return found;
}
int main()
{
SeqList obj1;
bool close = false;
string choice = "";
do
{
cout << "Please choose what you would like to do: " << "\n";
cout << "N = New record, D = Delete record, P = Print by gender, S = Search and E = Exit" << "\n";
cin >> choice;
cin.ignore();
if (choice == "n" || choice == "N")
{
string first, last;
int age;
char gen;
double empNum;
cout << "First name: ";
cin >> first;
cout << "Last name: ";
cin >> last;
cout << "Age: ";
cin >> age;
cout << "Gender ('M' Or 'F'): ";
cin >> gen;
cout << "Employee Number: ";
cin >> empNum;
Employee newEmp;
newEmp.ReadEmployee(first, last, age, gen, empNum);
obj1.Insert(newEmp);
}
if (choice == "e" || choice == "E")
{
close = true;
}
if (choice == "p" || choice == "P")
{
char genderSearch;
cout << "Male = M, Female = F";
cin >> genderSearch;
cin.ignore();
PrintByGender(obj1, genderSearch);
}
if (choice == "d" || choice == "D")
{
string last;
cout << "Which employee? (Enter Last Name): ";
cin >> last;
cin.ignore();
Employee emp;
emp.setLast(last);
obj1.Delete(emp);
cout << "Deleted";
}
if (choice == "s" || choice == "S")
{
char lnameSearch;
cout << "Last Name?: ";
cin >> lnameSearch;
cin.ignore();
Employee emp;
char *ptrSearch;
ptrSearch = &lnameSearch;
InList(obj1, ptrSearch, emp);
if (emp.getFirst() != "")
{
emp.PrintEmployee();
}
}
}
while (close != true);
};
And here's the header file for the class declarations:
#include <iostream>
using namespace std;
const int MaxListSize = 6;
// You will need to change the typedef in the following line
// from the data type int to Employee
class Employee
{
public:
Employee();
Employee(string firstName, string lastName, int age, char gender, double employeeNumber);
void ReadEmployee(string firstName, string lastName, int age, char gender, double employeeNumber);
char getGender();
string getFirst();
void Employee::setLast(string lname);
string getLast();
void PrintEmployee();
private:
string LastName;
string FirstName;
int Age;
char Gender;
double EmployeeNumber;
};
typedef Employee DataType;
class SeqList
{
private:
// list storage array and number of current list elements
DataType listitem[MaxListSize];
int size;
public:
// constructor
SeqList(void);
// list access methods
int ListSize(void) const;
int ListEmpty(void) const;
int Find (DataType& item) const;
DataType GetData(int pos) const;
// list modification methods
void Insert(const DataType& item);
void Delete(const DataType& item);
DataType DeleteFront(void);
void ClearList(void);
};
// Class Definition:
// constructor. set size to 0
SeqList::SeqList (void): size(6)
{}
// return number of elements in list
int SeqList::ListSize(void) const
{
return size;
}
// tests for an empty list
int SeqList::ListEmpty(void) const
{
return size == 0;
}
// clears list by setting size to 0
void SeqList::ClearList(void)
{
size = 0;
}
// Take item as key and search the list. return True if item
// is in the list and False otherwise. if found,
// assign the list element to the reference parameter item
bool operator==(Employee A, Employee B)
{
bool isequal = false;
if (A.getLast() == B.getLast())
isequal = true;
return isequal;
}
int SeqList::Find(DataType& item) const
{
int i = 0;
if (ListEmpty())
return 0; // return False when list empty
while (i < size && !(item == listitem[i]))
i++;
if (i < size)
{
item = listitem[i]; // assign list element to item
return 1; // return True
}
else
return 0; // return False
}
// insert item at the rear of the list. terminate the program
// if the list size would exceed MaxListSize.
void SeqList::Insert(const DataType& item)
{
// will an insertion exceed maximum list size allowed?
if (size+1 > MaxListSize)
{
cout << "Maximum list size exceeded" << endl;
exit(1);
}
// index of rear is current value of size. insert at rear
listitem[size] = item;
size++; // increment list size
}
// search for item in the list and delete it if found
void SeqList::Delete(const DataType& item)
{
int i = 0;
// search for item
while (i < size && !(item == listitem[i]))
i++;
if (i < size) // successful if i < size
{
// shift the tail of the list to the left one position
while (i < size-1)
{
listitem[i] = listitem[i+1];
i++;
}
size--; // decrement size
}
}
// delete element at front of list and return its value.
// terminate the program with an error message if the list is empty.
DataType SeqList::DeleteFront(void)
{
DataType frontItem;
// list is empty if size == 0
if (size == 0)
{
cout << "Attempt to delete the front of an empty list!" << endl;
exit(1);
}
frontItem = listitem[0]; // get value from position 0.
Delete(frontItem); // delete the first item and shift terms
return frontItem; // return the original value
}
// return value at position pos in list. if pos is not valid
// list position, teminate program with an error message.
DataType SeqList::GetData(int pos) const
{
// terminate program if pos out of range
if (pos < 0 || pos >= size)
{
cout << "pos is out of range!" << endl;
exit(1);
}
return listitem[pos];
}
Employee::Employee()
{
FirstName = "";
LastName = "";
Age = 0;
/*Gender = "";*/
EmployeeNumber = 0;
};
Employee::Employee(string firstName, string lastName, int age, char gender, double employeeNumber)
{
FirstName = firstName;
LastName = lastName;
Age = age;
Gender = gender;
EmployeeNumber = employeeNumber;
};
void Employee::PrintEmployee()
{
cout << "First Name: " << FirstName << "\n";
cout << "Last Name: " << LastName << "\n";
cout << "Age: " << Age << "\n";
cout << "Gender: " << Gender << "\n";
cout << "Employee Number :" << EmployeeNumber << "\n" << "\n";
};
void Employee::ReadEmployee(string firstName, string lastName, int age, char gender, double employeeNumber)
{
FirstName = firstName;
LastName = lastName;
Age = age;
Gender = gender;
EmployeeNumber = employeeNumber;
};
char Employee::getGender()
{
return Gender;
}
string Employee::getFirst()
{
return FirstName;
}
string Employee::getLast()
{
return LastName;
}
void Employee::setLast(string lname)
{
LastName = lname;
}
Problem in the constructor:
SeqList::SeqList (void): size(6)
size is being initialized as 6.
Other suggestions. Don't put using namespace std; in a header file. Better yet, don't put using namespace std; anywhere.
Why is "using namespace std" considered bad practice?
// constructor. set size to 0
SeqList::SeqList (void): size(6)
{}
This is wrong. Should be so:
// constructor. set size to 0
SeqList::SeqList (void): size(0)
{}
I consistently run into this problem where I'm trying to validate user input but I find myself using tons of ignores() throughout my program. Since it is a school program I'm only limited to just iostream, cctype, and student.h libraries. The problem is I need to make sure the user does not try to enter alpha characters into an integer field which I thought I covered with if(!(cin >> val)) and then I use cin.ignore(numeric_limits<streamsize>::max(), '\n'); to ignore anything extra (for instance if they try to enter a decimal into an integer field). Something is not working correctly though as I am either unable to input into name field or I get the remaining decimal as the name (if I enter 123.6, the name will be .6). Does someone know a better way to validate integers than using mass ignores?
Main
#include <iostream>
using namespace std;
#include "student.h"
//**************************************************************************
bool validInt(int&);
//**************************************************************************
int main()
{
Student student;
bool validInput;
cout << "You have Chosen to Add a New Student." << endl;
cout << "---------------------------------------" << endl;
// Student ID Validation
do
{
cout << "Enter Student ID (ex. 123): ";
validInput = validInt(student.id);
}while(!validInput);
cout << "Enter Student Name (ex. John Doe): ";
cin.getline(student.name, 50);
cout << "Enter Student City and State (ex. St. Louis, Missouri): ";
cin.getline(student.citystate, 50);
cout << "\n\nStudent ID: " << student.id << endl;
cout << "Student Name: " << student.name << endl;
cout << "Student City / State: " << student.citystate << endl;
return 0;
}
//**************************************************************************
bool validInt(int& val)
{
bool valid = true;
if(!(cin >> val))
{
cout << "\nERROR: Please enter a Positive Whole Number" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
valid = false;
}
return valid;
}
Student Header
#ifndef STUDENT_H
#define STUDENT_H
//**************************************************************************
struct Student
{
int id;
char name[50];
char citystate[50];
friend ostream& operator<<(ostream& out, const Student& data);
bool operator == (const Student &rhs) const;
bool operator != (const Student &rhs) const;
bool operator < (const Student &rhs) const;
bool operator > (const Student &rhs) const;
bool operator <= (const Student &rhs) const;
bool operator >= (const Student &rhs) const;
};
//**************************************************************************
ostream& operator << (ostream& out, const Student& data)
{
out << data.id << " " << data.name << endl;
return out;
}
//**************************************************************************
bool Student::operator == (const Student &rhs) const
{
return (this->id == rhs.id);
}
//**************************************************************************
bool Student::operator != (const Student &rhs) const
{
return (this->id != rhs.id);
}
//**************************************************************************
bool Student::operator < (const Student &rhs) const
{
return (this->id < rhs.id);
}
//**************************************************************************
bool Student::operator > (const Student &rhs) const
{
return (this->id > rhs.id);
}
//**************************************************************************
bool Student::operator <= (const Student &rhs) const
{
return (this->id <= rhs.id);
}
//**************************************************************************
bool Student::operator >= (const Student &rhs) const
{
return (this->id >= rhs.id);
}
#endif
Usually you would use std::getline(std::string&,std::istream&) for line orientated input and parse the number with an istringstream. However, since you aren't allowed to use neither std::string nor std::stringstream you need to parse the integer yourself.
But first the explanation for your errors.
Explanation
Something is not working correctly though as I am either unable to input into name field
When you enter a correct integer the newline token \n is not extracted from the string, that's why cin.getline(student.name, 50); won't extract anything: the next character in std::cin is \n, the line ends and the std::getline fills student.name with the extractet line, which is empty.
or I get the remaining decimal as the name (if I enter 123.6, the name will be .6).
Again, this is the same: you only extract the integer, but you don't extract the rest of the line.
Temporary solution
Ignore the rest of the line in your validInt:
bool validInt(int& val)
{
bool valid = true;
if(!(cin >> val))
{
cout << "\nERROR: Please enter a Positive Whole Number" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
valid = false;
}
cin.ignore(numeric_limits<streamsize>::max(), '\n');
return valid;
}
Correct solution
The correct solution is a little bit more elaborate, since you would have to write something that extracts single characters, checks whether they are digits (or a minus or plus), saves those as integer and ignores the rest of the line. Don't worry, this is possible with only <iostream>