I am currently having trouble with outputting from my program correctly. The currentNode pointer is empty, and I am unsure how to get it to not be empty. This program deals with linked lists, and I have tried using getters to no avail (I get a segmentation fault when I try). The program is supposed to take state parks, insert them into a linked list, search for pertinent data from the state parks, and output the summary to a file. All I get is output statements in the file, with no data where it should be. Here is all pertinent code to the program:
parkLL.h:
#include <string>
#include <cstddef>
#include <iostream>
#include <cstring>
using namespace std;
struct ParksNode;
typedef ParksNode* ParksPtr;
struct ParksNode
{
string parkName;
string parkLocation;
string parkOpeningYear;
string parkDescription;
int noTimesReferenced;
ParksPtr parkLink;
};
class Parks
{
public:
Parks();
~Parks();
void Delete(string pName);
int GetLength() const;
ParksNode GetNextPark();
bool HasNext() const;
void Insert(string& pName, string& pLocation, string& pOpeningYear,
string& pDescription, int& numberTimesReferenced);
bool IsEmpty() const;
bool IsFull() const;
bool IsThere(string pName) const;
private:
ParksNode* parkDataPtr; //Points to the first node in the list
int length;
ParksNode* parkCurrentPos; //Points to the current position in the list
ParksNode* parkLastPtr; //Point to the last node in the list
};
parkLL.cpp
#include <string>
#include <iostream>
#include <cstddef>
#include <cstring>
#include "parkLL.h"
using namespace std;
Parks::Parks()
//The parkDataPtr will be set to NULL
{
parkDataPtr = NULL;
parkCurrentPos = parkDataPtr;
length = 0;
}
Parks::~Parks()
//The destructor for the Parks Linked List class
{
ParksPtr parkTempPtr;
ParksPtr parkCurrPtr = parkDataPtr;
while(parkCurrPtr != NULL)
{
parkTempPtr = parkCurrPtr;
parkCurrPtr = parkCurrPtr->parkLink;
delete parkTempPtr;
}
}
void Parks::Delete(string pName)
//The delete method for the Parks Linked List class
{
ParksPtr parkPrevPtr = NULL; //The trailing pointer for the list
ParksPtr parkCurrPtr = parkDataPtr; //The loop control pointer
while(parkCurrPtr != NULL && parkCurrPtr->parkName != pName &&
parkCurrPtr->parkName < pName)
{
parkPrevPtr = parkCurrPtr;
parkCurrPtr = parkCurrPtr->parkLink;
}
if(parkCurrPtr != NULL && parkCurrPtr->parkName == pName) //the item has
been found
{
if(parkCurrPtr == parkDataPtr)
{
parkDataPtr = parkCurrPtr->parkLink;
}
else
{
parkPrevPtr->parkLink = parkCurrPtr->parkLink;
}
if(parkCurrPtr == parkLastPtr)
{
parkLastPtr = parkPrevPtr;
}
delete parkCurrPtr;
length--;
}
}
int Parks::GetLength() const
//Returns the length of the current list
{
return(length);
}
ParksNode Parks::GetNextPark()
//Gets the next park in the linked list
{
ParksNode currentPark;
currentPark.parkName = parkCurrentPos->parkName;
currentPark.parkLocation = parkCurrentPos->parkLocation;
currentPark.parkOpeningYear = parkCurrentPos->parkOpeningYear;
currentPark.parkDescription = parkCurrentPos->parkDescription;
currentPark.noTimesReferenced = parkCurrentPos->noTimesReferenced;
parkCurrentPos = parkCurrentPos->parkLink;
return(currentPark);
}
bool Parks::HasNext() const
//Checks to see if there is another park in the list
{
return(parkCurrentPos!=NULL);
}
void Parks::Insert(string& pName, string& pLocation, string& pOpeningYear,
string& pDescription, int& numberTimesReferenced)
//The insert method for the Parks Linked List class
{
ParksPtr parkCurrPtr; //moving pointer
ParksPtr parkPrevPtr; //trailing pointer
ParksPtr parkNewNodePtr; //pointer to a new node
parkNewNodePtr = new ParksNode;
parkNewNodePtr->parkName = pName;
parkNewNodePtr->parkLocation = pLocation;
parkNewNodePtr->parkOpeningYear = pOpeningYear;
parkNewNodePtr->parkDescription = pDescription;
parkNewNodePtr->noTimesReferenced = numberTimesReferenced;
parkCurrPtr = parkDataPtr;
parkPrevPtr = NULL;
while(parkCurrPtr != NULL && parkCurrPtr->parkName < pName)
{
parkPrevPtr = parkCurrPtr;
parkCurrPtr = parkCurrPtr->parkLink;
}
//Inserting the new node
parkNewNodePtr->parkLink = parkCurrPtr;
if(parkPrevPtr == NULL)
{
parkDataPtr = parkNewNodePtr;
}
else
{
parkPrevPtr->parkLink = parkNewNodePtr;
}
if(parkCurrPtr == NULL)
{
parkLastPtr = parkNewNodePtr;
}
length++;
}
bool Parks::IsEmpty() const
//Checks to see if the list is empty
{
return(parkDataPtr == NULL);
}
bool Parks::IsFull() const
//Checks to see if the list is full, will always return false because this
is a linked list
{
return(false);
}
bool Parks::IsThere(string pName) const
//Checks to see if an item is in the linked list
{
ParksPtr parkCurrPtr = parkDataPtr; //Loop control pointer
while(parkCurrPtr != NULL && parkCurrPtr->parkName != pName)
{
parkCurrPtr = parkCurrPtr->parkLink;
}
if(parkCurrPtr != NULL)
{
return(true);
}
else
{
return(false);
}
}
updateLL.cpp
#include <string>
#include <iostream>
#include <fstream>
#include <cstddef>
#include "parkLL.h"
void CloseFiles(ifstream& parkDataFile, ifstream& parkLookupFile, ofstream&
parkOutputFile);
//This function closes all data files
void OpenFiles(string& parkDataFileName, string& parkLookupFileName, string&
parkOutputFileName, ifstream& parkDataFile, ifstream& parkLookupFile,
ofstream& parkOutputFile);
//This function opens all data files
int main()
{
string parkDataFileName; //The variable for the data file for park info
string parkLookupFileName; //The variable for the lookup file name
string parkOutputFileName; //The variable for the output file name
ifstream parkDataFile; //The variable for the park data input file
ifstream parkLookupFile; //The variable for the park lookup file
ofstream parkOutputFile; //The variable for the park output file
string parkName2; //The variable for the park name
string parkLocation2; //The variable for the park location
string parkOpeningYear2; //The variable for the park opening year
string parkDescription2; //The variable for the park description
int noTimesReferenced2; //The variable for the number of times
referenced
string lookupChoice; //The variable for the information to look up
string option; //The variable for the option of data output
Parks currentPark; //The variable for the current park
ParksPtr currentNode; //The variable for the current node
cout << "Please enter the data file name: ";
cin >> parkDataFileName;
cout << "Please enter the lookup file name: ";
cin >> parkLookupFileName;
cout << "Please enter the output file name: ";
cin >> parkOutputFileName;
OpenFiles(parkDataFileName, parkLookupFileName, parkOutputFileName,
parkDataFile, parkLookupFile, parkOutputFile);
getline(parkDataFile, parkName2, '#'); //priming read for while loop
while (parkDataFile)
{
getline(parkDataFile, parkLocation2, '#');
getline(parkDataFile, parkOpeningYear2, '#');
getline(parkDataFile, parkDescription2);
noTimesReferenced2 = 0;
currentPark.Insert(parkName2, parkLocation2, parkOpeningYear2,
parkDescription2, noTimesReferenced2);
getline(parkDataFile, parkName2, '#');
}
cout << endl;
cout << "Outputting the info to file" << endl;
getline(parkLookupFile, parkName2, '#');
getline(parkLookupFile, lookupChoice);
currentNode = new ParksNode;
while(parkLookupFile)
{
if(currentPark.IsThere(parkName2))
{
if (lookupChoice == "Year")
{
parkOutputFile << currentNode->parkName << " established in
" << currentNode->parkOpeningYear << endl;
currentNode->noTimesReferenced = currentNode-
>noTimesReferenced + 1;
}
else if (lookupChoice == "Description")
{
parkOutputFile << currentNode->parkName << " is " <<
currentNode->parkDescription << endl;
currentNode->noTimesReferenced = currentNode-
>noTimesReferenced + 1;
}
else if (lookupChoice == "Location")
{
parkOutputFile << currentNode->parkName << " located near "
<< currentNode->parkLocation << endl;
currentNode->noTimesReferenced = currentNode-
>noTimesReferenced + 1;
}
else if (lookupChoice == "Remove")
{
currentPark.Delete(parkName2);
}
}
else
{
parkOutputFile << "** " << parkName2 << " is not an available
state park" << endl;
}
getline(parkLookupFile, parkName2, '#');
getline(parkLookupFile, lookupChoice);
}
delete currentNode;
parkOutputFile << "Summary (state park/ reference frequency)" << endl;
while(currentPark.HasNext())
{
parkOutputFile << currentNode->parkName << " " << currentNode-
>noTimesReferenced;
}
CloseFiles(parkDataFile, parkLookupFile, parkOutputFile);
}
void CloseFiles(ifstream& parkDataFile, ifstream& parkLookupFile, ofstream&
parkOutputFile)
{
parkDataFile.close();
parkLookupFile.close();
parkOutputFile.close();
}
void OpenFiles(string& parkDataFileName, string& parkLookupFileName, string&
parkOutputFileName, ifstream& parkDataFile, ifstream& parkLookupFile,
ofstream& parkOutputFile)
{
parkDataFile.open(parkDataFileName.c_str());
parkLookupFile.open(parkLookupFileName.c_str());
parkOutputFile.open(parkOutputFileName.c_str());
}
I apologize in advance for any syntax errors that may occur in the code as transferring the code is difficult. Please help me at your convenience. Thank you very much for any and all assistance with this matter.
Related
Trying to create a Hash Table with name as key and it's value as the drink, when printTable() is invoked without adding items (i.e. commenting out the following code snippet) it prints out the added image without any address boundary error :
h.addItem("Paul", "Locha");
h.addItem("Kim", "Iced Mocha");
h.addItem("Emma", "Strawberry Smoothy");
h.addItem("Annie", "Hot Chocolate");
h.addItem("Sarah", "Passion Tea");
h.addItem("Pepper", "Caramel Mocha");
h.addItem("Mike", "Chai Tea");
h.addItem("Steve", "Apple Cider");
h.addItem("Bill", "Root Bear");
h.addItem("Marie", "Skinny Latte");
Image of output with given default values
But when items are added either by parsing csv or directly calling the class member function of addItem(), the program renders an error like so :
➜ Hash Table ./hashTableWithStruct.o
fish: Job 1, './hashTableWithStruct.o' terminated by signal SIGSEGV (Address boundary error)
The erroneous code is herewith :
hashTableWithStruct.cpp
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class Hash
{
private:
static const int tableSize = 10;
struct item
{
string name;
string drink;
item *next;
};
item *hashTable[tableSize];
public:
Hash()
{
for (int i = 0; i < tableSize; i++)
{
hashTable[i] = new item;
hashTable[i]->name = "empty";
hashTable[i]->drink = "empty";
hashTable[i]->next = NULL;
}
}
int hashFunct(string key)
{
int hashed = 0;
for (int i = 0; key[i] != '\0'; i++)
{
hashed += (int)key[i];
}
return (hashed % tableSize); //returns the BUCKET value
}
void addItem(string name, string drink)
{
int BUCKET = hashFunct(name);
//if the value at BUCKET hasn't been written yet,
//override the default empty ones
if (hashTable[BUCKET]->name == "empty")
{
hashTable[BUCKET]->name = name;
hashTable[BUCKET]->drink = drink;
}
//otherwise, make a linked list starting from BUCKET
else
{
item *ptr = hashTable[BUCKET];
item *n = new item;
n->name = name;
n->drink = drink;
n->next = NULL;
//the linked list might contain many nodes,
//hence travel to last node and reassign the last node to be this new item
while (ptr != NULL)
ptr = ptr->next;
ptr->next = n;
}
return;
}
int numOfItemsInBucket(int BUCKET)
{
int count = 0;
if (hashTable[BUCKET]->name == "empty")
return count;
else
{
count++;
item *ptr = hashTable[BUCKET];
while (ptr->next != NULL)
{
count++;
ptr = ptr->next;
}
}
return count;
}
void printTable()
{
int num; //holds number of elements(items) in each bucket
for (int i = 0; i < tableSize; i++)
{
num = numOfItemsInBucket(i);
cout << "-----------------------------\n"
<< "Table[" << i << "]" << endl
<< hashTable[i]->name << endl
<< hashTable[i]->drink << endl
<< "# of items in bucket " << i << " : " << num << endl;
cout << "-----------------------------\n";
}
}
};
int main(int argc, char const *argv[])
{
Hash h;
/* string filename = "datasetForHashTable.csv";
ifstream myCSV(filename.c_str());
if (!myCSV.is_open())
{
cout<<"Failed to open file"<<endl;
return 0;
}
string name, drink;
while (myCSV.peek()!=EOF)
{
getline(myCSV, name, ',');
getline(myCSV, drink, '\n');
h.addItem(name, drink);
}
myCSV.close(); */
h.addItem("Paul", "Locha");
h.addItem("Kim", "Iced Mocha");
h.addItem("Emma", "Strawberry Smoothy");
h.addItem("Annie", "Hot Chocolate");
h.addItem("Sarah", "Passion Tea");
h.addItem("Pepper", "Caramel Mocha");
h.addItem("Mike", "Chai Tea");
h.addItem("Steve", "Apple Cider");
h.addItem("Bill", "Root Bear");
h.addItem("Marie", "Skinny Latte");
h.printTable();
return 0;
}
Basically, can't understand why the table won't print with name and drinks, since it works just fine when table is printed without it.
Please help, trying to figure this out since 2 days.
After this while loop
while (ptr != NULL)
ptr = ptr->next;
the pointer ptr is equal to nullptr. So the next statement
ptr->next = n;
invokes undefined behavior due to dereferencing a null pointer.
It seems you mean
while (ptr->next != NULL)
ptr = ptr->next;
ptr->next = n;
This program reads a CSV file and enters it into a binary search tree. So far I have managed to insert a new node, put it in order, however, internally, perform a search asking for the Varibale Key but I have not managed to get it to work, could someone help me?
The CSV file is reading a file that includes:
1, name1,123456
2, name2,165151
3, name3,1566516
#include <iostream>
#include <iomanip>
#include <fstream>
#include <memory>
#include <string>
#include <sstream>
#include <vector>
struct Person {
int key;
std::string name;
int num;
};
struct Node : Person {
Node(const Person &person) : Person(person) {}
std::unique_ptr<Node> left, right;
void insert(const Person &person);
};
void Node::insert(const Person &person) {
/* recur down the tree */
if (key > person.key) {
if (left)
left->insert(person);
else
left = std::make_unique<Node>(person);
} else if (key < person.key) {
if (right)
right->insert(person);
else
right = std::make_unique<Node>(person);
}
}
std::vector<Person> persons;
void inorder(Node *root) {
if (root) {
// cout<<"\t";
inorder(root->left.get());
std::cout << '\t' << root->key << ' ' << root->name << ' ' << root->num << '\n';
inorder(root->right.get());
}
}
Node *minValueNode(Node *node) {
Node *current = node;
/* loop down to find the leftmost leaf */
while (current && current->left) current = current->left.get();
return current;
}
int main() {
std::unique_ptr<Node> root;
std::ifstream fin("data.txt");
if (!fin) {
std::cout << "File not open\n";
return 1;
}
std::string line;
const char delim = ',';
while (std::getline(fin, line)) {
std::istringstream ss(line);
Person person;
ss >> person.key;
ss.ignore(10, delim);
std::getline(ss, person.name, delim);
ss >> person.num;
if (ss) persons.push_back(person);
}
for (unsigned int i = 0; i < persons.size(); i++) {
std::cout << std::setw(5) << persons[i].key << std::setw(20)
<< persons[i].name << std::setw(15) << persons[i].num << '\n';
if (!root) root = std::make_unique<Node>(persons[i]);
else root->insert(persons[i]);
}
std::cout << "\n\nInorder:\n";
// cout<<node.name;
inorder(root.get());
return 0;
}
/*bool busqueda(Node *root, int dato)
{
if(root){
return false;
}
else if(root->key==dato){
return true;
}
else if(dato<root->key){
busqueda(root->left.get(),dato);
}
else{
return busqueda(root->right.get(),dato);
}
}*/
Presuming that this is the function you need help with:
bool busqueda(Node *root, int dato) {
if(root){
return false;
}
else if(root->key==dato){
return true;
}
else if(dato<root->key){
busqueda(root->left.get(),dato);
}
else{
return busqueda(root->right.get(),dato);
}
}
There are a few issues here:
if(root) {
This is testing if root is not nullptr, so you're going to immediately bail if root points at something. Meaning, you will immediately return false if any tree is provided, which is the opposite of what you want. Even worse, if root is null you will proceed and try to dereference a null pointer, which will crash the program. Change this line to if (root != nullptr) {.
else if(dato<root->key){
busqueda(root->left.get(),dato);
}
This recursive call looks right except you don't return the result meaning that you will reach the end of a function returning bool without actually returning anything meaningful. Just add return before this function call.
You can mostly express this function using boolean logic as well:
bool busqueda(Node *root, int dato) {
return root != nullptr && (
root->key == dato ||
busqueda((dato < root->key ? root->left : root->right).get(), dato)
);
}
This makes it impossible to forget to return something.
As a side note, enable all compiler warnings -- it would have warned you about reaching the end of a non-void function without returning a value.
I have a program where I am setting up a closed hash table. In each Element of the Hash table, there is a Student class which holds varies members (name, id, year, etc.). I am simply trying to print out what has been added to my array, but I keep getting a SegFault, and I don't know why. It is only in my print function, though. I have copied the line of code to my other functions or put them in different classes, and they work there, but not when I try to print from my print function. I am at the end of my rope, trying to figure out why I can access the memory location of each member, but not it's actual value.
Here is my program:
main.cpp:
using namespace std;
#include <cstdlib>
#include "hash.h"
int main()
{
string temp1;
string temp2;
string temp3;
string temp4;
string temp5;
string temp6;
Hash h;
do{
cout << "set> ";
cin >> temp1;
//Checking for quit command.
if(temp1.compare("quit") == 0)
{
return 0;
}
//checking for add command.
else if(temp1.compare("add") == 0)
{
cin >> temp2;
cin >> temp3;
cin >> temp4;
cin >> temp5;
cin >> temp6;
Student *s1 = new Student(temp2, temp3, temp4, temp5, temp6);
Element e1(s1);
h.add(e1);
}
//checking for remove command.
else if(temp1.compare("remove") == 0)
{
int r;
cin >> r;
h.remove(r);
}
//checking for print command.
else if(temp1.compare("print") == 0)
{
h.print();
}
//Anything else must be an error.
else
{
cout << endl;
cout << "Error! "<< endl;
}
}while(temp1.compare("quit") != 0);
}
hash.h:
#include <string>
#include <iostream>
#include <cstdlib>
using namespace std;
// Student Class
class Student{
private:
string firstName;
string lastName;
string id;
string year;
string major;
public:
//Constructor
Student(string a, string b, string c, string d, string e);
friend class Element;
friend class Hash;
};
//Element class
class Element{
private:
Student *data;
public:
int getKey();
Student* getData();
void printStudent();
//Constructor
Element(Student *e)
{
data = e;
};
friend class Hash;
};
class Hash{
private:
Element **array;
public:
void add(Element);
void print();
void remove(int);
//Constructor
Hash()
{
array = new Element *[10];
};
friend class Student;
};
hash.cpp:
#include "hash.h"
//The Constructor for Student
Student::Student(string a, string b, string c, string d, string e)
{
firstName = a;
lastName = b;
id = c;
year = d;
major = e;
}
//getKey function for Element Class
int Element::getKey()
{
int key = atoi(getData()->id.c_str());
return key;
}
Student* Element::getData()
{
return data;
}
void Element::printStudent()
{
string c = data->firstName;
cout<< "(" << c << ")";
}
//The add command
void Hash::add(Element e1)
{
int x = e1.getKey()%10;
int i = 0;
if(array[x] == NULL || array[x]->getData() == NULL)
{
array[x] = &e1;
}
else
{while(array[x] != NULL || array[x]->getData() != NULL)
{
x=(x+(i*i))%10;
if(array[x] == NULL || array[x]->getData() == NULL)
{
array[x] = &e1;
break;
}
else
{
i++;
}
}}
}
//The remove command
void Hash::remove(int n)
{
Element e2(NULL);
for(int j = 0; j<10; j++)
{
if(n == array[j]->getKey())
{
array[j] = &e2;
cout << "true" << endl;
break;
}
}
cout << "false" << endl;
}
//The Print command
void Hash::print()
{ int k = 0;
while(k<10)
{
if(array[k] == NULL)
{
cout << "(NULL)";
}
else if(array[k]->getData() == NULL)
{
cout << "(DEL)";
}
else
{
cout << "(" << array[k]->getData()->firstName << ")";
}
k++;
}
cout << endl;
}
Thank you for your help.
You have dangling pointers.
This function gets a temporary copy of an Element, calling it e1.
//The add command
void Hash::add(Element e1)
{
It then stores the address of this local variable.
array[x] = &e1;
And when Hash::add leaves scope, e1 no longer exists.
}
array[x] now points to memory that is no longer Element e1.
The general problem you are facing is that you have designed a Hash class that maintains pointers to objects, but has little control or knowledge regarding when those objects get destroyed.
You will need to personally ensure that objects added to your Hash last at least as long as the Hash does.
Simplest solution for your problem could be to store Element instances in Hash by value not by pointers. So:
class Hash{
private:
Element *array;
public:
void add(Element);
void print();
void remove(int);
//Constructor
Hash()
{
array = new Element[10];
};
friend class Student;
};
Now when you store new element or remove existing you copy them:
array[x] = e1; // not &e1 anymore
This is not very good practice, but at least could change your program in some workable state with minimal changes.
I have built a static stack of structures, and everything works - including creating an array of the structures. However, for some reason I can't set the top of the array to a structure.
In my .cpp file, in my push function, I keep erroring on the following line:
stackArray[top] = newStudent;
The error I am receiving is:
"51: no match for 'operator=' in '(((studentstack)this)->studentstack::stackArray + (+(((unsigned int)((studentstack*)this)->studentstack::top) * 24u))) = ((studentstack*)this)->studentstack::newStudent' "
I am including my code below.
Header file:
#ifndef studentstack_H
#define studentstack_H
#include <iostream>
#include <string>
using namespace std;
class studentstack {
private:
int size; // Stack size
int top; // Top of the Stack
struct student {
int ID;
string Name;
string Address;
double GPA;
};
student * stackArray; // Pointer to the stack
student * newStudent; // Pointer to the new student
public: //Constructor
studentstack(int);
// Copy Constructor
studentstack(const studentstack &);
//Destructor
~studentstack();
//Stack Operaations
void push(string, int, double, string);
void pop(int &);
bool isFull() const;
bool isEmpty() const;
};
#endif
studentstack.cpp
#include <iostream>
#include "studentstack.h"
using namespace std;
studentstack::studentstack(int SIZE) {
stackArray = new student[SIZE];
size = SIZE;
top = -1;
int ID = 0;
double GPA = 0;
}
studentstack::studentstack(const studentstack &obj) {
if (obj.size > 0)
stackArray = new student[obj.size];
else
stackArray = NULL;
size = obj.size;
for (int count = 0; count < size; count++)
stackArray[count] = obj.stackArray[count];
top = obj.top;
}
studentstack::~studentstack() {
delete [] stackArray;
}
void studentstack::push(string name, int id, double gpa, string address) {
if (isFull()) {
cout << "The stack is full.\n";
} else {
top++;
newStudent = new student;
newStudent-> Name = name;
newStudent-> ID = id;
newStudent-> Address = address;
newStudent-> GPA = gpa;
stackArray[top] = newStudent;
}
}
void studentstack::pop(int &id) {
if (isEmpty()) {
cout << "The stack is empty.\n";
} else {
id = stackArray[top].ID;
top--;
}
}
bool studentstack::isFull() const {
bool status;
if (top == size - 1)
status = true;
else
status = false;
return status;
}
bool studentstack::isEmpty() const {
bool status;
if (top == -1)
status = true;
else
status = false;
return status;
}
main.cpp
#include "studentstack.h"
#include <iostream>
#include <string>
using namespace std;
int main() {
string name;
int id, var;
string address;
double gpa;
studentstack s[20];
for(int x =0; x<20; x++) {
cout << "New Student Name: " << endl;
cin >> name;
cout << "ID: " << endl;
cin >> id;
cout << "GPA: " << endl;
cin >> gpa;
cout << "Address: " << endl;
cin >> address;
s.push(name, id, gpa, address)
}
cout << "Popping: "
for(int x = 0; x < 5; x++) {
s.pop(var);
cout <<var;
}
return(0);
}
You might want to cut down the example to a minimal piece of code showing the problem. What it comes down to is that you try to assign a student* to a an element in an array of student objects. A pointer to an object is different to an object:
stackArray[0] = new student(); // does NOT work
stackArray[0] = student();
Note, that object are created in C++ by a constructor and not necessarily involving new. When you construct and object using new you still create an object but you also allocate space for it on the heap. By default, objects are created wherever they are defined. For example, student() creates an object on the stack which is then assigned to an object in the memory of stackArray[0].
Not directly related to your question, but note that your main() cannot work. You declare an array of 20 studentstack elements:
studentstack s[20];
and later on you're doing:
s.push(/* ... */);
s.pop(/* ... */);
That doesn't make much sense. s is not a studentstack. It's an array of studentstacks. Arrays in C++ don't have member functions.
My program is to print the queue of information from a file but i have problem with my following code. When i run the program it keep loop. I cant figure out the problem. Any help?
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <queue>
#include <list>
using namespace std;
void simulation(ifstream &infile);
void processArrival(int *newEvent, ifstream &inFile, list<int> eventList,queue<int> printQueue);
void processDeparture(int *newEvent, list<int> eventList,queue<int> printQueue);
string name[100];
int timeAccepted[100];
int fileSize[100];
int i = 1;
int j = 1;
int currentTime;
bool checker = true;
int main(void)
{
ifstream inFile;
string fileName;
int i = 0;
inFile.open("123.txt", ios::in);
simulation(inFile);
/*while(inFile.peek() != EOF )
{
inFile>>name[i]>>timeAccepted[i]>>fileSize[i];
i++;
}
for(int s = 0; s < i; s++)
{
cout << name[s] << timeAccepted[s] << fileSize[s] <<endl;
}*/
return 0;
}
void simulation(ifstream &inFile)
{
queue<int> printQueue;
list<int> eventList;
int *newEvent;
while(inFile.peek() != '\n')
{
inFile>>name[0]>>timeAccepted[0]>>fileSize[0];
}
eventList.push_front(timeAccepted[0]);
int checkEmpty = eventList.empty();
newEvent = &eventList.front();
while(checkEmpty ==0)
{
newEvent = &eventList.front();
if(checker)
{
processArrival(newEvent, inFile, eventList, printQueue);
}
else
{
processDeparture(newEvent, eventList, printQueue);
}
checkEmpty = eventList.empty();
}
}
void processArrival(int *newEvent, ifstream &inFile, list<int> eventList,queue<int> printQueue)
{
int atFront=0;
atFront = printQueue.empty();
cout << atFront <<endl;
printQueue.push(*newEvent);
cout << printQueue.front() <<endl;
eventList.remove(*newEvent);
int temp;
if(atFront==1)
{
currentTime = *newEvent + fileSize[0];
cout << name[0] << " ## " << *newEvent << " ## " << currentTime << endl;
eventList.push_back(currentTime);
}
checker = false;
if(inFile.peek() != EOF )
{
inFile>>name[i]>>timeAccepted[i]>>fileSize[i];
eventList.push_back( timeAccepted[i] );
i++;
checker = false;
if(eventList.back() <= eventList.front())
{
temp = eventList.back();
eventList.back() = eventList.front();
eventList.front() = temp;
checker = true;
}
}
}
void processDeparture(int *newEvent, list<int> eventList,queue<int> printQueue)
{
printQueue.pop();
eventList.pop_front();
int checkEmpty = 1;
checkEmpty = printQueue.empty();
int temp;
if(checkEmpty ==0)
{
currentTime = *newEvent + fileSize[j];
cout << name[j] << " " << *newEvent << " " << currentTime << endl;
eventList.push_back(currentTime);
checker = true;
if(eventList.back() < eventList.front())
{
temp = eventList.back();
eventList.back() = eventList.front();
eventList.front() = temp;
checker = false;
}
j++;
}
}
Your processArrival and processDeparture functions are taking their eventList and printQueue arguments by value. This means that when you call them, for example in this line:
processArrival(newEvent, inFile, eventList, printQueue);
Copies of eventList and printQueue are made and passed into the processArrival function. The processArrival function then operates on those copies, and the original data is never modified. In particular, this means that the original eventList will never have any items removed from it, so it will never be empty -- it will just keep trying to process the first event over and over again.
The solution is to pass these parameters by reference. i.e. change the definition of processArrival to
void processArrival(int *newEvent, ifstream &inFile, list<int>& eventList, queue<int>& printQueue)
Note the & characters that I have inserted before eventList and printQueue. These cause references to the original data, rather than copies of the original data, to be passed into the processArival function. This means that processArrival will operate directly on the original data as you intend it to. Don't forget to make the corresponding change to processDeparture as well.