I am working on a program through Xcode, it is supposed to read a file and perform various functions:
displayMenu,
doDisplay,
doView,
doAdd,
doEdit,
doDelete.
I have gotten it all to work except the do edit and do delete functions, and I can't find anything online that helps with my particular situation.
The user is supposed to pick the course they want to edit, and be able to edit the term, year, start date, end date, etc.
Thank you in advance.
Here is my code attached.
Here are instructions if you are curious:
Course Menu
=====================
d - Display list of courses
v - View course details
a - Add a course
e - Edit a course
d - Delete a course
x - Exit program
Requirements
Given a comma-delimited text file named courses.csv Download
courses.csv(click to download) that stores the starting data for the
program.
A course is an organized presentation about a particular subject that includes Term, Year, Start Date, End Date, Course Name, Class ID, Section, Meeting Days, Location (online, hybrid, or on-campus), Meeting Information, Instructor, Units.
For the view, edit, and delete commands, display an error message if
the user selects an invalid course.
Define a data structure to store the data for each course.
When you start the program, it should read the contacts from the
comma-delimited text file and store them in a vector of courses.
When reading data from the text file, you can read the line and
separate the field by an all text up to the next comma (ex. getline()
function).
When you add, edit or delete a contact, the change should be saved to
the text file immediately. That way, no changes are lost, even if the
program crashes later.
For demonstration, you need to be able to view/add/edit/delete at
least 3 courses listed
Here is my code: https://pastebin.com/HkEE9HBD
////myApp.cpp
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
#include "course.h"
#include "utils.h"
using namespace std;
char menu();
int main() {
vector<courseType> list;
readData(list);
char ch = 'x';
do {
cout << endl;
ch = menu();
switch (ch) {
case 'l':
// function handler
doDisplay(list);
break;
case 'v':
doView(list);
break;
case 'a':
doAdd(list);
break;
case 'e':
doEdit(list);
break;
case 'd':
doDelete(list);
break;
default:
cout << "Please enter valid choice" << endl;
}
} while (ch != 'x');
cout << "Exit the program" << endl;
return 0; // exit the program successfully
}
/**
* Display application menu
*/
char menu() {
cout << "Course Menu" << endl;
cout << "=====================" << endl;
cout << "l - Display list of courses" << endl;
cout << "v - View course details" << endl;
cout << "a - Add a course" << endl;
cout << "e - Edit a course" << endl;
cout << "d - Delete a course" << endl;
cout << "x - Exit program" << endl << endl;
cout << "Enter choice: ";
char ch;
cin >> ch;
cout << endl;
return ch;
}
//courseImp.cpp
#include <string>
#include "course.h"
#include <iostream>
using namespace std;
courseType::courseType() {
term = "";
year = 0.0;
startDate = "";
endDate = "";
courseName = "";
section = "";
classID = 0.0;
meetingDays = "";
location = "";
meetingInfo = "";
instructor = "";
units = 0.0;
}
courseType::~courseType() {
}
//List of Acessor and Getter Methods For Each Variable
void courseType::setTerm(string term) {
this ->term = term;;
}
string courseType::getTerm() {
return term;
}
void courseType::setYear(string temp) {
this ->temp = temp;
}
string courseType::getYear() {
return temp;
}
void courseType::setStart(string startDate) {
this ->startDate = startDate;
}
string courseType::getStart() {
return startDate;
}
void courseType::setEnd(string endDate) {
this ->endDate = endDate;
}
string courseType::getEnd() {
return endDate;
}
void courseType::setName(string courseName) {
this ->courseName = courseName;
}
string courseType::getName() {
return courseName;
}
void courseType::setSection(string section) {
this ->section = section;
}
string courseType::getSection() {
return section;
}
void courseType::setID(string tempC) {
this->tempC = tempC;
}
string courseType::getID() {
return tempC;
}
void courseType::setDays(string meetingDays) {
this ->meetingDays = meetingDays;;
}
string courseType::getDays() {
return meetingDays;
}
void courseType::setLocation(string location) {
this ->location = location;
}
string courseType::getLocation() {
return location;
}
void courseType::setInfo(string meetingInfo) {
this ->meetingInfo = meetingInfo;
}
string courseType::getInfo() {
return meetingInfo;
}
void courseType::setInstructor(string instructor) {
this ->instructor = instructor;
}
string courseType::getInstructor() {
return instructor;
}
void courseType::setUnits(string tempU) {
this ->tempU = tempU;
}
string courseType::getUnits() {
return tempU;
}
//utils.cpp
#include <iostream>
#include <iomanip>
#include "utils.h"
#include "course.h"
#include <cstdlib>
#include <iostream>
#include <utility>
#include <string>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
//Function Dislays list of Courses
void doDisplay(vector<courseType>& list) {
cout << left << setw(10) << "Course List" << endl;
cout << "==============================" << endl;
for(int i = 0; i < list.size(); i++){
cout << left << setw(10) << list[i].getName() << "" << endl << endl;
}
}
//Function views individual course
void doView(vector<courseType>& list) {
int chv = 0;
for(int i = 0; i < list.size(); i++){
cout << i+1 << ". " << list[i].getName() << "" << endl << endl;
}
cout << "Please choose a course you want to view: ";
cin >> chv;
cout << endl;
if(chv<list.size()+1)
{
cout << left << setw(10) << "Term" << setw(10) << "Year"
<< setw(15) << "Start Date" << setw(15) << "End Date"
<< setw(35) <<"Course Name" << setw(15) << "Section"
<< setw(12) << "Class ID" << setw(17) << "Meeting Days"
<< setw(15) << "Location" << setw(20) << "Meeting Info"
<< setw(15) << "Instructor" << "Units" << endl;
cout << "=============================================================================================";
cout << "=============================================================================================" << endl;
chv=chv-1;
cout << left << setw(10) << list[chv].getTerm() << "" << setw(10) << list[chv].getYear() <<
"" << setw(15) << list[chv].getStart() << "" << setw(15) << list[chv].getEnd() << "" <<
setw(35) << list[chv].getName() << "" << setw(15) << list[chv].getSection() << "" <<
setw(15) << list[chv].getID() << "" << setw(15) << list[chv].getDays() << "" <<
setw(17) << list[chv].getLocation() << "" << setw(20) << list[chv].getInfo() << "" <<
setw(15) << list[chv].getInstructor() << "" << setw(10) << list[chv].getUnits() << "" << endl;
}
}
//Function Adds Courses
void doAdd(vector<courseType>& list) {
char choice;
char delim = ',';
string term = "";
float year = 0.0;
string start = "";
string end = "";
string name = " ";
string section = "";
float id = 0.0;
string days = "";
string location = "";
string info = "";
string instructor = "";
float units = 0.0;
ofstream outMyStream (FILE_NAME, ios::app);
do {
cout << "Enter term: " ;
cin.ignore();
getline(cin, term);
cout << "Enter year: ";
cin >> year;
cin.ignore();
cout << "Enter start date: ";
getline(cin, start);
cout << "Enter end date: ";
getline(cin, end);
cout << "Enter course name: ";
getline(cin, name);
cout << "Enter course section: ";
getline(cin, section);
cout << "Enter course ID: ";
cin >> id;
cin.ignore();
cout << "Enter meeting Days : ";
getline(cin, days);
cout << "Enter meeting location: ";
getline(cin, location);
cout << "Enter meeting information: ";
getline(cin, info);
cout << "Enter instructor name: ";
getline(cin, instructor);
cout << "Enter units: ";
cin >> units;
cin.ignore();
outMyStream << term << delim << year << delim << start << delim << end << delim << name << delim << section << delim
<< id << delim << days << delim << location << delim << info << delim << instructor << delim << units << endl;
cout << "\nEnter another Record? (Y/N) ";
cin >> choice;
if (choice != 'Y' and choice != 'y' and choice != 'N' and choice != 'n') // if needed add input
cout << choice << " is not a valid option. Try agian" << endl;
}while (choice != 'N' && choice != 'n');
{
outMyStream.close();
}
}
//Function Edits Courses
void doEdit(vector<courseType>& list) {
}
//Function Deletes Courses
void doDelete(vector<courseType>& list) {
}
//Function Reads Data from "courses.csv"
void readData(vector<courseType>& list) {
ifstream inFile;
fstream fin;
inFile.open(FILE_NAME);
string line;
while (getline(inFile, line)) {
string term;
float year;
string startDate;
string endDate;
string courseName;
string section;
float classID;
string meetingDays;
string location;
string meetingInfo;
string instructor;
float units;
string temp;
string tempU;
string tempC;
stringstream ss(line);
getline(ss, term, ',');
getline(ss, temp, ',');
year = atoi(temp.c_str());
getline(ss, startDate, ',');
getline(ss, endDate, ',');
getline(ss, courseName, ',');
getline(ss, section, ',');
getline(ss,tempC,',');
classID = atoi(tempC.c_str());
getline(ss, meetingDays, ',');
getline(ss, location, ',');
getline(ss, meetingInfo, ',');
getline(ss, instructor, ',');
getline(ss,tempU,',');
units = atoi(tempU.c_str());
courseType c;
c.setTerm(term);
c.setYear(temp);
c.setStart(startDate);
c.setEnd(endDate);
c.setName(courseName);
c.setSection(section);
c.setID(tempC);
c.setDays(meetingDays);
c.setLocation(location);
c.setInfo(meetingInfo);
c.setInstructor(instructor);
c.setUnits(tempU);
list.push_back(c);
}
inFile.close();
}
//course.h
#pragma once
#include <string>
#include <sstream>
using namespace std;
class courseType {
public:
// mutator methods - set
void setTerm(string term);
void setYear(string temp);
void setStart(string startDate);
void setEnd(string endDate);
void setName(string courseName);
void setSection(string section);
void setID(string tempC);
void setDays(string meetingDays);
void setLocation(string location);
void setInstructor(string instructor);
void setInfo(string meetingInfo);
void setUnits(string tempU);
// ...
// accessor methods - get
string getTerm();
string getYear();
string getStart();
string getEnd();
string getName();
string getSection();
string getID();
string getDays();
string getLocation();
string getInstructor();
string getInfo();
string getUnits();
// ...
// Other member methods
// ...
courseType();
~courseType();
protected:
// tbd
private:
// data structures
string term;
float year;
string startDate;
string endDate;
string courseName;
string section;
float classID;
string meetingDays;
string location;
string meetingInfo;
string instructor;
float units;
string temp;
string tempU;
string tempC;
};
//utils.h
#pragma once
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include "course.h"
using namespace std;
const string FILE_NAME = "courses.csv";
// Prototype functions...
void doDisplay(vector<courseType>& list);
void doView(vector<courseType>& list);
void doAdd(vector<courseType>& list);
void doEdit(vector<courseType>& list);
void doDelete(vector<courseType>& list);
void readData(vector<courseType>& list);
//courses.csv
Spring,2022,1/24/2022,5/20/2022,Discrete Structures,CS-113-02,085689,T TH,On-Campus,Newark,Pham,3
Spring,2022,1/24/2022,5/20/2022,Programming W/ Data Structures,CS-124-02,084371,M W,On-Campus,Zoom,Pham,3
Spring,2022,1/24/2022,5/20/2022,Programming W/ Data Structures,CS-124-03,085698,T TH,Online,Newark,Pham,3
Spring,2022,1/24/2022,5/20/2022,JavaScript for Web Development,CS-175-01,084377,M,Online,Zoom,J. Pham,4
Spring,2022,1/24/2022,5/20/2022,Beginner Java,CS-125-05,089434,TH,Online,Zoom,Gao,3
Ah, college professors... Store things in csv files but act like it's a database.
What I would do is design a set of classes that mirror your data. So you'd have a class called Course (for instance). And you'd have another called Curriculum, perhaps, and it would store a std::vector of Courses.
You would then need a readFromCSV and writeToCSV pair of methods. You would want more methods for the various actions you have to perform, and any methods that modify data should then call writeToCSV automatically.
Does that make sense?
You can build it by first just writing the read and write methods and just make sure your output file looks identical to your input file.
Then start implementing the data update methods, one at a time.
Not too bad.
Related
I am trying to add a customer to my vector and when I run my program the copy constructor is called. I am doing an assignment where I need a vector of customers and have to be able to add customers, display customers, find customers and load/store the data. Have I created the vector wrong? I am only new to c++ and really unsure about vectors.
Code from Main.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include "Customer.h"
using namespace std;
void OutputFileStream();
void parseLine(const string& str);
void InputFileStream();
void save(vector<Customer> customers);
void load(vector<Customer>& customers);
void addCustomer(vector<Customer>& vect);
void displayAll(vector<Customer>& customers);
//void printActions();
vector<Customer> customers;
void OutputFileStream()
{
cout << "Creating and writing to file: Customer.txt" << endl;
ofstream outStream("customers.txt"); // write mode (overwrites existing data)
if (outStream.good())
{
int customerID = 150033;
outStream << "This is a line of text.\n";
outStream << "This is another line of text.\n";
outStream << "This is a line of text.\n";
int numOfPurchases = 4;
int purchases = 0;
outStream << customerID << "Mr" << "Jack" << "New" << numOfPurchases << purchases << endl;
//int *purchases = customers[0].getPurchases();
outStream.close(); // close file
cout << "File written.\n" << endl;
}
else
cout << "Unable to open file";
}
void parseLine(const string& str) {
stringstream strStream(str); //create string stream from the string
// int customerID;
string title;
string name;
string type;
//int numOfPurchases;
//int purchases;
string s;
int customerID = 150033;
getline(strStream, s, ';');
customerID = stoi(s);
getline(strStream, title, ';');
getline(strStream, name, ';');
getline(strStream, type, ';');
int numOfPurchases = 4;
getline(strStream, s, ';');
numOfPurchases = stoi(s);
int purchases = 0;
getline(strStream, s, ';');
purchases = stoi(s);
int* purchasesArray = new int[3];
purchasesArray[0] = (purchases & (255 << 16)) >> 16;
purchasesArray[1] = (purchases & (255 << 8)) >> 8;
purchasesArray[2] = purchases & 255;
for (int i = 0; i < 3; i++)
{
cout << purchasesArray[i];
}
cout << " CustomerID: " << customerID << "Title:" << title << " Name: " << name << " Type:" << type << " Number of Purchases: " << numOfPurchases << "Purchases: " << purchases << endl;
}
void InputFileStream() {
cout << "Reading from a semi-colon delimited txt file" << endl;
string line;
ifstream inStream("customers.txt"); //opens file as an input file stream
if (inStream.good()) //if the file is opened successfully and not empty
{
while (getline(inStream, line)) //reads line until false return
{
parseLine(line);
}
inStream.close();
}
else
cout << "unable to open file or the file is empty!";
}
void save(vector<Customer> customers)
{
ofstream out("customers.txt");
if(out)
{
for (Customer& c : customers)
{
out << c.save();
}
out.flush();
out.close();
}
else
{
cout << "Error Writing to File" << endl;
}
}
void load(vector<Customer>& customers)
{
ifstream in("customers.txt");
if (in) {
string line;
while (!in.eof())
{
getline(in, line);
if (line != "")
{
Customer c;
c.parse(line);
customers.push_back(c);
}
}
}
}
void addCustomer(vector<Customer>& customers) {
Customer customer;
cin >> customer;
customers.push_back(customer);
}
void displayAll(vector<Customer>& customers)
{
cout << "\nvector contains:\n";
for (Customer c : customers)
cout << c.getCustomerID() << " " << c.getTitle() << c.getName() << c.getNumOfPurchases() << c.getPurchases() << c.getType() << endl;
cout << endl;; //same as calling customer
}
//
//int getCustomerByPurchaseNumber(int numOfPurchases) {
// vector<Customer> customers;
// int pos = -1;
// for (int i = 0; i < customers.size(); i++) {
// if (customers.at(i).getNumOfPurchases() == numOfPurchases) {
// return i;
// }
// }
// return pos;
//}
//
//void findCustomerByPurchaseNumber(vector<Customer>& customers) {
// vector<Customer> customers;
// int numOfPurchases;
// cout << "Please Enter Your Purchase Number:" << endl;
// cin >> numOfPurchases;
// int pos = customers.get(pos);
// getCustomerByPurchaseNumber(numOfPurchases);
// if (pos == -1) {
// cout << "Number of Purchase Not Found! " << endl;
// return customers;
// }
// else {
// cout << "Number Of Purchase Found! " << endl;
//
// return customers* = customers;
// }
//
//}
int main()
{
vector<Customer> customers;
Customer c1 = { 150031, "Mr", "John", 5, 333,362,341, "New" };
customers.push_back(c1);
//InputFileStream();
/* Customer customer;
customer.setCustomerID(150032);
customer.setTitle("Mr");
customer.setName("Joey");
customer.setNumOfPurchases(3);
customer.setPurchases(366, 352, 334);
customer.setType("New");
cout << customer.getCustomerID() << endl;
cout << customer.getTitle() << endl;
cout << customer.getName() << endl;
cout << customer.getNumOfPurchases() << endl;
cout << customer.getPurchases() << endl;
cout << customer.getType() << endl;
*/
return 0;
}
Code from Customer.cpp:
#include "Customer.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include<utility>
using namespace std;
//default constructor
Customer::Customer() {
}
//Full constructor
Customer::Customer(int customerID, string title, string name, int numOfPurchases, int purchase1, int purchase2, int purchase3, string type)
{
this->customerID = customerID;
this->title = title;
this->name = name;
this->numOfPurchases = numOfPurchases;
purchases = new int[3];
purchases[0] = purchase1;
purchases[1] = purchase2;
purchases[2] = purchase3;
this->type = type;
}
Customer::Customer(const Customer& source) //copy constructor
{
cout << "copy constructor called" << endl;
this->customerID = source.customerID;
this->title = source.title;
this->name = source.name;
this->numOfPurchases = source.numOfPurchases;
this->purchases = new int[3];
purchases[0] = source.purchases[0];
purchases[1] = source.purchases[1];
purchases[2] = source.purchases[2];
this->type = source.type;
}
//overloaded assignment operator=
Customer& Customer::operator= (Customer& otherCustomer)
{
cout << "Overloaded assignment operator= called" << endl;
//self-assignment guard
if (this == &otherCustomer)
return *this; //refernce to the same object
// copy data from the source (rhs) to this object (the destination)
name = otherCustomer.name;
//must make a new scores object to store a copy of the other student
if (purchases != nullptr)
delete[] purchases;
purchases = new int[3];
for (int i = 0; i < 3; i++) {
purchases[i] = otherCustomer.purchases[i];
}
//return this existing object so we can chain this operator
return *this;
}
string Customer::save()
{
stringstream out;
out << this->customerID << ";";
out << this->title << ";";
out << this->name << ";";
out << this->type << ";\n";
out << this->numOfPurchases << ";";
int* purchases = 0;
out.flush();
return out.str();
}
void Customer::parse(string line)
{
stringstream in(line);
string customerIDLine;
getline(in, customerIDLine, ';');
customerID = stoi(customerIDLine);
getline(in, title, ';');
getline(in, name, ';');
getline(in, type, ';');
string numOfPurchases;
getline(in, numOfPurchases, ';');
int s = stoi(numOfPurchases);
int* purchasesArray = new int[3];
purchasesArray[0] = (s & (255 << 16)) >> 16;
purchasesArray[1] = (s & (255 << 8)) >> 8;
purchasesArray[2] = s & 255;
}
void Customer::addCustomer(vector<Customer>& customers )
{
//after read data
int customerID;
cout << "Please Enter Customer ID: " << endl;
cin >> customerID;
string title;
cout << "Please Enter Title: " << endl;
getline(cin, title);
string name;
cout << "Please Enter Name: " << endl;
getline(cin, name);
string type;
cout << "Please Enter Type: " << endl;
getline(cin, type);
int numOfPurchases;
cout << "Please Enter Number of Purchases: " << endl;
cin >> numOfPurchases;
int purchase1;
cout << "Please Enter First Purchase: " << endl;
cin >> purchase1;
int purchase2;
cout << "Please Enter Second Purchase: " << endl;
cin >> purchase2;
int purchase3;
cout << "Please Enter Third Purchase: " << endl;
cin >> purchase3;
Customer c;
customers.push_back(c);
//Customer c();
}
Customer::~Customer() {
cout << "Destructor ~Customer called" << endl;
delete[] purchases;
}
// Overloaded insertion operator (Outputs Character object data as an output stream)
// Defined in header file as a "friend" function, as it is not a member function
//
ostream& operator<<(ostream& out, Customer& customer)
{
cout << "Customer details ( output by insertion operator<< )" << endl;
cout << "Customer ID: " << customer.customerID << endl;
cout << "Title: " << customer.title << endl;
cout << "Name: " << customer.name << endl;
cout << "Number of purchases: " << customer.numOfPurchases << endl;
cout << "Purchases: ";
for (int i = 0; i < 3; i++)
{
if (i > 0) cout << ",";
cout << customer.purchases[i];
}
cout << "Type: " << customer.type << endl;
return out;
}
istream& operator>> (istream& in, Customer& customer)
{
cout << "Enter Customer details ( using the extraction operator>> )" << endl;
cout << "Enter Customer ID: " << endl;
cin >> customer.customerID;
cout << "Enter Title: " << endl;
getline(cin, customer.title);
cout << "Enter Name: " << endl;
getline(cin, customer.name);
cout << "Enter Number of Purchases: ";
cin >> customer.numOfPurchases;
cout << "Enter Purchases: ";
cin >> customer.purchases[0];
cin >> customer.purchases[1];
cin >> customer.purchases[2];
cout << "Enter Type";
getline(cin, customer.type);
cout << endl;
return in;
}
int Customer::getCustomerID()
{
return customerID;
}
string Customer::getTitle()
{
return title;
}
string Customer::getName()
{
return name;
}
int Customer::getNumOfPurchases()
{
return numOfPurchases;
}
int* Customer::getPurchases()
{
return purchases;
}
string Customer::getType()
{
return type;
}
void Customer::setCustomerID(int customerID)
{
if (customerID < 1) {
cout << "Customer ID has to be equal to 1 or more" << endl; //Changed all the "throw invalid_argument" messages to cout as they were causing an issue with my main.cpp file and an abort message kept appearing every time I ran my main.cpp file.
}
this->customerID = customerID;
}
void Customer::setTitle(string title)
{
if (title.length() < 2) {
cout << "Title has to be more than or equal to 2 characters" << endl;
}
this->title = title;
}
void Customer::setName(string name)
{
if (name.length() < 4) {
cout << "Length of name should be more than or equal to 4 characters" << endl;
}
this->name = name;
}
//Got help ith this on stack overflow as I was using "&&" instead of using "||" for the if statement
void Customer::setNumOfPurchases(int numOfPurchases)
{
if(numOfPurchases <0 || numOfPurchases > 10000){
cout << "Number of purchases should be between 0 to 10000" << endl;
}
this->numOfPurchases = numOfPurchases;
}
void Customer::setPurchases(int purchase1, int purchase2, int purchase3)
{
if (purchase1 < 0 || purchase2 < 0 || purchase3 < 0) {
cout << "Purchases must be more than or equal to zero" << endl;
}
}
//Got help from stack overflow on comparing strings as I originally didnt use "type.compare"
void Customer::setType(string type) {
if (type.compare("New") !=0 || type.compare("Either") !=0) {
cout << "Type of purchase has to be New or Either" << endl;
}
}
Code from Customer.h:
#pragma once
#include<iostream>
using namespace std;
#include<string>
#include <vector>
class Customer
{
private:
int customerID;
string title;
string name;
int numOfPurchases;
int* purchases;
string type;
public:
Customer(); // default constructor
Customer(int customerID, string title, string name, int numOfPurchases, int purchase1, int purchase2, int purchase3, string type);
//copy overload assignment
Customer& operator=(Customer& otherCustomer);
Customer(const Customer& source);
string save();
void parse(string line);
void addCustomer(vector<Customer>& customers);
~Customer(); //destructor
//Getters and Setters
void setCustomerID(int customerID);
void setTitle(string title);
void setName(string name);
void setNumOfPurchases(int numOfPurchases);
void setPurchases(int purchase1, int purchase2, int purchase3);
void setType(string type);
int getCustomerID();
string getTitle();
string getName();
int getNumOfPurchases();
int* getPurchases();
string getType();
void printCustomer() {
cout << customerID << "," << title << "," << name << "," << numOfPurchases << "," << purchases << "," << type << endl;
}
friend std::ostream& operator<<(std::ostream& out, Customer& customer); // overloaded operator<<
friend istream& operator>> (istream& in, Customer& customer); // overloaded operator >>
};
Vectors hold objects. If you have an object outside of the vector there is no way to have that same object inside the vector. You can move from one instance to one in the vector (that will move the instances inner parts, but there are still two instances). push_back does make a copy of its parameter when it cannot be moved from.
As you have a constructor that takes all necessary parameters, you can use emplace_back to avoid the copy and construct the instance right in place in the vector:
customers.emplace_back( customerID, title, name, numOfPurchases, purchase1, purchase2, purchase3, type);
If you check reference on std::vector<T,Allocator>::push_back object can be added to vector either by being copied (option1) or being moved (option 2).
So you can create a move constructor for your customer class:
class_name ( class_name && );
And then call push_back using that move consturctor (option 2) on vector:
void push_back( T&& value );
The std::vector<Customer> holds the element by value so just using std::vector::push_back will copy your local object into the vector.
To mitigate this you could either implement move semantics and move the the Customer object like this:
#include <utility>
....
Customer c;
c.parse(line);
customers.push_back(std::move(c));
or construct the object in-place:
// Post c++17 you could use `push_back()` here as well as
// c++17 has mandatory copy elision.
customers.emplace_back(Customer{}); // or customers.emplace_back(); only
customers.back().parse(line);
Both solutions require c++11.
You could also store a reference/pointer and allocate the object on the heap.
std::vector<std::unique_ptr<Customer>> customerVector;
customer_vector.push_back(std::make_unique<Customer>());
// or customer_vector.push_back(std::make_shared<Customer>());
Or
std::vector<Customer*> customerVector;
// Beware for memory leaks, needs to be deleted.
// Basically never use code like this post c++11).
customer_vector.push_back(new Customer{});
So i set my array value as 100 and when i want to display my array,the others array with no value will also display. Any ways to remove it ? Thanks!
#include<iostream>
#include<iomanip>
#include<cstring>
#include<string>
#include<fstream>
#include<limits>
#include<sstream>
using namespace std;
char add();
char list();
struct Book //structure for the book
{
char title[50];
char author[50];
int price;
void display() {
cout << "Name:" << title << endl
<< "Author:" << author<< endl
<< "Price:" << price << endl << endl;
}
};
Book book[100];
void main()
{
int selection;
do {
cout << "Activity Selection: " << endl;
cout << "1. Add book" << endl;
cout << "2. List all books" << endl;
cout << "3. Search book" << endl;
cout << "4. Check total book purchased and total spent" << endl;
cout << "5. Quit" << endl;
cout << "Please enter your selection(1/2/3/4/5): ";
cin >> selection;
cin.ignore();
switch (selection)
{
case 1:
add();
break;
case 2:
list();
break;
case 3:
cout << "number 3" << endl;
break;
case 4:
cout << "number 4" << endl;
break;
default:
exit(1);
break;
}
} while (selection <= 4);
system("pause");
}
char add()
{
int i;
ofstream outFile;
outFile.open("Records.dat", ios::app);
if (!outFile.is_open())
{
cout << "Can’t open file.";
system("pause");
exit(1);
}
cout << "Please enter the book title:";
cin.getline(book[i].title, 51);
cout << "Please enter the author name of the book:";
cin.getline(book[i].author, 51);
cout << "Please enter the price of the book RM: ";
cin >> book[i].price;
cout << "\nThe book\""<< book[i].title <<"\"has been added to the system.\n" <<
endl;
outFile << book[i].title << "," << book[i].author << "," << book[i].price <<
endl;
outFile.close();
}
char list() //second solution but still doesnt work need some fixing here i think
{
int i;
string line, token;
ifstream inFile;
inFile.open("Records.dat", ios::in);
if (!inFile.is_open())
{
cout << "File could not open" << endl;
system("pause");
exit(1);
}
char data;
while (getline(inFile,line))
{
inFile.get(data);
if (!(data == 0));
cout << data;
}
cout << endl;
inFile.close();
}
when i debug something like this come out :
ss
this is the second solution i come out with but still does not work
char list()
{
int i , count = 0;
string line, token;
ifstream inFile;
inFile.open("Records.dat", ios::in);
if (!inFile.is_open())
{
cout << "File could not open" << endl;
system("pause");
exit(1);
}
char data;
while (getline(inFile, line))
{
stringstream ss(line);
getline(ss, token, ',');
stringstream(token) >> book[i].title;
getline(ss, token, ',');
stringstream(token) >> book[i].author;
getline(ss, token, ',');
stringstream(token) >> book[i].price;
i++;
}
cout << endl;
inFile.close();
for (int count = 0; count < i; count++)
book[i].display();
}
The problem is i dont really know how to display the array using the dat file and i successfully display it but theres error
You are reading the CSV as a text file and just printing it.
So, the solution is to make a record class, read it from stream, then check it whether it is empty or no.
#include <iostream>
#include <sstream>
using namespace std;
class Record {
private:
std::string title;
std::string shortTitle;
int number;
public:
Record(std::string title, std::string shortTitle, int number): title(title),
shortTitle(shortTitle),
number(number){
}
inline std::string getTitle() const { return title; }
inline std::string getShortTitle() const { return shortTitle; }
inline int getNumber() const { return number; }
};
// Make this function capable of handling any stream by making it template
// (anything that could be passed to a `getline` as a first parameter and have
// an operator >> overloaded that accepts an integer)
template<typename Stream>
Record readFromStream(Stream &str) {
std::string title;
std::string shortTitle;
int number;
std::string line;
// Read a line from the stream
getline(str, line);
// Make a new stream from that line
std::stringstream lineStream(line);
// Read until the comma
getline(lineStream, title, ',');
getline(lineStream, shortTitle, ',');
// The last one is an integer, simply read it
lineStream >> number;
return Record(title, shortTitle, number);
}
int main() {
Record rec = readFromStream(cin);
// Check for emptiness, if is NOT empty write it
if (rec.getTitle().size() && rec.getShortTitle().size()) {
cout << rec.getTitle() << "\n";
cout << rec.getShortTitle() << "\n";
cout << rec.getNumber() << "\n";
}
return 0;
}
Okay, so I have a parent class called employee and 3 subclass called manager,researcher and engineer. I made a vector and want to list them. this is the how I process the making.
vector <Employee*,Manager*> EmployeeDB;
Employee *temp;
temp = new Manager(first, last, salary, meetings, vacations);
EmployeeDB.push_back(temp);
I have no problem in making the vector, my concern is listing the info. all 3 subclasses have firstname, lastname and salary but they're difference is that they have different data members which is unique, example the Manager has the int value vacation and the Engineer has the int value experience so on and so forth.
Employee.h:
#include <iostream>
#include <string>
using namespace std;
#ifndef EMPLOYEE_h
#define EMPLOYEE_h
class Employee
{
public:
Employee();
Employee(string firstname, string lastname, int salary);
string getFname();
string getLname();
int getSalary();
virtual void getInfo();
private:
string mFirstName;
string mLastName;
int mSalary;
};
#endif
Employee.cpp:
#include "Employee.h"
#include <iostream>
#include <string>
using namespace std;
Employee::Employee()
{
mFirstName = "";
mLastName = "";
mSalary = 0;
}
Employee::Employee(string firstname, string lastname, int salary)
{
mFirstName = firstname;
mLastName = lastname;
mSalary = salary;
}
string Employee::getFname()
{
return mFirstName;
}
string Employee::getLname()
{
return mLastName;
}
int Employee::getSalary()
{
return mSalary;
}
void Employee::getInfo()
{
cout << "Employee First Name: " << mFirstName << endl;
cout << "Employee Last Name: " << mLastName << endl;
cout << "Employee Salary: " << mSalary << endl;
}
Main:
#include <vector>
#include <iostream>
#include <string>
#include "Employee.h"
#include "Engineer.h"
#include "Manager.h"
#include "Researcher.h"
using namespace std;
vector <Employee*> EmployeeDB;
Employee *temp;
void add()
{
int emp, salary, vacations, meetings, exp, c;
string first, last, type, school, topic;
bool skills;
do
{
system("cls");
cout << "===========================================" << endl;
cout << " Add Employee " << endl;
cout << "===========================================" << endl;
cout << "[1] Manager." << endl;
cout << "[2] Engineer." << endl;
cout << "[3] Researcher." << endl;
cout << "Input choice: ";
cin >> emp;
system("cls");
} while (emp <= 0 || emp > 3);
cout << "===========================================" << endl;
cout << " Employee Info " << endl;
cout << "===========================================" << endl;
cout << "Employee First name: ";
cin >> first;
cout << "Employee Last name: ";
cin >> last;
cout << "Employee Salary: ";
cin >> salary;
switch (emp)
{
case 1:
cout << "Employee numbers of meetings: ";
cin >> meetings;
cout << "Employee numbers of vacations: ";
cin >> vacations;
temp = new Manager(first, last, salary, meetings,vacations);
EmployeeDB.push_back(temp);
delete temp;
break;
case 2:
cout << endl;
cout << "[1]YES [2]NO" << endl;
cout << "Employee C++ Skills: ";
cin >> c;
if (c == 1)
{
skills = true;
}
else
{
skills = false;
}
cout << "Employee Years of exp: ";
cin >> exp;
cout << "(e.g., Mechanical, Electric, Software.)" << endl;
cout << "Employee Engineer type: ";
cin >> type;
temp = new Engineer(first, last, salary, skills, exp, type);
EmployeeDB.push_back(temp);
delete temp;
break;
case 3:
cout << "Employee School where he/she got his/her PhD: ";
cin >> school;
cout << "Employee Thesis Topic: ";
cin >> topic;
temp = new Researcher(first, last, salary, school, topic);
EmployeeDB.push_back(temp);
delete temp;
break;
}
}
void del()
{
}
void view()
{
for (int x = 0; x < (EmployeeDB.size()); x++)
{
cout << EmployeeDB[x]->getInfo();
}
}
void startup()
{
cout << "===========================================" << endl;
cout << " Employee Database " << endl;
cout << "===========================================" << endl;
cout << "[1] Add Employee." << endl;
cout << "[2] Delete Employee." << endl;
cout << "[3] List Employees." << endl;
cout << "[4] Exit." << endl;
cout << "Please Enter Your Choice: ";
}
int main(int argc, char** argv)
{
bool flag = true;
int choice;
do {
do
{
system("cls");
system("pause>nul");
startup();
cin >> choice;
} while (choice < 0 || choice >4);
switch (choice)
{
case 1:
add();
break;
case 2:
del();
break;
case 3:
view();
break;
case 4:
flag = false;
system("EXIT");
break;
}
} while (flag == true);
return 0;
system("pause>nul");
}
I am getting error on the view() function.
It says no operator<< matches these operands
binary '<<': no operator found which takes a right hand operand of type void etc etc.
The problem is that the getInfo has return type void and you are trying to put that return value into cout.
It's important to understand that the code std::cout << val actually calls the function operator<<(ostream& out, const objectType& val) where objectType is the type of 'val'.
In your case the type is void, and there is simply no implementation of operator<< that takes void as a type. hence the error "no operator found which takes a right hand operand of type void...".
In order to fix your issue you have a few options:
Change view() to be
for (...)
{
EmployeeDB[x]->getInfo();
}
Change getInfo() to return a string the info as you'd like:
std::string getInfo()
{
std::string info;
info =...
return info;
}
Create an operator<< for Employee and change view to call it:
view()
{
for (...)
{
std::cout << EmployeeDB[x];
}
}
Hello I am having issues with a final project. The objective is to have the user create a form that allows a user to view data, edit data, add data, and save their password data in an encoded format. The program starts with an input file made by the user. The delimiter is ';', and the first char is a "code", then the, site, username, password, and notes follow.
I am very new to vectors, and I am not allowed to use a 2d array, or map.
Thank you for your time.
#include <iomanip>
#include <cmath>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
const int MAX_SIZE = 30;
const int BUFFER_SIZE = 200;
struct dataRow {
string site, user, pass, notes;
string code;
};
string inFileName; //name of inputfile
string outFileName;
ifstream pathStream;
ofstream outFile;
char inputChar;
int extPosition(1), count = 0,lineNum;
void displayVector(vector<dataRow> inputData);
void viewLineData(vector<dataRow> inputData, int lineNum);
void addNewRow(vector<dataRow> inputData,int& lastRowNum, string site, string user, string pass, string notes);
void editLineData(vector<dataRow> inputData, int& lineNum, string site, string user, string pass, string notes);
void warning();
void cleanBuffer();
bool displayMenu();
int exit();
dataRow descripLine;
int main()
{
vector<dataRow> inputData;
string rowDescripin,userin,passin,notesin,sitein;
string codein,errorMsg;
int lastRow;
//add a .txt extension to the file if the user didn't provide an extension
if (inFileName.size() > 4)
// If there's a valid extension, it will be in the last 4 positions of the string; Adjust by 1 for 0 offset
extPosition = inFileName.size() - 4;
int ext = inFileName.find_last_of(".txt");
if (!(inFileName.find_last_of(".") == extPosition))
{
inFileName += ".txt";
}
cout << "\nPlease enter the filename of input file: ";
cin >> inFileName;
pathStream.open(inFileName.c_str());
if (pathStream.fail())
{
cerr << inFileName << " failed to open.\n";
system("pause");
exit(1);
}
else
{
cout << "startup success" << endl;
}
getline(pathStream, codein, ';');
descripLine.code = codein;
while (!pathStream.eof())
{
getline(pathStream, sitein, ';');
descripLine.site = sitein;
getline(pathStream, userin, ';');
descripLine.user = userin;
getline(pathStream, passin, ';');
descripLine.pass = passin;
getline(pathStream, notesin, ';');
descripLine.notes = notesin;
inputData.push_back(descripLine);
}
displayVector(inputData);
displayMenu();
while (cin){
cin >> inputChar;
inputChar = toupper(inputChar);
//Adjust calculations based on inputCHar
if (inputChar == 'D') // Display line descriptions
{
displayVector(inputData);
}
else if (inputChar == 'V') //View line data
{
cout << "Enter line number you wish to view: ";
cin >> lineNum;
viewLineData(inputData, lineNum);
}
/* else if (inputChar == 'E') //Edit line Data
{
cout << "Enter line number you wish to edit: ";
cin >> lineNum;
editLineData(inputData, lineNum);
}*/
else if (inputChar == 'A') //Add line data
{
warning();
lastRow = inputData.size();
cout << "Enter a line description: ";
cin >> rowDescripin;
cout << "Enter a line username: ";
cin >> userin;
cout << "Enter a line password: ";
cin>>passin;
cout << "Enter notes: ";
cin>>notesin;
addNewRow(inputData, lastRow, rowDescripin, userin, passin, notesin);
}
/*else if (inputChar == 'S') //Save and encode file
{
}*/
else if (inputChar == 'X') //exit program
{
exit();
}
}
system("pause");
}
bool displayMenu()
{
cout << endl << " AVAILABLE OPTIONS " << endl << endl <<
"D - DISPLAY LINE DESCRIPTIONS" << endl <<
"V - VIEW LINE DATA" << endl <<
"E - EDIT LINE DATA" << endl <<
"A - ADD LINE DATA" << endl <<
"S - SAVE AND ENCODE FILE" << endl <<
"X - EXIT PROGRAM" << endl;
return 0;
}
void viewLineData(vector<dataRow> inputData,int lineNum)
{
cout << inputData[lineNum].site << endl << inputData[lineNum].user<<endl<<inputData[lineNum].pass <<endl<<inputData[lineNum].notes;
}
void displayVector(vector<dataRow> inputData)
{
cout << fixed << setprecision(3);
for (unsigned int i = 0; i < inputData.size(); i++)
{
cout << left << setw(20) << inputData[i].site ;
}
}
void addNewRow(vector<dataRow> inputData, int& lastRowNum, string site, string user, string pass, string notes)
{
char ans;
cout << "You have entered:" << endl << site << endl << user << endl << pass << endl << notes<<endl;
cout << "Is this the data you wish to add (Y/N)? ";
cin >> ans;
ans = toupper(ans);
if (ans == 'Y')
{
dataRow tempRow = { site, user, pass, notes };
inputData.push_back(tempRow);
cout << inputData.size();
int num = inputData.size()-1;
for (unsigned int i = 0; i < inputData.size(); i++)
{
cout << inputData[i].site << endl << inputData[i].user << endl << inputData[i].pass << endl << inputData[i].notes;
}
}
else if (ans == 'N')
{
cout << "ok enter of no";
}
}
void warning()
{
cout<< "WARNING: You cannot use semi-colons in these fields. Any semi-colons entered will be removed." << endl;
return;
}
int exit()
{
pathStream.close();
system("pause");
return 0;
}
void cleanBuffer()
{
cin.clear();
cin.ignore(BUFFER_SIZE, '\n');
}
I'm trying to assign some values to a vector from cin.
How can I achieve that the while loop breaks immediately after a specific word, e.g. end, was entered?
In my example it only breaks if I enter this word as "age", so only at the end of the loop. If I enter it at the beginning (as "name") it just continues.
#include <iostream>
#include <vector>
using namespace std;
struct person {
string name;
string age;
};
int main() {
vector<person> myPerson;
string text;
while(text != "end") {
person tempPerson;
cout << "Name:" << endl;
cin >> text;
tempPerson.name = text;
cout << "Age:" << endl;
cin >> text;
tempPerson.age = text;
myPerson.push_back(tempPerson);
}
for(int i=0; i<myPerson.size(); i++) {
cout << "Person No. " << i << ": " << endl;
cout << "Name: " << myPerson[i].name << endl;
cout << "Age: " << myPerson[i].age << endl;
}
return 0;
}
break out of the loop if "end" is entered.
while (true) {
cin >> text;
if (text == "end")
break;
// ...
}