I have made an array based queue with a template so that the user can decide what kind of data is held inside the queue but I cannot figure out how gather input and then from that create a queue of that data type.
Here is my Queue
#include <memory>
using namespace std;
template<class itemType>
class Queue
{
private:
unique_ptr<itemType []> queueArray;
int queueSize;
int front;
int rear;
int numItems;
public:
Queue(int);
itemType peekFront();
void enqueue(itemType item);
void dequeue();
bool isEmpty() const;
bool isFull() const;
void clear();
};
And I have tried this and many other ways but cant figure out how to tell what type of data the user inputs and then create a Queue with that type of data.
int main()
{
const int MAXSIZE = 5;
int choice;
cout << "1. integer queue\n" << "2. string queue\n" << "3. float queue\n";
choice = menu();
if(choice == 1)
{
Queue<int> newQueue(MAXSIZE);
int data;
}
else if(choice == 2)
{
Queue<string> newQueue(MAXSIZE);
string data;
}
else if(choice == 3)
{
Queue<float> newQueue(MAXSIZE);
float data;
}
else
cout << "Number needs to be 1-3." << endl;
cout << "Enter an item to add" << endl;
cin >> data;
newQueue->enqueue(data);
Thanks everyone for the help! I almost have it done, but now that I have all virtual functions how do I call peekFront()? Since the virtual functions can't return itemType right?
You need runtime polymorphism to solve this problem. This can either be achieved with a base class:
class IQueue {
virtual ~IQueue() = default;
virtual void enqueue(istream&) = 0;
};
template<class itemType>
class Queue : public IQueue
{
//...
public:
void enqueue(istream& is) override {
itemType item;
is >> item;
enqueue(item);
}
//...
};
And use as a pointer
int main() {
//...
unique_ptr<IQueue> newQueue;
//...
if(choice == 1)
{
newQueue.reset(new Queue<int>(MAXSIZE));
int data;
}
//...
newQueue->enqueue(cin);
//...
}
Or something like std::variant.
Well, you are almost there.
You just need to not loose the scope of your data and newQueue variables.
template <typename T>
T input()
{
T data;
cout << "Enter an item to add" << endl;
cin >> data;
return data;
}
int main()
{
const int MAXSIZE = 5;
int choice;
cout << "1. integer queue\n" << "2. string queue\n" << "3. float queue\n";
choice = menu();
if(choice == 1)
{
Queue<int> newQueue(MAXSIZE);
newQueue->enqueue(input<int>());
}
else if(choice == 2)
{
Queue<string> newQueue(MAXSIZE);
newQueue->enqueue(input<string>());
}
else if(choice == 3)
{
Queue<float> newQueue(MAXSIZE);
newQueue->enqueue(input<float>());
}
else
cout << "Number needs to be 1-3." << endl;
}
You still have some problem with this architecture, for example, maybe you want to move your queues outside these ifs, otherwise you can't use them anymore. (Read about scope).
You could also look at std::variant for these kind of situations.
I have recently tried to learn how to create an object of vectors in order to represent objects of students including their names and grades. but when I wrote my program I got some errors regarding using &. I do not know what is the problem with my errors. could you please help me to fix it?
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void printvector(const vector< student>&); // fill vector.fill in student information
void fillvector(vector< student>&); // print the information of all students
class student {
public:
student();
student(string, char);
~student();
string getName() ;
char getGrade() ;
void setName(string);
void setGrade(char);
private:
string newName;
char newGrade;
};
student::student() { newGrade = ' '; }
student::student(string name, char grade) {
newName = name;
newGrade = grade;
}
student::~student(){ }
string student::getName() { return newName; }
char student::getGrade() { return newGrade; }
void student::setName(string name) { newName = name; }
void student::setGrade(char grade) { newGrade = grade; }
int main() {
vector<student> myclass;
printvector(myclass);
fillvector(myclass);
return 0;
}
void fillvector(vector< student>& newmyclass) {
string name;
char grade;
int classsize;
cout << "how many students are in your class?";
cin >> classsize;
for (int i = 0; i < classsize; i++) {
cout << "enter student name";
cin >> name;
cout << "enter student grade";
cin >> grade;
student newstudent(name, grade);
newmyclass.push_back(newstudent);
cout << endl;
}
}
void printvector( vector< student>& newmyclass) {
unsigned int size = newmyclass.size();
for (unsigned int i = 0; i < size; i++) {
cout << "student name:" << newmyclass[i].getName() << endl;
cout << endl;
cout << "student grade" << newmyclass[i].getGrade() << endl;
cout << endl;
}
}
It seems you're printing your vector before filling it.. Is your problem fixed when you swap them around?
int main() {
vector<student> myclass;
printvector(myclass); // <--- These two lines should probably be swapped
fillvector(myclass); // <---
return 0;
}
(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?
#ifndef MOVIETREE_H_INCLUDED
#define MOVIETREE_H_INCLUDED
#include <iostream>
#include <cstdlib>
#include <vector>
#include <math.h>
using namespace std;
class BinarySearchTree
{
private:
struct tree_node
{
tree_node* left;
tree_node* right;
int ranking;
string title;
int year;
int quantity;
};
tree_node* root;
public:
BinarySearchTree()
{
root = NULL;
}
bool isEmpty() const { return root==NULL; }
void insert(int ranking, string title, int year, int quantity);
void remove(string title);
void inorder(tree_node* p);
double orderrating(string title);
void print_inorder();
void search(string d);
void rent(string l);
// void split(const string& s, char c,vector<string>& v);
};
double BinarySearchTree::orderrating(string title)
{
// string letters[52]={"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","o","p","q","r","s","t","u","v","w","x","y","z"};
char letters[54]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
'P','Q','R','S','T','U','V','W','X','Y','Z',':','a','b','c','d','e','f','g','h','i','j',
'k','l','m','o','p','q','r','s','t','u','v','w','x','y','z',' '};
double rating = 0;
for(int i = 0; i<title.length();i++)
{
for(int j = 0;j<52;j++)
{
if(letters[j]==title.at(i))
{
rating = rating+pow(10,-i)*((j)%26);
}
}
}
//cout<<rating<<endl;
return rating;
}
void split(const string& s, char c, vector<string>& v)
{
string::size_type i = 0;
string::size_type j = s.find(c);
while (j != string::npos) {
v.push_back(s.substr(i, j-i));
i = ++j;
j = s.find(c, j);
if (j == string::npos)
v.push_back(s.substr(i, s.length()));
}
}
void BinarySearchTree::insert(int ranking, string title, int year, int quantity)
{
tree_node* t = new tree_node;
tree_node* parent;
t->quantity = quantity;
t->ranking = ranking;
t->title = title;
t->year = year;
t->left = NULL;
t->right = NULL;
parent = NULL;
// is this a new tree?
if(isEmpty()) root = t;
else
{
//Note: ALL insertions are as leaf nodes
tree_node* curr;
curr = root;
// Find the Node's parent
while(curr)
{
parent = curr;
if(orderrating(t->title) > orderrating(curr->title)) curr = curr->right;
else curr = curr->left;
}
if(orderrating(t->title) <= orderrating(parent->title))
parent->left = t;
else
parent->right = t;
}
}
void BinarySearchTree::search(string l)
{
//Locate the element
bool found = false;
double d = orderrating(l);
if(isEmpty())
{
cout<<" This Tree is empty! "<<endl;
return;
}
tree_node* curr;
tree_node* parent;
curr = root;
while(curr != NULL)
{
if(curr->title == l)
{
found = true;
cout << "Movie Info:" << endl;
cout << "===========" << endl;
cout << "Ranking:" <<curr->ranking<<endl;
cout << "Title:"<<curr->title<<endl;
cout << "Year:" <<curr->year<<endl;
cout << "Quantity:"<<curr->quantity<<endl;
break;
}
else
{
parent = curr;
if(d>orderrating(curr->title)) curr = curr->right;
else curr = curr->left;
}
}
if(!found)
{
cout<<" Movie not found."<<endl;
return;
}
}
void BinarySearchTree::rent(string l)
{
//Locate the element
bool found = false;
double d = orderrating(l);
if(isEmpty())
{
cout<<"This Tree is empty!"<<endl;
return;
}
tree_node* curr;
tree_node* parent;
curr = root;
while(curr != NULL)
{
if(curr->title == l)
{
found = true;
if(curr->quantity!=0)
{curr->quantity = curr->quantity-1;
cout << "Movie has been rented." << endl;
cout << "Movie Info:" << endl;
cout << "===========" << endl;
cout << "Ranking:" <<curr->ranking<<endl;
cout << "Title:" <<curr->title<<endl;
cout << "Year:" <<curr->year<<endl;
cout << "Quantity:" << curr->quantity<<endl;
}
else{//If movie is in stock
cout << "Movie out of stock." << endl;
}
break;
}
else
{
parent = curr;
if(d>orderrating(curr->title)) curr = curr->right;
else curr = curr->left;
}
}
if(!found)
{
cout<<"Movie not found."<<endl;
return;
}
}
void BinarySearchTree::print_inorder()
{
inorder(root);
}
int counter =0;
void BinarySearchTree::inorder(tree_node* p)
{
if(p != NULL)
{
if(p->left) inorder(p->left);
cout<<"Movie: "<<p->title<<endl;
//cout<<" "<<p->quantity<<endl;//cout<<counter<<endl;
if(p->right) inorder(p->right);
}
else return;
}
#endif // MOVIETREE_H_INCLUDED
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <stdlib.h>
#include "MovieTree.h"
using namespace std;
struct MovieInfo{
int ranking;
string title;
int year;
int quantity;
};
int main(int argc, char * argv[])
{
//creates struct to store movie info
MovieInfo MovieInfo1[51];
int counter1 = 0;
std::string word1;
//"Assignment5Movies.txt"
ifstream myfile1("Assignment5Movies.txt");
if (myfile1.is_open())
{
std::string line;
while ( getline (myfile1,line) )
{
//need delimeter for file.
vector<string> v;
string s = line;
split(s, ',', v);
for (unsigned int i = 0; i < v.size(); ++i)
//add individual atributes to moviearray
{//cout<<v[i]<<endl;
if(i%4==1){MovieInfo1[counter1].title = v[i];}
if(i%4==2){ int value =atoi(v[i].c_str()); MovieInfo1[counter1].year = value;}
if(i%4==3){ int value =atoi(v[i].c_str()); MovieInfo1[counter1].quantity = value;}
if(i%4==0){ int value =atoi(v[i].c_str()); MovieInfo1[counter1].ranking = value;}
}//cout<<counter1<<endl;
counter1++;
}
myfile1.close();
}
// construct Binary tree
BinarySearchTree b;
for(int i = 0; i<counter1;i++)
{
b.insert(MovieInfo1[i].ranking,MovieInfo1[i].title,MovieInfo1[i].year, MovieInfo1[i].quantity);
}
int option;
//do while loop for user interface
do{
cout << "======Main Menu=====" << endl;
cout << "1. Find a movie" << endl;
cout << "2. Rent a movie" << endl;
cout << "3. Print the inventory" << endl;
cout << "4. Quit" << endl;
cin>>option;
cin.ignore(10000,'\n');
if (option==1)//find movie
{
cout << "Enter title:" << endl;
string temp;
cin >> ws;
getline(cin, temp);
b.search(temp);
}
if (option==2)//rent movie
{
cout << "Enter title:" << endl;
string temp;
cin >> ws;
getline(cin, temp);
b.rent(temp);
}
if (option==3)//print inventory
{
b.print_inorder();
}
}while(option!=4);
cout << "Goodbye!" << endl;
}
here is my main file and my header, basically my output is off for like two movies and I don't know why. any input would be appreciated. and yes I should have used a string.compare(string) also when given a txt file it prints
12 Angry Men
Back to the Future
Casablanaca
... the rest are in order except
Lord of the Rings: the two towers
Lord of the Rings: the fellowship of the ring
Lord of the Rings: the return of the king
are in the right place, but ordered incorrectly.
The value of orderrating() for these three movies is identical. Therefore, they will be printed in the opposite order that you insert them into the tree.
Lord of the Rings: the two towers
Lord of the Rings: the fellowship of the ring
Lord of the Rings: the return of the king
There's only so much precision in a double.
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)
{}