Issue with C++ using getline and vector - c++

I have an issue where I am reading a line from a file using getline and the using a stringstream to separate the different variables using a comma as a delimiter. The issue is that a standard cout of the variables shows the seatDes properly, but using the vector I get the name back instead of the seatDes. Not sure why this is happening.
A standard line in file: Jane Doe,04202013,602,1A
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <cstdlib>
#include "reservation.h"
int main(int argc, char **argv)
{
std::ifstream flightFile;
std::string name, date, seatDes, flightNum, line;
int error = 0, conFlightNum;
flightFile.open("reservations.txt");
if(!flightFile)
{
//returns a error value if there is a problem reading the file
error = 1;
return error;
}
else
{
//Start reading files and sticks them into a class object and sticks the object into the vector set
while (std::getline(flightFile, line))
{
std::istringstream ss(line);
std::getline(ss, name, ',');
std::getline(ss, date, ',');
std::getline(ss, flightNum, ',');
conFlightNum = atoi(flightNum.c_str());
ss >> seatDes;
reservation newRes(name, date, conFlightNum, seatDes);
std::cout << name << std::endl << date << std::endl << conFlightNum << std::endl << seatDes << std::endl;
std::cout << "Vector Component" << std::endl;
std::cout //<< newRes.getName() << std::endl << newRes.getDate() << std::endl << newRes.getFlightNum()
<< std::endl << newRes.getSeatDesg() << std::endl;
}
}
flightFile.close();
return 0;
}
reservation.h file
class reservation {
private:
std::string name, seatDesg, date;
int flightNum;
public:
//Default Constructor
reservation(){}
//Big Constructor
reservation(std::string name, std::string date, int flightNum, std::string seatDesg)
{
this->name = name;
this->seatDesg = name;
this->date = date;
this->flightNum = flightNum;
}
//Setters
void setName(std::string name)
{ this->name = name; }
void setFlightNum(int flightNum)
{ this->flightNum = flightNum; }
void setSeatDesg(std::string seatDesg)
{ this->seatDesg = seatDesg; }
void setDate(std::string date)
{ this->date = date; }
//Getters
std::string getName()
{ return name; }
std::string getSeatDesg()
{ return seatDesg; }
std::string getDate()
{ return date; }
int getFlightNum()
{ return flightNum; }
};

reservation(std::string name, std::string date, int flightNum, std::string seatDesg)
{
this->name = name;
this->seatDesg = name; // Here is your problem
this->date = date;
this->flightNum = flightNum;
}
Should be
this->seatDesg = seatDesg;

Related

c++ program crashing after reading a file the second time

Basically, the problem is already described in the title: When starting the program first time ( meaning that the new file is created then ), it works perfectly and it doesn't crash, but when trying a second time ( meaning that the file already is there ), it crashes.
Question is: Why does it crash and how do I prevent that from happening?
Here's the code:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;
class TStudent
{
public:
string Name, Surname;
int Age;
TStudent(string name, string surname, int age)
{
Name = name;
Surname = surname;
Age = age;
cout <<"\n";
}
string toString() const
{
return Name + " ; " + Surname + " ; " + to_string(Age);
}
int aux1 = sizeof(Name), aux2 = sizeof(Surname);
};
class TRegistru
{
public:
string name, surname;
int age;
vector <TStudent> students;
TRegistru(const TStudent &other)
{
this->name = other.Name;
this->surname = other.Surname;
this->age = other.Age;
students.push_back(other);
}
void adauga(const TStudent& student)
{
students.push_back(student);
}
void salveaza(string file_name)// creating the file and storing the data
{
ofstream file1;
file1.open(file_name, ios::app);
file1.write((char*)&students, sizeof(students));
file1.close();
cout<<"\nFile saved and closed successfully.\n"<<endl;
}
void sterge()
{
students.clear();
}
void incarca(string file_name)// opening the file and reading the data
{
ifstream file2;
file2.open(file_name, ios::in);
if(!file2)
{
cout<<"Error in opening file..";
}
else
{
cout<<"File opened successfully.\n"<<endl;
}
file2.seekg(0);
file2.read((char*)&students, sizeof(students));
}
void afiseaza()//printing the data
{
for(auto student : students)
{
cout << student.Name << endl ;
cout << student.Surname << endl;
cout << student.Age << endl;
cout <<"\n";
}
}
string toString() const
{
string ret{};
for(const auto& student : students)
{
ret += student.toString() + "\n";
}
return ret;
}
};
int main()
{
TStudent student1("Simion", "Neculae", 21);
TStudent student2("Elena", "Oprea", 21);
TRegistru registru(student1);
registru.adauga(student2);
registru.salveaza("data.bin");// creating the file and storing the data
registru.sterge();
registru.incarca("data.bin");// opening the file and reading the data
registru.afiseaza();//printing the data
return 0;
}
After reading a second time your code I realised that the way you try to read and write a vector was plain wrong:
vector <TStudent> students;
...
ifstream file2;
file2.open(file_name, ios::in);
file2.seekg(0);
file2.read((char*)&students, sizeof(students)); // WRONG!!!
A vector does store its data in a contiguous way, but the address of the vector is not the address of the data. The correct way is to serialize each element of the vector to the file and then deserialize each element and push that into the vector.

Reading variables from txt file and saving them into the class objects as arrays c++

I am trying to get variables from a txt file which looks like;
1 Prince Heins 25
2 Lady Bridgette 29
3 Tony Ann 223
4 Lucy Phoenix 35
and here is my code but i can not get the variables from txt file to myArray. I created them with the number of line by using getline and linenumber is equal to linecount . Then i created many objects which is equal to linecount number. Next step was getting the variables from txt file line by line and i tried to use while(pbin) which is my read function. I am trying to send variables to class by using set functions which includes my strings and integer but i get an compile error:[Error] no match for 'operator>>' (operand types are 'std::ifstream {aka std::basic_ifstream}' and 'void') I checked the examples but none of them solved my issue.
Couldn't get the issue and fix it. I would be glad if someone helps.
#include <iostream>
#include <string>
#include <conio.h>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <istream>
#include <iomanip>
#include <cstring>
using namespace std;
class contact{
private:
int listno;
string name;
string surname;
string phonenumber;
public:
contact(){
this->name="Unknown";
this->surname="Unknown";
this->phonenumber="Unknown";
this->listno=0;
}
contact (string name,string surname,string phonenumber){
this->name=name;
this->surname=surname;
this->phonenumber=phonenumber;
this->listno=0;
}
contact(int listno,string name,string surname,string phonenumber){
this->name=name;
this->surname=surname;
this->listno=listno;
this->phonenumber=phonenumber;
}
void setListno(int listno){
this->listno=listno;
}
int getListno(){
return listno;
}
void setName(string name){
this->name=name;
}
string getName(){
return name;
}
void setSurname(string surname){
this->surname=surname;
}
string getSurname(){
return surname;
}
void setNumber(string phonenumber){
this->phonenumber=phonenumber;
}
string getNumber(){
return phonenumber;
}
void showInfos(){
cout << "Listno: " << this->listno << endl;
cout << "Name: " << this->name << endl;
cout << "Surname: " << this->surname << endl;
cout << "Number: " << this->phonenumber<<endl;
}
};
int main(){
int mListno;
string mName;
string mSurname;
string mNumber;
ifstream pbin("phoneData2.txt");
string line;
long linecount;
contact* myArray = new contact[linecount];
for(linecount=0;getline(pbin,line);linecount++);
if(pbin.is_open()){
int i;
for(i=0;i<linecount;i++){
while(
pbin >> myArray[i].setListno(mListno);
pbin >> myArray[i].setName(mName);
pbin >> myArray[i].setSurname(mSurname);
pbin >> myArray[i].setNumber(mNumber);
)
}
}
pbin.close();
return 0;
}
edited:
#include <iostream>
#include <string>
#include <conio.h>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <istream>
#include <iomanip>
#include <cstring>
using namespace std;
class contact{
private:
int listno;
string name;
string surname;
string phonenumber;
public:
contact(){
this->name="Unknown";
this->surname="Unknown";
this->phonenumber="Unknown";
this->listno=0;
}
contact (string name,string surname,string phonenumber){
this->name=name;
this->surname=surname;
this->phonenumber=phonenumber;
this->listno=0;
}
contact(int listno,string name,string surname,string phonenumber){
this->name=name;
this->surname=surname;
this->listno=listno;
this->phonenumber=phonenumber;
}
void setListno(int listno){
this->listno=listno;
}
int getListno(){
return listno;
}
void setName(string name,int count){
this->name=name[count];
}
string getName(){
return name;
}
void setSurname(string surname){
this->surname=surname;
}
string getSurname(){
return surname;
}
void setNumber(string phonenumber){
this->phonenumber=phonenumber;
}
string getNumber(){
return phonenumber;
}
void showInfos(){
cout << "Listno: " << this->listno << endl;
cout << "Name: " << this->name << endl;
cout << "Surname: " << this->surname << endl;
cout << "Number: " << this->phonenumber<<endl;
}
friend istream & operator>> (istream & in, contact & con){
in >> con.listno >> con.name >> con.surname >> con.phonenumber;
return in;
}
};
int main(){
ifstream pbin("phoneData2.txt");
string line;
long linecount=0;
contact* myArray = new contact[linecount];
for(linecount=0;getline(pbin,line);linecount++);
pbin.seekg(0);
if(pbin.is_open()){
int i;
for(i=0;i<linecount;i++){
if(! (pbin >> myArray[i]))
{
cout << "The contact is not found." ;
}
}
}
pbin.close();
return 0;
}
Add to contact a >> overload
friend std::istream & operator>> (std::istream & in, contact & con)
{
in >> con.listno >> con.name >> con.surname >> con.phonenumber;
return in;
}
and then in main, the for loop becomes
for(i=0;i<linecount;i++){
if (! (pbin >> myArray[i]))
{ // failed to read a contact
// do something here to clean up the mess
}
}
To round out a couple of the other mistakes,
int main(){
ifstream pbin("phoneData2.txt");
string line;
long linecount = 0; // otherwise you don't know what number linecount starts at
contact* myArray = new contact[linecount];
for(linecount=0;getline(pbin,line);linecount++);
pbin.clear(); // Clear the error flag from hitting the end of the file
// Needed when building to older C++ Standards
pbin.seekg(0); // rewind the file
if(pbin.is_open()){
int i;
for(i=0;i<linecount;i++){
if (! (pbin >> myArray[i]))
{
// do something here to clean up the mess
}
}
}
pbin.close();
return 0;
}

Error occurred when I compile the following code

When I was trying to run the program Visual Studio threw the error like this: " Error: Unable to open file C:\Users...\test1\Debug\investment.obj. Error code = 0x80070002.
I have tried many ways mentioned online but still not working. So, I was thinking if there was any problem in the code.
What's going on? Please help.
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cmath>
#include <numeric>
using namespace std;
struct Investment
{
string Name;
string BankAccount;
string SortCode;
float Investment;
float Contribution;
};
string Trim(string str)
{
str.erase(0, str.find_first_not_of(" \t\r\n"));
str.erase(str.find_last_not_of(" \t\r\n") + 1);
return str;
}
void Get_Data(const string& filename, vector<Investment>& data)
{
ifstream fin(filename);
if (!fin.is_open())
return;
string line;
if (!getline(fin, line))
return;
while (getline(fin, line))
{
istringstream sin(line);
vector<string> fields;
string field;
while (getline(sin, field, ','))
{
fields.push_back(field);
}
Investment inv;
inv.Name = Trim(fields[0]);
inv.BankAccount = Trim(fields[1]);
inv.SortCode = Trim(fields[2]);
inv.Investment = atof(Trim(fields[3]).c_str());
inv.Contribution = 0.0f;
data.push_back(inv);
}
}
void Save_Data(const string& filename, const vector<Investment>& data)
{
ofstream fout(filename);
if (!fout.is_open())
return;
fout << "NAME, BANK ACCOUNT, SORT CODE, INVESTMENT, Contribution\n";
for (auto& inv : data)
{
fout << inv.Name << " "
<< inv.BankAccount << " "
<< inv.SortCode << " "
<< inv.Investment << " "
<< inv.Contribution << "\n";
}
}
int main()
{
vector<Investment> Data_investment;
Get_Data("aaa.csv", Data_investment);
float total = accumulate(Data_investment.begin(), Data_investment.end(), 0.0f,[](float sum, const Investment& inv) { return sum + inv.Investment; }
);
for (auto& inv : Data_investment)
{
float percentage = (inv.Investment * 100.0f) / total;
inv.Contribution = percentage;
}
Save_Data("aaa_new.csv", Data_investment);
return 0;
}
I have successfully compiled your source code into Visual Studio 2017 with very slight modification. Please have a look.
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cmath>
#include <numeric>
using namespace std;
struct Investment
{
std::string Name;
std::string BankAccount;
std::string SortCode;
float Invest; // Changed due the variable name goes same as struct name if use Investment
float Contribution;
};
string Trim(string &str)
{
str.erase(0, str.find_first_not_of(" \t\r\n"));
str.erase(str.find_last_not_of(" \t\r\n") + 1);
return str;
}
void Get_Data(const string& filename, vector<Investment>& data)
{
ifstream fin(filename);
if (!fin.is_open())
return;
string line;
if (!getline(fin, line))
return;
while (getline(fin, line))
{
istringstream sin(line);
vector<string> fields;
string field;
while (getline(sin, field, ','))
{
fields.push_back(field);
}
Investment inv;
inv.Name = Trim(fields[0]);
inv.BankAccount = Trim(fields[1]);
inv.SortCode = Trim(fields[2]);
inv.Invest = atof(Trim(fields[3]).c_str());
inv.Contribution = 0.0f;
data.push_back(inv);
}
}
void Save_Data(const string& filename, const vector<Investment>& data)
{
ofstream fout(filename);
if (!fout.is_open())
return;
fout << "NAME, BANK ACCOUNT, SORT CODE, INVESTMENT, Contribution\n";
for (auto& inv : data)
{
fout << inv.Name << " "
<< inv.BankAccount << " "
<< inv.SortCode << " "
<< inv.Invest << " "
<< inv.Contribution << "\n";
}
}
int main()
{
vector<Investment> Data_investment;
Get_Data("aaa.csv", Data_investment);
float total = accumulate(Data_investment.begin(), Data_investment.end(), 0.0f, [](float sum, const Investment& inv) { return sum + inv.Invest; }
);
for (auto& inv : Data_investment)
{
float percentage = (inv.Invest * 100.0f) / total;
inv.Contribution = percentage;
}
Save_Data("aaa_new.csv", Data_investment);
return 0;
}
Below is the modified part
std::string Name;
std::string BankAccount;
std::string SortCode;
float Invest; // Changed due the variable name goes same as struct name if use Investment

Read class objects from file c++ (Private member variables)

I am learning how to work with objects but am stuck the closest answer is could find was Read class objects from file c++.
In this question:
How would you go about the same task if your member variables were declared as private?
Try something similar to this:
Content of person.txt
John California 3683893
Stalin Russia 489895
Sample code:
#include<iostream>
#include <fstream>
#include <vector>
#include <string>
class person
{
private:
std::string _name;
std::string _address;
unsigned int _phone;
public:
person(const std::string& name, const std::string& address, unsigned int phone)
:_name(name),_address(address),_phone(phone)
{}
std::string getName() const { return _name; }
std::string getAddress() const { return _address; }
unsigned int getPhone() { return _phone; }
};
int main()
{
std::vector<person> persons;
std::string name;
std::string address;
unsigned int phone;
std::ifstream fs;
fs.open("person.txt");
if (fs.is_open()) {
while (std::getline(fs, name, ' ') && std::getline(fs, address, ' ') &&
(fs >> phone))
{
persons.push_back(person(name,address,phone));
}
}
for (auto p : persons) {
std::cout << p.getName() << " " << p.getAddress() << " " << p.getPhone() << '\n';
}
return 0;
}

Reading from file separated with semicolons and storing into array

I am completely lost and have been trying for hours to read from a file named "movies.txt" and storing the info from it into arrays, because it has semicolons. Any help? Thanks.
movies.txt:
The Avengers ; 2012 ; 89 ; 623357910.79
Guardians of the Galaxy ; 2014 ; 96 ; 333130696.46
Code:
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
struct Movie {
std::string name;
int year;
int rating;
double earnings;
};
int main()
{
const int MAX_SIZE = 100;
Movie movieList[MAX_SIZE];
std::string line;
int i = 0;
std::ifstream movieFile;
movieFile.open("movies.txt");
while (getline(movieFile, line, ';'))
{
movieFile >> movieList[i].name >> movieList[i].year >> movieList[i].rating >> movieList[i].earnings;
i++;
}
movieFile.close();
std::cout << movieList[0].name << " " << movieList[0].year << " " << movieList[0].rating << " " << movieList[0].earnings << std::endl;
std::cout << movieList[1].name << " " << movieList[1].year << " " << movieList[1].rating << " " << movieList[1].earnings << std::endl;
return 0;
}
What I want is to have:
movieList[0].name = "The Avengers";
movieList[0].year = 2012;
movieList[0].rating = 89;
movieList[0].earnings = 623357910.79;
movieList[1].name = "Guardians of the Galaxy";
movieList[1].year = 2014;
movieList[1].rating = 96;
movieList[1].earnings = 333130696.46;
I amended your code.
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
struct Movie {
std::string name;
int year;
int rating;
double earnings;
};
std::vector<std::string>
split(const std::string &s, char delim = ',')
{
std::vector<std::string> elems;
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim))
{
elems.push_back(item);
}
return elems;
}
int main()
{
std::vector<Movie> movieList;
std::string line;
std::ifstream movieFile;
movieFile.open("movies.txt");
while (getline(movieFile, line))
{
std::vector<std::string> columns = split(line,';');
Movie movie;
movie.name = columns[0];
movie.year = std::stoi(columns[1]);
movie.rating = std::stoi(columns[2]);
movie.earnings = std::stof(columns[3]);
movieList.push_back(movie);
}
movieFile.close();
for (const Movie & m: movieList)
{
std::cout << m.name << " " << m.year << " " << m.rating << " " << m.earnings << std::endl;
}
return 0;
}
Basicly, I added a split function that splits the lines using ';'. Also I use vector to store the movies rather than hard coded array of movies. Much better this way.
P.S. Second version without vectors
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
struct Movie {
std::string name;
int year;
int rating;
double earnings;
};
void split(const std::string &s, char delim, std::string elems[])
{
std::stringstream ss(s);
std::string item;
int i = 0;
while (std::getline(ss, item, delim))
{
elems[i++] = item;
}
}
int main()
{
//std::vector<Movie> movieList;
const int MAX_SIZE = 100;
Movie movieList[MAX_SIZE];
int movieNo = 0;
std::string line;
std::ifstream movieFile;
movieFile.open("/home/marcin/testing/movies.txt");
std::string columns[4];
while (getline(movieFile, line))
{
split(line,';', columns);
movieList[movieNo].name = columns[0];
movieList[movieNo].year = std::stoi(columns[1]);
movieList[movieNo].rating = std::stoi(columns[2]);
movieList[movieNo].earnings = std::stof(columns[3]);
++movieNo;
}
movieFile.close();
for (int i =0; i < movieNo; ++i) {
std::cout << movieList[i].name
<< " "
<< movieList[i].year
<< " "
<< movieList[i].rating
<< " "
<< movieList[i].earnings
<< std::endl;
}
return 0;
}
Use getline(my_movieFile, movie_name, ';') to get the name of the movie up to the ;.
You'll need to figure out how to remove the trailing whitespace from the name if necessary.. you can search for examples.
Read the rest of the line using getline(movieFile, line)
Use std::replace to replace all ; with a space in line
Put line into a std::stringstream.
Then extract the remaining fields from the stringstream using the >> operators.
Put this in loop do { ... } while (movieFile);
Also, don't hardcode an arbitrary number of movies. Use a std::vector<Movie> and push_back to add new ones.
I think you want to break your line into tokens using something like std::strtok. Check out the reference here. The example given on that page uses a blank as a separator, you would use a semicolon.