I wrote a little c++ class that read a ASCII files each line can have
4 element (int, string, int, float)
1000 I 100 10.0
or 3 (int, string, int)
1001 E 100
which means that if the string is an I the fourth element exist, not otherwise.
I am trying to write a class to insert rows.
The code asks the user to insert the object properties and then writes to file
I want to add a check
if the string is "I" then should ask to insert the float otherwise leave empty.
#include <iostream>
#include <fstream>
using namespace std;
void writing();
void deleting();
void searching();
class orderbook
{
string text;
private:
double Price = (double) NULL;
public:
int Timestamp = 0;
string Operation;
long int Id;
orderbook(){};
orderbook(const string& name)
{
ifstream infile;
infile.open(name);
if(!infile.good())
{
cout << "File is not open";
}
else
{
string line;
while(getline(infile,line))
text = text + line + '\n';
}
};
string contetns()
{
return text;
};
void SetPrice(double x = NULL)
{
Price = x;
}
float GetPrice()
{
return Price;
}
void insert(const string& name)
{
long int Id;
double Price;
float a;
orderbook ob;
cout << "Please enter Timestamp : ";
cin >> ob.Timestamp;
cout << "Please enter the Operation type: ";
cin >> ob.Operation;
cout << "Please enter Id : ";
cin >> ob.Id;
if (ob.Operation == 'I')
{
cout << "Pleae enter the Price of order: ";
cin >> a;
ob.SetPrice(a);
}
else{
ob.SetPrice()
}
ofstream myfile;
myfile.open(name, ios::app | ios::out);
myfile << ob.Timestamp << "\t";
myfile << ob.Operation << "\t";
myfile << ob.Id << "\t";
// if (ob.GetType().GetProperty("Price") != null )
// {
// myfile << ob.GetPrice() << endl;
// }
// else
// {
// myfile << endl;
// }
myfile.close();
}
void deleting()
{
string line, record;
cout << "Please Enter the name of record you want to delete: ";
cin >> record;
ifstream myfile;
ofstream temp;
myfile.open("record.txt");
temp.open("temp.txt");
while (getline(myfile, line))
{
if (line.substr(0, record.size()) != record)
temp << line << endl;
}
cout << "The record with the name " << record << " has been deleted if it exsisted" << endl;
myfile.close();
temp.close();
remove("record.txt");
rename("temp.txt", "record.txt");
}
};
int main()
{
string filename;
cout<<"Please enter the full name of the data file: ";
cin>>filename;
orderbook ob(filename);
cout << "content: " << endl << ob.contetns() << endl;
ob.insert(filename);
cout << "content: " << endl << ob.contetns() << endl;
ob.deleting();
cout << "content: " << endl << ob.contetns() << endl;
}
I get this error
class_student.cpp:64:20: error: invalid operands to binary expression
('string'
(aka 'basic_string, allocator >') and 'int') if (ob.Operation == 'I')
Related
For one of my options, I had to add a row of data to my struct array, I was able to update the array but it does not update the actual array. So I am trying to update my struct array by passing it as a reference. I placed the '&' sign before the name of the variable, but all my indexes within the function errored.. I'm still a newbie to programing and I'm not "allowed " to use any vectors according to my Professor. . I looked online and placed the '&' on the function name as well as on the prototype. I also changed it from void to the "data type" to return the updated array, but no luck... I hope this comes out clear....
#include<iostream>
#include<iomanip>
#include<fstream>
using namespace std;
struct Data {
string first_name;
string last_name;
int employee_id;
string phone_number;
};
void readFile( ifstream& , string, Data [],int&);
void getEmployeeDetail(Data [], int&);
void getEmployeeLast(Data [], int&);
Data getAddEmployee(Data &, int&);
void getRemoveEmployee();
void getManagerOnly();
void getStaffOnly();
const int SIZE = 15;
Data employee[SIZE];
int main() {
ifstream inputFile;
ofstream outputFile;
int count = 0;
int selection;
const int EMPLOYEE_DETAIL = 1,
EMPLOYEE_LAST = 2,
ADD_EMPLOYEE = 3,
REMOVE_EMPLOYEE = 4,
MANAGER_ONLY = 5,
STAFF_ONLY = 6,
QUIT = 7;
readFile( inputFile ,"employeeData.txt", employee,count);
do {
cout << "\t Please select your option.\n"
<< "1. List all employee details\n"
<< "2. List employee by last name\n"
<< "3. Add a new employee\n"
<< "4. Remove an employee\n"
<< "5. Show all managers only\n"
<< "6. Show all staff only\n"
<< "7. Quit\n"
<< "Please enter your selection.\n" << endl;
cin >> selection;
while (selection < EMPLOYEE_DETAIL || selection > QUIT) {
cout << " Pleasse enter a valid selection.\n";
cin >> selection;
}
switch (selection) {
case EMPLOYEE_DETAIL:
getEmployeeDetail(employee,count);
break;
case EMPLOYEE_LAST:
getEmployeeLast(employee, count);
break;
case ADD_EMPLOYEE:
getAddEmployee(employee, count);
break;
case REMOVE_EMPLOYEE:
getRemoveEmployee();
break;
case MANAGER_ONLY:
getManagerOnly();
break;
case STAFF_ONLY:
getStaffOnly();
break;
case QUIT:
cout << "Program ending\n";
break;
}
} while (selection != QUIT);
system("pause");
return(0);
}
void readFile(ifstream& inputFile, string data, Data employee[],int &count) {
inputFile.open(data);
if (!inputFile) {
cout << " Error in opening file\n";
exit(1);
}
else {
while (!inputFile.eof()) {
inputFile >> employee[count].first_name;
inputFile >> employee[count].last_name >> employee[count].employee_id >> employee[count].phone_number;
count++;
}
inputFile.close();
}
return;
};
void readFile(ifstream& inputFile, string data, Data employee[],int &count) {
inputFile.open(data);
if (!inputFile) {
cout << " Error in opening file\n";
exit(1);
}
else {
while (!inputFile.eof()) {
inputFile >> employee[count].first_name;
inputFile >> employee[count].last_name >> employee[count].employee_id >> employee[count].phone_number;
count++;
}
inputFile.close();
}
return;
};
void getEmployeeDetail( Data employee[], int& count) {
cout << "Firt Name" << "\t" << "Last Name " << "\t" << "Employee ID " << "\t" << "Phone Number \n";
cout << "--------------------------------------------------------------------------\n";
for(int i =0; i < count; i++)
cout <<employee[i].first_name<<"\t\t"<<employee[i].last_name<<"\t\t"<<employee[i].employee_id<<"\t\t"<<employee[i].phone_number<< "\n ";
cout << endl;
}
void getEmployeeLast(Data employee[], int& count) {
string searchName;
cout << "Please enter the last name of the employee you want to search for.\n";
cin >> searchName;
/*
for (int i = 0; i < count; i++)
if (searchName ==employee[i].last_name) {
cout << employee[i].last_name;
}
*/
string matchString = searchName;
for (int i = 0; i < count; i++) {
if (employee[i].last_name.find(matchString, 0) != std::string::npos) {
cout << employee[i].last_name << endl;
}
else {
cout << "No employee was located with that name.\n";
exit(1);
}
}
}
Data getAddEmployee(Data &employee, int& count) {
string firstName, lastName, phoneNumber;
int employeeID, size;
for (int i = 0; i < count; i++)
cout << employee[i].first_name << "\t\t\t" << employee[i].last_name << "\t\t" << employee[i].employee_id << "\t\t" << employee[i].phone_number << "\n ";
cout << endl;
cout << count <<"\n";
size = count + 1;
cout << size << "\n";
cout << "Please enter the new employee First Name.\n";
cin >> firstName;
cout << "Please enter the new employee Last Name.\n";
cin >> lastName;
cout << "Please enter the new employee's ID.\n";
cin >> employeeID;
cout << "Please enter the new employee Phone Number.\n";
cin >> phoneNumber;
employee[10].first_name = firstName;
employee[10].last_name = lastName;
employee[10].employee_id = employeeID;
employee[10].phone_number = phoneNumber;
for (int i = 0; i < size; i++) {
cout << employee[i].first_name << "\t\t\t" << employee[i].last_name << "\t\t" << employee[i].employee_id << "\t\t" << employee[i].phone_number << "\n ";
cout << endl;
}
return employee;
}
First of all, your naming could be better. Like employeeList instead employee to specify its a list/array of employee, also addEmployee instead of getAddEmployee.
Second, instead of pasting whole code, it's better to paste the relevant block of code based on your question to make it clearer.
The solution is, your array is basically already on global scope, you don't need to pass it. Can just directly modify the array.
struct Data {
string first_name;
string last_name;
int employee_id;
string phone_number;
};
void addEmployee();
const int SIZE = 15;
Data employeeList[SIZE];
int current = 0;
int main(){
Data emp1 = {"John", "Doe", 100, "12345"};
employeeList[0] = emp1;
current++;
addEmployee();
for(int i=0; i<current; i++){
Data emp = employeeList[i];
cout<<i+1<<" "<<emp.first_name<<" "<<emp.phone_number<<endl;
}
}
void addEmployee(){
Data emp2 = {"Sam", "Smith", 200, "67890"};
employeeList[current] = emp2;
current++;
}
Can try it here: https://onlinegdb.com/drhzEOpis
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;
}
I have changed the code, now the program reads teh file form students.txt correctly, but still calculated from user input instead of students.txt
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//Declaring class Student
class Student
{
private:
string newName;
int newScore1;
int newScore2;
int newScore3;
float newFinal;
public:
// No argument constructors
Student ()
{
newName = " ";
newScore1 = 0;
newScore2 = 0;
newScore3 = 0;
newFinal = 0.00;
}
//all arguements constructors
Student (string name, int score1, int score2, int score3, float final)
{
newName = name;
newScore1 = score1;
newScore2 = score2;
newScore3 = score3;
newFinal = final;
}
//getters
string getName() const
{
return newName;
}
int getScore1() const
{
return newScore1;
}
int getScore2()const
{
return newScore2;
}
int getScore3()const
{
return newScore3;
}
float getFinal () const
{
return newFinal;
}
//Setters
void setName(string name)
{
newName = name;
}
void setScore1(int score1)
{
newScore1=score1;
}
void setScore2(int score2)
{
newScore2=score2;
}
void setScore3 (int score3)
{
newScore3 = score3;
}
void setFinal (float final)
{
newFinal = final;
}
};
//asks for number of students,
// function asks for input to fill in vector
//sorts the inputs to get max 2 scores out of 3
//puts the data in a vector of class Student
//Sends data to a text file students.txt
void fillvector(vector <Student>& newMyClass)
{
string name;
float score1;
float score2;
float score3;
float final;
float tmp;
cout << "Please enter the number of Students: " << endl;
int classSize;
cin >> classSize;
for (int i = 0; i < classSize; i ++)
{
cout << "Enter Student's name" << endl;
cin >> name;
cout << "Enter Student's Score 1" << endl;
cin >> score1;
cout << "Enter Student's Score 2" << endl;
cin >> score2;
cout << "Enter Student's Score 3" << endl;
cin >> score3;
if(score1>score2)
{
float tmp = score1;
score1 = score2;
score2 = tmp;
}
if(score1>score3)
{
float tmp = score1;
score1=score3;
score3 = tmp;
}
if(score2>score3)
{
float tmp = score2;
score2=score3;
score3=tmp;
}
final = (score2+score3)/2;
Student newStudent (name, score1, score2, score3, final);
newMyClass.push_back(newStudent);
cout << endl;
ofstream myfile;
myfile.open ("students.txt", std::ofstream::out |std::ofstream::app );
myfile << name<< setw(5)<< score1<< setw(5)<<score2<<setw(5) <<score3<<setw(5)<<final<<setw(5)<<endl;
myfile.close();
cout << "Copied to students.txt" << endl;
}
cout << endl;
}
//reads data from textfile students.txt
//calculated teh minimum scores and maximum scores
//sends the minimum and maximum scores to text file Results.txt
void readToVector(vector <Student>& newMyClass)
{
string name;
float score1;
float score2;
float score3;
float finalScore;
Student newStudent (name, score1, score2, score3, finalScore);
unsigned int size = newMyClass.size();
ifstream fin("students.txt");
if (fin.is_open())
{cout << "File open" << endl;
while(fin >> name >> score1 >> score2 >> score3 >> finalScore)
{
newStudent.setName(name);
newStudent.setScore1(score1);
newStudent.setScore2(score2);
newStudent.setScore3(score3);
newStudent.setFinal(finalScore);
newMyClass.push_back(newStudent);
//cout << newStudent.getName() << newStudent.getFinal() << endl;
}
fin.close();
cout << endl;
Student studWMaxScore = newMyClass[0];
float maxscore = studWMaxScore.getFinal();
for (unsigned int i =0; i < size; i++)
{
if (maxscore < newMyClass[i].getFinal())
{
maxscore = newMyClass[i].getFinal();
studWMaxScore = newMyClass[i];
}
}
cout << "Maximum Score is " << maxscore << endl;
ofstream myfile;
myfile.open ("Result.txt", std::ofstream::out );
myfile << "Maximum Score" << endl;
myfile << maxscore << endl;
myfile << "Name of the student with maximum score is " << endl;
myfile << studWMaxScore.getName() << endl << endl;
// myfile.close();
cout << "Copied to Results.txt" << endl;
Student stuWMinScore = newMyClass[0];
float minscore = stuWMinScore.getFinal();
for (unsigned int i =0; i < size; i++)
{
if (minscore > newMyClass[i].getFinal())
{
minscore = newMyClass[i].getFinal();
stuWMinScore = newMyClass[i];
}
}
cout << "Minimum Score is " << minscore << endl;
// ofstream myfile;
// myfile.open ("Result.txt", std::ofstream::out );
myfile << "Mimimum Score" << endl;
myfile << minscore << endl;
myfile << "Name of the student with minimum score is " << endl;
myfile << stuWMinScore.getName() << endl << endl;
// myfile.close();
cout << "Copied to Results.txt" << endl;
}
else
cout << "file in not open" << '\n';
}
//prints out the name and scores of each student
void printVector (const vector<Student>& newMyClass)
{
unsigned int size = newMyClass.size();
for (unsigned int i =0; i < size; i++)
{
cout << "Student name is: "<< newMyClass[i].getName() << endl;
cout << "Student Score 1 is "<< newMyClass[i].getScore1()<< endl;
cout << "Student Score 2 is "<< newMyClass[i].getScore2()<< endl;
cout << "Student Score 3 is "<< newMyClass[i].getScore3()<< endl;
cout << "Student Final Score is " << newMyClass[i].getFinal() << endl;
cout << endl;
}
}
int main ()
{
vector <Student> myClass;
fillvector (myClass);
readToVector(myClass);
printVector(myClass);
}
Core of bug looks to be right here:
while(fin >> name >> score1 >> score2 >> score3 >> finalScore)
{
newStudent.setName(name);
newStudent.setScore1(score1);
newStudent.setScore2(score2);
newStudent.setScore3(score3);
newStudent.setFinal(finalScore);
}
fin.close();
newMyClass.push_back(newStudent);
Once the indentation is fixed, it's easy to see that newStudent is only pushed into the vector after the file has been completely read. OP should be getting the last student into the vector, but none of the others. Since OP probably wants all of the students in the file in the vector,
while(fin >> name >> score1 >> score2 >> score3 >> finalScore)
{
newStudent.setName(name);
newStudent.setScore1(score1);
newStudent.setScore2(score2);
newStudent.setScore3(score3);
newStudent.setFinal(finalScore);
newMyClass.push_back(newStudent); <- moved push_back to here
}
fin.close(); <- probably not necessary
Can't verify the rest of the code because there doesn't seem to be a definition or assignment of size--Crom only knows if those for loops are covering the correct ground--or the validity of the input because there is no provided input file. OP may be reading exactly nothing if the parsing rules are wrong. Debugger would figure that out much faster than another Stack Overflow post.(OP has since addressed this)
New stuff.
I don't see why the input doesn't parse either. First make sure the file is encoded as ASCII text. I do not know what tools you have to do this on your computer. I use a hex editor, lets you see the file in byte values rather than characters, to see if the characters are not matching their expected ASCII values. A text editor may be converting for you and hiding the differences.
For example, often a UTF-8 encoded file will look exactly the same as an ASCII file except for a bit of binary at the beginning marking informing the reader program that it is a UTF-8 file and may contain non-ASCII.
If it isn't, there's the problem. Re-save the file as an ASCII file. If it is an ASCII file, time to minimize. Write a small program that does nothing but open the file, read it token by token, and see which token fails to parse. Something like this:
int main()
{
ifstream fin("students.txt");
if (fin.is_open())
{
int line = 0;
while(true) // loop forever
{
line++;
if (!fin >> name)
{
std::cout << "Could not read name on line " << line << std::endl;
break; // exit loop
}
if (!fin >> score1)
{
std::cout << "Could not read score1 on line " << line << std::endl;
break;
}
if (!fin >> score2)
{
std::cout << "Could not read score2 on line " << line << std::endl;
break;
}
if (!fin >> score3)
{
std::cout << "Could not read score3 on line " << line << std::endl;
break;
}
if (!fin >> finalScore)
{
std::cout << "Could not read finalScore on line " << line << std::endl;
break;
}
}
}
else
{
std::cout << "Could not open file" << std::endl;
}
}
Once you know where the file fails, you are in great position to ask a new question. This one is sprawling a bit too much.
I have got an assignment project to make a program using C++ which maintains a list of Students (their name, age, and GPA) in a text file. The program has the following functionality:
Insertion of record
Deletion of record
Searching of record
Updating a record
When deleting a record my code takes a string name as input and removes it from the text file. However the next two lines in the file (age & gpa for that student) are left. How do I remove those too?
Following is the code for my program.
#include <iostream>
#include <fstream>
using namespace std;
void writing();
void deleting();
void searching();
class student {
public:
int age = 0;
string name;
void SetGpa(float x)
{
gpa = x;
}
float GetGpa()
{
return gpa;
}
private:
float gpa = 0.0;
};
int main()
{
int opt;
cout << "Please Enter an option number to continue:\n ";
cout << "\nPress 1 for New Record insertion";
cout << "\nPress 2 for Record Deletion";
cout << "\nPress 3 for Searching a Record";
cout << "\nPress 4 for Updating a Record";
cout << "\nEnter option Number: ";
cin >> opt;
switch (opt)
{
case 1:
{
writing();
break;
}
case 2:
{
deleting();
break;
}
case 3:
{
searching();
break;
}
case 4:
{
deleting();
writing();
cout << "Record has been updated! ";
break;
}
}
}
void writing()
{
float a;
student moiz;
cout << "Please enter name of student: ";
cin >> moiz.name;
cout << "Please enter the age of student: ";
cin >> moiz.age;
cout << "Pleae enter the Gpa of student: ";
cin >> a;
moiz.SetGpa(a);
ofstream myfile;
myfile.open("record.txt", ios::app | ios::out);
myfile << endl << moiz.name << endl;
myfile << moiz.age << endl;
myfile << moiz.GetGpa();
myfile.close();
}
void deleting()
{
string line, name;
cout << "Please Enter the name of record you want to delete: ";
cin >> name;
ifstream myfile;
ofstream temp;
myfile.open("record.txt");
temp.open("temp.txt");
while (getline(myfile, line))
{
if (line != name)
temp << line << endl;
}
cout << "The record with the name " << name << " has been deleted if it exsisted" << endl;
myfile.close();
temp.close();
remove("record.txt");
rename("temp.txt", "record.txt");
}
void searching()
{
ifstream fileInput;
fileInput.open("record.txt");
string line, search;
cout << "Please enter the term to search: ";
cin >> search;
for (unsigned int curLine = 0; getline(fileInput, line); curLine++)
{
if (line.find(search) != string::npos)
{
cout << "found: " << search << " on line: " << curLine << endl;
}
else
{
cout << "Error! Not found on Line" << curLine << endl;
}
}
}
You can add an else clause to your statement checking the name, and introduce a counter of how many of the following lines should be skipped after name was found:
int skip = 0;
while (getline(myfile, line)) {
if ((line != name) && !(skip > 0)) {
temp << line << endl;
}
else {
if(skip == 0) {
skip = 2; // Skip the next two lines also
}
else {
--skip;
}
}
}