I'm doing a Shopping Mall project in Link List C++. In which I have to insert new Shop,Search Shop, Delete Shop, Count Shops and Display all. I written some of code.
I wrote the code but:
(1) it give error in input after when I input 2nd time and press input at last input i gives following Exception.
"Exception thrown: read access violation.
std::_String_alloc > >::_Mysize(...) returned 0xCDCDCDE1."
(2) When I display it give following Exception:
Exception thrown: read access violation.
temp was 0xCDCDCDCD.
Here is main.
int main()
{
ShoppingMallList* shopList=new ShoppingMallList();
string name="";
int shopNumber;
string brandShop;
int floor;
string shoptype;
do
{
system("cls");
cout << "**************WELCOME TO MALL**************\n1: Add Shop\n2: Search Shop\n3: Count Shops\n4:Display Shops\n5: Quit" << endl;
int option;
cin >> option;
switch (option)
{
case 1:
{
input(name, shopNumber, brandShop, floor, shoptype);
shopList->Insert(name, shopNumber, brandShop, floor, shoptype);
}
break;
case 2:
{
string name1;
cin.clear();
cin.ignore();
cout << "Enter Name of Shop to Search: ";
getline(cin, name1);
shopList->search(name1);
}
break;
case 4:
{
shopList->Print();
}
break;
case 5:
{
shopList->~ShoppingMallList();
exit(0);
}
break;
default:
continue;
}
system("pause");
shopList;
} while (true);
return 0;
}
void input(string& name, int& shopNumber, string& brandShop, int& floor, string& shoptype)
{
char temp;
cin.clear();
cin.ignore();
cout << "Enter Name: ";
getline(cin, name);
cout << "Enter Shop Number: ";
cin >> shopNumber;
cin.clear();
cin.ignore();
cout << "Enter Brand(yes/no): ";
getline(cin, brandShop);
cout << "Enter Floor: ";
cin >> floor;
cin.clear();
cin.ignore();
cout << "Enter Shop Type: ";
getline(cin, shoptype);
}
Here is shoppingMall.h
class ShoppingMall
{
friend std::ostream& operator<<(std::ostream& cout, const ShoppingMall& shop);
friend class ShoppingMallList;
public:
ShoppingMall(std::string& , int&, std::string&, int&, std::string&);
private:
std::string name;
int shopNumber;
std::string brandshop;
int floor;
std::string shopType;
ShoppingMall* link;
};
ShoppingMall::ShoppingMall(std::string& name , int& shopNumber, std::string& brandShop, int& floor, std::string& shoptype) : name(name), shopNumber(shopNumber), brandshop(brandShop), floor(floor), shopType(shoptype)
{
}
std::ostream& operator<<(std::ostream& cout, const ShoppingMall& shop)
{
cout << "Name: " << shop.name << std::endl << "Shop Number: " << shop.shopNumber << std::endl << "Brand Shop: " << shop.brandshop << std::endl << "Floor: " << shop.floor << std::endl << "Shop Type: " << shop.shopType << std::endl;
return cout;
}
And here is ShoppingMallList.h header file.
class ShoppingMallList
{
public:
ShoppingMallList();
void addToHead(std::string&, int&, std::string&, int&, std::string&);
void Insert(std::string&, int&, std::string&, int&, std::string&);
void Print();
int getsize();
void deleteShop(std::string&);
void search(std::string&);
private:
ShoppingMall* head;
int size;
};
ShoppingMallList::ShoppingMallList() : head(0), size(0)
{
}
void ShoppingMallList::addToHead(std::string& name, int& shopNumber, std::string& brandShop, int& floor, std::string& shoptype)
{
ShoppingMall* temp = new ShoppingMall(name,shopNumber,brandShop,floor,shoptype);
if (head==0)
{
head = temp;
}
else
{
temp->link = head;
head = temp;
}
size++;
}
int ShoppingMallList::getsize()
{
return size;
}
void ShoppingMallList::Print()
{
ShoppingMall* temp = head;
while ( temp != 0 )
{
std::cout << "Name: " << temp->name << std::endl << "Shop Number: " << temp->shopNumber << std::endl << "Brand Shop: " << temp->brandshop << std::endl << "Floor: " << temp->floor << std::endl << "Shop Type: " << temp->shopType << std::endl;
temp = temp->link;
}
}
void ShoppingMallList::Insert(std::string& name, int& shopNumber, std::string& brandShop, int& floor, std::string& shoptype)
{
ShoppingMall* newShop = new ShoppingMall(name, shopNumber, brandShop, floor, shoptype);
//case-1 EmptyList
if ( head == 0 )
{
head = newShop;
}
else
{
ShoppingMall* temp = head;
ShoppingMall* previous = 0;
// Traversing link to find insert location
while (temp!=0)
{
if ( temp->name >= newShop->name )
{
break;
}
else
{
previous = temp;
temp = temp->link;
}
}
//case-2 Adding To Head
if ( temp == head )
{
newShop->link = head;
head = newShop;
}
//case-3 Adding After Head
else
{
newShop->link = temp;
previous->link = newShop;
}
}
size++;
}
void ShoppingMallList::deleteShop(std::string& name)
{
ShoppingMall* temp=head;
ShoppingMall* previous = 0;
if (head == 0)
{
//Case-1 If There is no node
std::cout << "Shop cannot be deleted becasue the there no Node " << std::endl;
}
//Traversing Node to find node to delete
while (temp!=0)
{
if ( temp->name == name )
{
break;
}
else
{
previous = temp;
temp = temp->link;
}
}
//case-2 If Shop with name passed not found
if ( temp == 0 )
{
std::cout << "Shop of name " << name << " not found!" << std::endl;
}
else
{
//case-3 Delete node from head Node
if ( temp == head )
{
head = head->link;
}
//delete other than head shop
else
{
previous->link = temp->link;
}
delete temp;
size--;
}
}
void ShoppingMallList::search(std::string& name)
{
ShoppingMall* tempShop = head;
while ( tempShop != 0 )
{
if (tempShop->name == name)
{
std::cout << "Name: " << tempShop->name << std::endl << "Shop Number: " << tempShop->shopNumber << std::endl << "Brand Shop: " << tempShop- >brandshop << std::endl << "Floor: " << tempShop->floor << std::endl << "Shop Type: " << tempShop->shopType << std::endl;
}
else
{
tempShop = tempShop->link;
}
}
if ( tempShop == 0 )
{
std::cout << "Shop of name " << name << " not found!" << std::endl;
}
}
link field of ShoppingMall class is not initialized in constructor and contains some random rubbish. All list iterations like:
while ( temp != 0 )
{
// Code skipped for simplicity
temp = temp->link;
}
could cause Access Violation because condition temp != 0 never met and skipped code access memory at random address.
To fix it:
ShoppingMall::ShoppingMall(const std::string& name, int shopNumber, std::string& brandShop, int floor, const std::string& shoptype)
: link(nullptr), name(name), shopNumber(shopNumber), brandshop(brandShop), floor(floor), shopType(shoptype)
{
}
Related
I want to update a data in the node of the linked list. I have tried to but it does not changed the data within. If anyone can help me with this, i would be really appreciated.
This is my Main Driver Code
#include <iostream>
#include <fstream>
#include <string>
#include "item.h"
using namespace std;
LinkedList list;
Item item;
Node* node;
void menu()
{
here:
int choice = 0;
string itemId, title, type, loan, num_copy, fee, genre;
cout << "Welcome to Genie\'s video store" << endl;
cout << "Enter an option below" << endl;
cout << "1. Add a new item" << endl;
cout << "2. Delete an item" << endl;
cout << "3. Update an item" << endl;
cout << "4. Search an item by ID" << endl;
cout << "5. Search an item by title" << endl;
cout << "6. Display all item" << endl;
cout << "Exit" << endl;
cout << "Enter your choice: ";
cin >> choice;
if (choice == 1)
{
system("cls");
list.addItem(list);
cout << endl;
goto here;
}
else if (choice == 2)
{
system("cls");
list.deleteItem(list);
cout << endl;
goto here;
}
else if (choice == 3)
{
system("cls");
list.updateItem(list);
cout << endl;
goto here;
}
else if (choice == 4)
{
system("cls");
list.searchById(list);
cout << endl;
goto here;
}
else if (choice == 5)
{
system("cls");
list.searchByTitle(list);
cout << endl;
goto here;
}
else if (choice == 6)
{
system("cls");
list.printAll(list);
cout << endl;
goto here;
}
}
int main(int argc, char* argv[])
{
ifstream file("items.txt", ios::in);
if (!file)
{
cerr << "Error in opening file.";
throw(file);
}
list.readAllFile(file, list);
file.close();
menu();
return 0;
}
And this is my item.h:
#pragma once
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Item
{
protected:
string itemId, title, type, loan, num_copy, fee, genre;
public:
Item() {}
Item(string itemId, string title, string type, string loan, string num_copy, string fee, string genre)
: itemId(itemId), title(title), type(type), loan(loan), num_copy(num_copy), fee(fee), genre(genre)
{}
~Item() {}
string& getItemId() { return this->itemId; }
string& getTitle() { return this->title; }
string& getType() { return this->type; }
string& getLoan() { return this->loan; }
string& getCopy() { return this->num_copy; }
string& getFee() { return this->fee; }
string& getGenre() { return this->genre; }
void setItemId(string itemId) { this->itemId = itemId; }
void setTitle(string title) { this->title = title; }
void setFee(string fee) { this->fee = fee; }
void setCopy(string num_copy) { this->num_copy = num_copy; }
void setLoan(string loan) { this->loan = loan; }
void setType(string type) { this->type = type; }
void setGenre(string genre) { this->genre = genre; }
};
class Node
{
private:
Item data;
Node* next;
public:
Node() {}
Node(Item newData)
{
data = newData;
next = nullptr;
}
Node(Item newData, Node* nextNode)
{
data = newData;
next = nextNode;
}
~Node() {}
Node* getNext() { return next; }
void setNext(Node* newNext) { next = newNext; }
Item getData() { return data; }
Item setData(Item newData) { data = newData; }
Node* createNode(Item newData);
};
class LinkedList
{
private:
Node* head;
Node* tail;
public:
LinkedList() : head(NULL), tail(NULL)
{}
~LinkedList() {}
void createList(LinkedList& list);
void insertHead(LinkedList& list, Node* temp);
void appenTail(LinkedList& list, Node* temp);
void readLine(ifstream& file, Item& item);
void readAllFile(ifstream& file, LinkedList& list);
void printOneLine(Item item);
void printAll(LinkedList list);
//void writeToFile(LinkedList& list);
void addItem(LinkedList& list);
void deleteItem(LinkedList list);
void updateItem(LinkedList& list);
void searchById(LinkedList list);
void searchByTitle(LinkedList list);
};
Finally, this is my item.cpp file:
void LinkedList::updateItem(LinkedList& list)
{
string updateId, updateTitle, updateType, updateLoan, updateNumCopy, updateFee, updateGenre;
Node node;
Node* temp = list.head;
bool found = false;
if (temp == nullptr)
{
cerr << "There are no items." << endl;
exit(EXIT_FAILURE);
}
cout << "Enter the item's id and other info you want to update below:" << endl;
cout << "ID: ";
cin.ignore();
getline(cin, updateId);
cout << "Title: ";
cin.ignore();
getline(cin, updateTitle);
cout << "Type: ";
cin.ignore();
getline(cin, updateType);
cout << "Loan type: ";
cin.ignore();
getline(cin, updateLoan);
cout << "Copy(s): ";
cin.ignore();
getline(cin, updateNumCopy);
cout << "Rental fee: ";
cin.ignore();
getline(cin, updateFee);
cout << "Rental genre: ";
cin.ignore();
getline(cin, updateGenre);
while (temp != nullptr)
{
Item item = temp->getData();
if ((_stricmp(item.getItemId().c_str(), updateId.c_str()) == 0) || (_stricmp(item.getTitle().c_str(), updateTitle.c_str()) == 0))
{
item.getItemId() = updateId;
item.getTitle() = updateTitle;
item.getType() = updateType;
item.getLoan() = updateLoan;
item.getFee() = updateFee;
item.getGenre() = updateGenre;
found = true;
}
temp = temp->getNext();
}
if (!found)
{
cerr << "Item not found." << endl;
exit(EXIT_FAILURE);
}
}
So the main problem is that inside the updateItem() function, we do not know how to make the function to update a specific variables of the object. I have tried the above updateItem function and the final result is that none of the item's information is changed.
Thank you.
Item item = temp->getData();
getData returns a copy and it is stored inside a new variable. You are making changes but it is not in the right variable. One solution would be to store and return a reference:
// return a reference
Item & getData() { return data; }
// store a reference
Item & item = temp->getData();
using namespace std;
void createsqueue();
void insertname();
void insertheight();
void del();
void push();
void display();
struct nodename
{
string name;
float height;
struct nodename *next;
};
nodename *front;
nodename *rear;
void createstack()
{
front = NULL;
rear = NULL;
}
void insertname()
{
while (true)
{
char dec;
nodename *temp;
temp = new nodename;
std::cout << "ENTER YOUR NAME : ";
std::cin >> temp -> name;
std::cout << "ENTER YOUR HEIGHT : ";
std::cin >> temp -> height;
std::cout <<'\n';
temp -> next = NULL;
if(rear == NULL)
{
rear = temp;
front = temp;
}
else
{
rear -> next = temp;
rear = temp;
}
std::cout << "ADD ANOTHER DATA? (Y/N) : ";
std::cin >> dec;
std::cout <<'\n';
if (dec == 'n' || dec == 'N')
{
break;
}
}
}
void del()
{
if(front != NULL)
{
nodename *temp = front;
cout << "The deleted element is: " << temp -> name << endl;
front = front -> next;
delete temp;
}
else
{
cout << "Queue List is empty!\n";
}
}
void display()
{
nodename *temp = front;
while(temp != NULL)
{
std::cout << "--------------------------" << '\n';
std::cout <<"NAME : "<< temp -> name << endl;
std::cout << showpoint << fixed << setprecision(0);
std::cout <<"HEIGHT : " << temp -> height << endl;
std::cout << showpoint << fixed << setprecision(2);
temp = temp -> next;
std::cout << "--------------------------" << '\n';
}
}
int main()
{
int operation;
createstack();
do
{
std::cout << "\tMAIN MENU" << endl;
std::cout << "1 - ENTER NAME : "
<< "\n2 - DELETE PREV DATA : "
<< "\n3 - DISPLAY DATA : "
<< "\n0 - End Program"
<< "\nEnter your operation: ";
cin >> operation;
switch (operation)
{
case 1: insertname();
break;
case 2: del();
break;
case 3: display();
break;
case 0: cout << "Program End";
break;
default:
cout << "Wrong option. Please insert a new operation: ";
}
}
while(operation ! = 0);
return 0;
}
This is the code.
The program Works fine the only problem I have is displaying the name with height in descending order so that the tallest person's info displays first
I have tried multiple ways but nothing seems to work it might be my in-experience in coding since im a newbie and pardon me for any error im just getting started
Modify the code for inserting a new name such that whenever you add a node,you find the correct position for it before inserting in the linked list.
void insertname(){
cin>>h;
nodename* ctr=front;
while(ctr-> height >h){
ctr=ctr->next;
}
nodename* temp =new nodename;
temp->next=ctr->next
ctr->next=temp
temp->height=h; //similarly for name
}
Just find it if the node added is the first node or any other which you have achieved and the above will add nodes in the descending order, which will be displayed as you wanted. So, you can modify it accordingly.
I've spent pretty much all day trying to do this, I understand pointers and what a linked list does, but I don't know how to actually code it and all I've found are Java and C examples which don't help because I'm using C++.
Thanks in advance for taking a look at my code and helping me, I really appreciate it considering how many days I've spent stressed out and confused about this. I'm not going to lie so far most of my deleteNode function is probably trash. But like I've said I'm just lost I don't even know where to start or how to progress because I only understand the concepts.
This is my data file.
John Doe 80
Jane Smith 70
Bill Jones 50
Pat Hughes 90
Sam Sosa 40
This is my Header file
#include<string>
using namespace std;
class student {
public:
student(); // constructor method
void st_fn(string fn);
string st_fn();
void st_ln(string ln);
string st_ln();
void st_score(float s);
float st_score();
string st_pass_or_fail();
// need a pointer to the next object
student *nxt_ptr;
protected: // protected can be inherited
float m_score;
string m_ln;
string m_fn;
string m_pf_msg;
};
student::student() //constructor
{
nxt_ptr = NULL;
m_score = 0;
}
void student::st_fn(string fn)
{
m_fn = fn;
}
string student::st_fn()
{
return m_fn;
}
void student::st_ln(string ln)
{
m_ln = ln;
}
string student::st_ln()
{
return m_ln;
}
void student::st_score(float s)
{
m_score = s;
}
float student::st_score()
{
return m_score;
}
string student::st_pass_or_fail()
{
if (m_score >= 60)
m_pf_msg = "PASSED";
else
m_pf_msg = "FAILED";
return m_pf_msg;
}
This is my .cpp file.
#include<iostream>
#include<string>
#include<fstream>
#include "Header.h"
using namespace std;
int display_menu()
{
int option;
cout << endl << endl;
cout << "1. Display List" << endl;
cout << "2. Add a student" << endl;
cout << "3. Delete first student" << endl;
cout << "4. Search by Last Name" << endl;
cout << "5. Exit" << endl;
cin >> option;
return option;
}
student * search_last_name(student *h)
{
student *f = NULL;
student *t = NULL;
string s_ln;
// prompt for last name to search for
cout << "Enter Last Name of the Student";
cin >> s_ln;
if (h != NULL)
{
t = h;
while (t != NULL)
{
if (t->st_ln() == s_ln)
f = t; // found the last name so save t
t = t->nxt_ptr;
}
}
else
cout << "List is empty" << endl;
return f;
}
void add_student(student *&head) // h is the head of the list
{
student *new_st, *r;
string fn, ln;
float s;
cout << "Enter new students first name, last name and score";
cin >> fn >> ln >> s;
// instantiate a new node, use new_st
new_st = new student;
new_st->st_fn(fn);
new_st->st_ln(ln);
new_st->st_score(s);
if (head == NULL)
head = new_st;
else
{
// find the last node, use r for this
// write code
r = head;
while (r->nxt_ptr != nullptr)
r = r->nxt_ptr;
// add to the back of the list
// write code
r->nxt_ptr = new_st;
} // end of else
} // end of add student
student * delete_front(student * head)
{
student *t;
// delete front node
// check for empty list
if (head != NULL)
{
// delete first node
t = head;
head = head->nxt_ptr;
delete(t);
}
else
cout << "List is empty - nothing to delete" << endl;
return head;
}
void deleteNode(struct Node *head, struct Node *n)
{
// When node to be deleted is head node
if (head == n)
{
n = head->next;
//Remove the link of next node
head->next = head->next->next;
return;
}
//When not first node, folow the normal deletion process
//Find the previous node
struct Node *prev = head;
while (prev->next != NULL && prev->next != n)
prev = prev->next;
// Check if node really exists in Linked List
if (prev->next == NULL)
{
cout << endl << "Given node is not present in Linked List";
return;
}
//Remove node from linked list should it exist
prev->next = prev->next->next;
return;
}
void display_list(student *t)
{
if (t == NULL)
cout << "List is Empty!";
else
{
while (t != NULL)
{
cout << "******Student******" << endl;
cout << t->st_ln() << endl;
cout << t->st_fn() << endl;
cout << t->st_score() << endl << endl;
t = t->nxt_ptr;
}
}
}
int main()
{
string ln, fn;
float s;
int n;
ifstream infile;
student *head = NULL; //pointer to a student object
student *cp = NULL; // pointer to end of the list
student *new_st = NULL; // pointer to a new student object
student *f = NULL; // pointer to found node
int option; // the numbe of menu item the user selects
infile.open("lab8d.txt");
while (!infile.eof())
{
infile >> fn >> ln >> s;
//instantiate a student object
new_st = new student;
//load the object with data
new_st->st_fn(fn);
new_st->st_ln(ln);
new_st->st_score(s);
// check for empty list - its a special case
if (head == NULL)
{
head = new_st;
cp = new_st;
}
else // list is not empty
{
cp->nxt_ptr = new_st;
cp = new_st;
}
} // end of loop
// loop to give the user some options
option = display_menu();
while (option != 5)
{
if (option == 1)
display_list(head);
else if (option == 2)
add_student(head);
else if (option == 3)
head = delete_front(head);
else if (option == 4)
{
f = search_last_name(head);
if (f != NULL)
{
cout << f->st_fn() << endl;
cout << f->st_ln() << endl;
cout << f->st_score() << endl;
cout << f->st_pass_or_fail() << endl;
}
else
cout << "Name not in the list" << endl;
}
else if (option == 6)
{
cout << "Enter the number of the node you would like to delete: " << endl;
cin >> n;
}
option = display_menu();
}
system("pause");
return 0;
}
The simpler and self-contained your functions are, the easier they are to test and debug, and the less like they are to fail.
Try something more like this:
Student.h:
#include <string>
class student_list;
class student
{
public:
student();
student(const std::string &fn, const std::string &ln, float s, student *nxt = NULL);
void next(student *s);
student* next() const;
void firstName(const std::string &fn);
std::string firstName() const;
void lastName(const std::string &ln);
std::string lastName() const;
void score(float s);
float score() const;
std::string pass_or_fail() const;
void display(bool showPassOrFail = false) const;
friend class student_list;
protected: // protected can be inherited
student *m_next;
std::string m_fn;
std::string m_ln;
float m_score;
};
Student.cpp:
#include "Student.h"
#include <iostream>
student::student()
: m_next(NULL), m_score(0)
{
}
student::student(const std::string &fn, const std::string &ln, float s, student *nxt)
: m_next(nxt), m_fn(fn), m_ln(ln), m_score(s)
{
}
void student::next(student *s)
{
m_next = s;
}
student* student::next() const
{
return m_next;
}
void student::firstName(const std::string &fn)
{
m_fn = fn;
}
std::string student::firstName() const
{
return m_fn;
}
void student::lastName(const std::string &ln)
{
m_ln = ln;
}
std::string student::lastName() const
{
return m_ln;
}
void student::score(float s)
{
m_score = s;
}
float student::score() const
{
return m_score;
}
std::string student::pass_or_fail() const
{
if (m_score >= 60)
return "PASSED";
else
return "FAILED";
}
void student::display(bool showPassOrFail) const
{
std::cout << lastName() << std::endl;
std::cout << firstName() << std::endl;
std::cout << score() << std::endl;
if (showPassOrFail)
std::cout << pass_or_fail() << std::endl;
}
StudentList.h:
#include <string>
class student;
class student_list
{
public:
student_list();
~student_list();
student* search_last_name(const std::string &ln);
student* insert(const std::string &fn, const std::string &ln, float s, student* after = NULL);
bool remove(int idx);
void display() const;
private:
student *m_head;
};
StudentList.cpp:
student_list::student_list()
: m_head(NULL)
{
}
student_list::~student_list()
{
while (m_head)
remove(0);
}
student* student_list::search_last_name(const std::string &ln)
{
student *t = m_head;
while (t)
{
if (t->lastName() == ln)
break; // found the last name
t = t->next();
}
return t;
}
student* student_list::insert(const std::string &fn, const std::string &ln, float s, student* after)
{
student **r;
if (after)
{
// add to list after the specified node
// get pointer to next node
r = &(after->m_next);
}
else
{
// add to the back of the list
// find pointer to last node
r = &m_head;
while (*r)
r = &((*r)->m_next);
}
// instantiate a new node
student *new_st = new student(fn, ln, s);
if (after)
new_st->next(*r);
// add to list
*r = new_st;
return new_st;
}
bool student_list::remove(int idx)
{
// delete a node at index
// find pointer to node
student **r = &m_head;
while ((*r) && (idx-- > 0))
r = &((*r)->m_next);
if (*r)
{
// delete node
student *t = *r;
*r = t->next();
delete t;
return true;
}
return false;
}
void student_list::display() const
{
student *t = m_head;
if (!t)
std::cout << "List is Empty!" << std::endl;
else
{
do
{
std::cout << "******Student******" << std::endl;
t->display();
t = t->next();
}
while (t);
}
}
Main.cpp:
#include "Student.h"
#include "StudentList.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <limits>
#include <cstdlib>
int read_number()
{
int value;
while (!(std::cin >> value))
{
std::cout << "Must be a number, try again: ";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
return value;
}
int display_menu()
{
int option;
std::cout << std::endl << std::endl;
std::cout << "1. Display List" << std::endl;
std::cout << "2. Add a student" << std::endl;
std::cout << "3. Delete first student" << std::endl;
std::cout << "4. Search by Last Name" << std::endl;
std::cout << "5. Delete student by index" << std::endl;
std::cout << "6. Exit" << std::endl << std::endl;
std::cout << "Choice: ";
do
{
option = read_number();
if ((option >= 1) && (option <= 6))
break;
std::cout << "Must be 1..6, try again: ";
}
while (true);
return (option != 6) ? option : -1;
}
int main()
{
student_list students;
std::ifstream infile("lab8d.txt");
if (infile.is_open())
{
student *cp = NULL;
std::string ln, fn;
float s;
while (infile >> fn >> ln >> s)
cp = students.insert(fn, ln, s, cp);
infile.close();
}
// loop to give the user some options
int option; // the number of menu item the user selects
while ((option = display_menu()) != -1)
{
switch (option)
{
case 1:
{
students.display();
break;
}
case 2:
{
// prompt for student info
std::string info;
std::cout << "Enter new student's first name, last name, and score: ";
std::string ln, fn;
float s;
if (std::cin >> fn >> ln >> s)
students.insert(fn, ln, s);
break;
}
case 3:
{
if (!students.remove(0))
std::cout << "List is empty" << std::endl;
break;
}
case 4:
{
// prompt for last name to search for
std::string ln;
std::cout << "Enter Last Name of the Student: ";
if (std::cin >> ln)
{
student *f = students.search_last_name(ln);
if (f)
f->display(true);
else
std::cout << "Name not found in List" << std::endl;
}
break;
}
case 5:
{
std::cout << "Enter the index of the Student to Delete: " << std::endl;
int idx = read_number();
if (!students.remove(idx))
std::cout << "Index not found in List" << std::endl;
break;
}
}
}
std::system("pause");
return 0;
}
That being said, you really should be using the std::list container instead, eg:
Student.h:
#include <string>
class student_list;
class student
{
public:
student();
student(const std::string &fn, const std::string &ln, float s);
void firstName(const std::string &fn);
std::string firstName() const;
void lastName(const std::string &ln);
std::string lastName() const;
void score(float s);
float score() const;
std::string pass_or_fail() const;
void display(bool showPassOrFail = false) const;
friend class student_list;
protected: // protected can be inherited
std::string m_fn;
std::string m_ln;
float m_score;
};
Student.cpp:
#include "Student.h"
#include <iostream>
student::student()
: m_score(0)
{
}
student::student(const std::string &fn, const std::string &ln, float s)
: m_fn(fn), m_ln(ln), m_score(s)
{
}
void student::firstName(const std::string &fn)
{
m_fn = fn;
}
std::string student::firstName() const
{
return m_fn;
}
void student::lastName(const std::string &ln)
{
m_ln = ln;
}
std::string student::lastName() const
{
return m_ln;
}
void student::score(float s)
{
m_score = s;
}
float student::score() const
{
return m_score;
}
std::string student::pass_or_fail() const
{
if (m_score >= 60)
return "PASSED";
else
return "FAILED";
}
void student::display(bool showPassOrFail) const
{
std::cout << lastName() << std::endl;
std::cout << firstName() << std::endl;
std::cout << score() << std::endl;
if (showPassOrFail)
std::cout << pass_or_fail() << std::endl;
}
Main.cpp:
#include "Student.h"
#include <list>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <limits>
#include <algorithm>
#include <cstdlib>
int read_number()
{
int value;
while (!(std::cin >> value))
{
std::cout << "Must be a number, try again: ";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
return value;
}
int display_menu()
{
int option;
std::cout << std::endl << std::endl;
std::cout << "1. Display List" << std::endl;
std::cout << "2. Add a student" << std::endl;
std::cout << "3. Delete first student" << std::endl;
std::cout << "4. Search by Last Name" << std::endl;
std::cout << "5. Delete student by index" << std::endl;
std::cout << "6. Exit" << std::endl << std::endl;
std::cout << "Choice: ";
do
{
option = read_number();
if ((option >= 1) && (option <= 6))
break;
std::cout << "Must be 1..6, try again: ";
}
while (true);
return (option != 6) ? option : -1;
}
int main()
{
std::list<student> students;
std::ifstream infile("lab8d.txt");
if (infile.is_open())
{
std::string ln, fn;
float s;
while (infile >> fn >> ln >> s)
students.push_back(student(fn, ln, s));
infile.close();
}
// loop to give the user some options
int option; // the number of menu item the user selects
while ((option = display_menu()) != -1)
{
switch (option)
{
case 1:
{
if (students.empty())
std::cout << "List is Empty!" << std::endl;
else
{
for(const auto &s : students)
{
std::cout << "******Student******" << std::endl;
s.display();
}
}
break;
}
case 2:
{
// prompt for student info
std::string info;
std::cout << "Enter new student's first name, last name, and score: ";
std::string ln, fn;
float s;
if (std::cin >> fn >> ln >> s)
students.push_back(student(fn, ln, s));
break;
}
case 3:
{
if (students.empty())
std::cout << "List is empty" << std::endl;
else
students.erase(students.begin());
break;
}
case 4:
{
// prompt for last name to search for
std::string ln;
std::cout << "Enter Last Name of the Student: ";
if (std::cin >> ln)
{
auto f = std::find(students.begin(), students.end(),
[&](const student &s){ return (s.lastName() == ln); }
);
if (f != students.end())
f->display(true);
else
std::cout << "Name not found in List" << std::endl;
}
break;
}
case 5:
{
std::cout << "Enter the index of the Student to Delete: " << std::endl;
int idx = read_number();
if ((idx < 0) || (idx >= students.size()))
std::cout << "Index not found in List" << std::endl;
else
students.erase(std::next(students.begin(), idx));
break;
}
}
}
std::system("pause");
return 0;
}
I'm writing a modified version of 20 Questions for my CS2 class and I am having one heck of a time trying to figure out why I'm getting the error.
IC2664 cannot convert argument 1 from 'const char ' to 'Node'
Anyways, any assistance would be appreciated.
#include "LetMeGuess.h"
#include<iostream>
#include<memory>
#include<string>
#include<fstream>
#include<vector>
struct LetMeGuess::Node {
Node(std::string data) : data(data), no(nullptr), yes(nullptr) {};
std::string data;
std::shared_ptr<Node>no;
std::shared_ptr<Node>yes;
};
void LetMeGuess::letMeGuess() {
std::cout << "***Let Me Guess!***\nLoading questionArchive.txt ..." << std::endl;
readInFile();
std::cout << "Done!" << std::endl;
askQuestions();
std::cout << "Saving questionArchive.txt ..." << std::endl;
readOutFile(root);
std::cout << "Done! Goodbye!" << std::endl;
}
void LetMeGuess::readInFile() {
root = std::shared_ptr<Node>("Is it an animal?");
root->no = std::shared_ptr<Node>("Toaster");
root->yes = std::shared_ptr<Node>("Elephant");
//std::vector<Node> myStack;
//std::shared_ptr<Node> newNode;
//std::string nextInfo;
//std::string nextID;
//fin.open("questionArchive.txt");
//while (!fin.eof) {
// fin >> nextID;
// if (nextID == "A") {
// fin >> nextInfo;
// Node newNode(nextInfo);
// myStack.push_back(newNode);
// }
// else {
// fin >> nextInfo;
// Node newNode = Node(nextInfo);
// Node newNode->yes = myStack.back();
// }
//}
}
std::string LetMeGuess::readOutFile(std::shared_ptr<Node>curr) {
curr = root;
std::string outString;
fout.open("questionArchive.txt");
if (!curr) return outString;
outString += readOutFile(curr->no);
outString += readOutFile(curr->yes);
if (curr->no == nullptr || curr->yes == nullptr) {
outString += "A ";
}
else {
outString += "Q ";
}
outString += curr->data;
outString += "/n";
fout << outString;
return outString;
}
bool LetMeGuess::stillAsking(std::shared_ptr<Node> temp){
if (temp->no == nullptr || temp->yes == nullptr) return false;
else return true;
}
bool LetMeGuess::playAgain(char ans) {
switch (ans) {
case'Y':
case'y':
return true;
case'N':
case'n':
default:
std::cout << "y/n not selected, starting a new game anyways." << std::endl;
return true;
}
}
void LetMeGuess::insertNewQuestion(std::shared_ptr<Node>& curr, std::string newQuest, std::string objThought) {
curr->no = std::make_shared<Node>(curr->data);
curr->yes = std::make_shared<Node>(objThought);
curr->data = newQuest;
}
void LetMeGuess::askQuestions() {
std::shared_ptr<Node> current = root;
char answer;
char plyAgn = 'y';
std::string thoughtObject;
std::string newQuestion;
while (playAgain(plyAgn)) {
while (stillAsking(current)) {
std::cout << current->data;
std::cin >> answer;
switch (answer) {
case'y':
case'Y':
current = current->yes;
break;
case'n':
case'N':
current = current->no;
break;
default:
std::cout << "Please enter y/n." << std::endl;
break;
}
}
std::cout << "Let me guess, you're thinking of a(n)" << current->data << "?" << std::endl;
std::cin >> answer;
switch (answer) {
case 'y':
case'Y':
std::cout << "I win!" << std::endl;
break;
case'n':
case'N':
std::cout << "What where you thinking of?" << std::endl;
std::cin >> thoughtObject;
std::cout << "What could I have asked to know you were thinking of a(n) " + thoughtObject + " and not a(n) " + current->data + "?" << std::endl;
std::cin >> newQuestion;
insertNewQuestion(current, newQuestion, thoughtObject);
break;
default:
std::cout << "Please enter y/n." << std::endl;
break;
}
std::cout << "Would you like to play again? (y/n)" << std::endl;
std::cin >> plyAgn;
}
}
root = std::shared_ptr<Node>("Is it an animal?");
root->no = std::shared_ptr<Node>("Toaster");
root->yes = std::shared_ptr<Node>("Elephant");
is incorrect way of creating shared_ptr .
root = std::make_shared<Node>("Is it an animal?");
root->no = std::make_shared<Node>("Toaster");
root->yes = std::make_shared<Node>("Elephant");
is the correct way of constructing shared_ptr
I got strange program behaviour and crashing.
I created class 'List', with array of pointers to objects of class 'Student'. I observe that I succesfully called 'Student' object in 'List' constructor. But I'm unable to call 'Student' object from any other 'List' methods.
I even checked the same line for testing inside 'List' constructor and 'push' method, resulting in program crash.
Here is testing line: cout << (studentBox[numb] -> getRef()) << endl;
Here is the problematic part of code:
#include <iostream>
using namespace std;
class Student
{
private:
int referenceNumb;
int markNumb;
public:
Student();
Student(int, int);
~Student();
int getRef();
int getMark();
};
class List
{
private:
int numb;
Student* studentBox[1000];
public:
List();
~List();
void push(int, int);
int getAVG();
};
int main()
{
List* base = NULL;
int x, y;
char mod;
do
{
cout << "Waiting for orders." << endl;
cout << "1 - Quit," << endl;
cout << "2 - Add new student," << endl;
cout << "3 - Calculate average mark," << endl;
cout << "0 - Create new list." << endl;
cin >> mod;
switch(mod)
{
case '0': base = new List(); break;
case '1': cout << "Bye."; break;
case '2':
if(base != NULL)
{
cout << "Specify student's reference number: "; cin >> x;
cout << "Specify student's mark: "; cin >> y;
base->push(x, y);
}
else cout << "List does not exist!" << endl;
break;
case '3':
if(base != NULL)
{
cout << "Average mark is equal: " << base->getAVG();
}
else cout << "List does not exist!";
cout << endl;
break;
default: cout << "Correct command required!" << endl; break;
}
}
while(mod!='1');
return 0;
}
Student::Student()
{
referenceNumb = NULL;
markNumb = NULL;
}
Student::Student(int r, int m)
{
referenceNumb = r;
markNumb = m;
}
Student::~Student()
{
referenceNumb = NULL;
markNumb = NULL;
cout << "pusto." << endl;
}
int Student::getRef()
{
return referenceNumb;
}
int Student::getMark()
{
return markNumb;
}
List::List()
{
int numb = 0;
studentBox[numb] = new Student();
cout << (studentBox[numb] -> getRef()) << endl;
}
List::~List()
{
}
void List::push(int x, int y)
{
cout << (studentBox[numb] -> getRef()) << endl;
if(studentBox[numb] != NULL)
{
studentBox[numb] = new Student();
cout << (studentBox[numb] -> getRef()) << endl;
}
else cout << "Hujnia" << endl;
}
int List::getAVG()
{
int temp = 0;
for(int i=0; i<numb; i++)
{
temp += studentBox[i]->getMark();
}
return (temp / numb);
}
There are a couple of major problems that I see. The first is that the numb member of the List isn't initialized.
List::List()
{
int numb = 0; // this creates a new local variable called numb, it doesn't
// initialize the numb member.
studentBox[numb] = new Student();
cout << (studentBox[numb] -> getRef()) << endl;
}
Do this instead:
List::List()
: numb(0) // initialize the numb member to zero.
{
studentBox[numb] = new Student();
cout << (studentBox[numb] -> getRef()) << endl;
}
Another problem is that numb appears to be meant to indicate the size of the list, but it is never changed when a new student is added.