How to get variables stored in class from different lines? - c++

How to get program read every line from .txt file and store 3 variables per line in different place ? I don't understand how can I store different value in same class. One line works fine but what I have tried more doesn't work.
class Team
{
public:
string name;
string dificulty;
string section;
};
void GetTeamInfo(Team& ko);
int main()
{
Team ko;
GetTeamInfo(ko);
cout << ko.name << " ";
cout << ko.dificulty<< " ";
cout << ko.section<< " ";
system("PAUSE");
}
void GetTeamInfo(Team& ko, int & i)
{
ifstream fd;
fd.open("Team.txt");
if (fd.is_open())
{
for(int i = 0; i < 10 ; i ++)
{
fd >> ko.name;
fd >> ko.dificulty;
fd >> ko.section ;
}
}
else
{
std::cout << "Mistake can't open file 'Team.txt'\n";
}
}

Try this:
void GetTeamInfo(vector<Team>& kos)
{
ifstream fd;
fd.open("Team.txt");
if (fd.is_open())
{
while (!d.eof())
{
Team ko;
fd >> ko.name;
fd >> ko.dificulty;
fd >> ko.section;
kos.push_back(ko);
}
}
...
}

I suggest you use a std::vector, since you have a number of teams.
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
using namespace std;
class Team
{
public:
string name;
string dificulty;
string section;
};
void GetTeamInfo(vector<Team>& ko_v);
int main()
{
vector<Team> ko; // a vector of Teams
GetTeamInfo(ko); // read from file inside a vector
// print every team
for(unsigned int i = 0; i < ko.size(); ++i) {
cout << ko[i].name << " ";
cout << ko[i].dificulty<< " ";
cout << ko[i].section<< " ";
cout << "\n";
}
//system("PAUSE"); // don't use system()
return 0; // return 0 should be placed at the end of main
}
void GetTeamInfo(vector<Team>& ko_v) // you had an extra parameter here, no need to
{
ifstream fd;
fd.open("Team.txt");
if (fd.is_open()) // check if file is open
{
while (!fd.eof()) // while you have more to read
{
Team ko; // create a Team
fd >> ko.name; // read data
fd >> ko.dificulty;
fd >> ko.section;
ko_v.push_back(ko); // store that Team in the vector of teams
}
}
else
{
cout << "File not opened!\n";
}
}
Why not to use an array? You could use an array of course, but since this is C++, std::vector's usage is encouraged. Moreover, you don't have to worry about the number of the Teams you are going to read from the file. If you would have used an array, you should know apriori the number of the Teams, or dynamically allocate memory.
Why not use system(pause); ?
Just for a glance, I am modifying the example with the use of an array.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class Team
{
public:
string name;
string dificulty;
string section;
};
void GetTeamInfo(Team* ko_ar, const int N);
int main()
{
const int N = 3; // number of teams in the file
Team ko[N]; // a vector of Teams
GetTeamInfo(ko, N); // read from file inside a vector
// print every team
for(int i = 0; i < N; ++i) {
cout << ko[i].name << " ";
cout << ko[i].dificulty<< " ";
cout << ko[i].section<< " ";
cout << "\n";
}
//system("PAUSE"); // don't use system()
return 0; // return 0 should be placed at the end of main
}
void GetTeamInfo(Team* ko_ar, const int N)
{
ifstream fd;
fd.open("Team.txt");
int i = 0;
if (fd.is_open()) // check if file is open
{
while (!fd.eof()) // while you have more to read
{
Team ko; // create a Team
fd >> ko.name; // read data
fd >> ko.dificulty;
fd >> ko.section;
if(i == N) {
cout << "Read more than " << N << " teams\n";
break;
}
ko_ar[i++] = ko; // store that Team in the vector of teams
}
}
else
{
cout << "File not opened!\n";
}
cout << "Read " << i << " teams\n";
}

Use a vector, here you have a full example(commented):
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Team
{
public:
// Adding a constructor.
Team(string name, string dificulty, string section):
name(name),
dificulty(dificulty),
section(section)
{}
string name;
string dificulty;
string section;
};
// Defining a convenience type;
typedef vector<Team> team_list_t;
// This function now receives a vector of teams.
void GetTeamInfo(team_list_t &tl);
int main()
{
team_list_t tl;
GetTeamInfo(tl);
for (vector<Team>::iterator it = tl.begin(); it != tl.end(); ++it)
cout << it->name << " " << it->dificulty << " " << it->section << endl;
// You can also ...
for (int i = 0; i < tl.size(); i++)
cout << tl[i].name << " " << tl[i].dificulty << " " << tl[i].section << endl;
}
void GetTeamInfo(team_list_t& tl)
{
ifstream fd;
fd.open("Team.txt");
if (fd.is_open())
{
// Define variables;
string name, dificulty, section;
// Read until EOF
while(fd >> name >> dificulty >> section)
{
// Add teams to the vector/list.
tl.push_back(Team(name, dificulty, section));
}
}
else
{
std::cout << "Mistake can't open file 'Team.txt'\n";
}
}

Related

C++ Read Value from a pointer to struct including the target struct in an array

I am new to c++ and trying to make an atm. It consits of one file reading user data from files and a main file. Everytime I try to read the output of the returned pointer to the array of structs, where the data is stored, I get strange data. I think there is a problem when assigning strings to the first struct, because when I tried with test values (third file) it worked.
Edit:
I can read out integeres from the strcut, but I have problems with strings.
Here is the code
users.cpp (Creates the struct, included in main.cpp)
#include <fstream>
#include <string>
#include <iostream>
#define STRING_ERROR 4294967295
#define MAX_USERS 100000
using namespace std;
struct user
{
int id;
string firstname;
string name;
int age;
int pin;
};
struct user_container{
int size;
user users [MAX_USERS];
};
typedef struct user User;
typedef struct user_container container;
void print_user_vars(User *user){
cout << "Id: " << user->id << "\nFirstname: " << user->firstname << "\nName: " << user->name << "\nAge: " << user->age << "\nPIN: " << user->pin << endl;
}
int get_usercount(string path){
int usercount = 0;
ifstream file;
string line;
file.open(path, ios::binary | ios::in);
while(true){
getline(file , line);
if(file.fail())
break;
if(line.find("}") != STRING_ERROR){
usercount++;
}
}
file.close();
return usercount;
}
container * get_users(string path){
const int usercount = get_usercount(path);
ifstream file;
string line;
User users[usercount];
const char *values[5] = {"id", "firstname", "name", "age", "pin"};
file.open(path, ios::binary | ios::in);
User proto_user;
int user_num = 0;
while(true){
getline(file , line);
if(file.fail())
break;
if(line.find(":") != STRING_ERROR){
for(int i = 0; i < 5; i++){
if(line.find(values[i]) != STRING_ERROR){
string value;
for(int v = 0; v < line.length(); v++){
if(v > line.find_first_of(":")){
value += line[v];
}
}
if(values[i] == "id"){
proto_user.id = stoi(value);
}
else if(values[i] == "firstname"){
proto_user.firstname = value;
}
else if(values[i] == "name"){
proto_user.name = value;
}
else if(values[i] == "age"){
proto_user.age = stoi(value);
}
else if(values[i] == "pin"){
proto_user.pin = stoi(value);
}
break;
}
}
}
else if(line.find("}") != STRING_ERROR){
//print_user_vars(&proto_user);
users[user_num++] = proto_user;
//cout << "Added user at " << user_num << endl;
}
//cout << line << endl;
}
for(int i = 0; i < user_num; i++){
//cout << "\nUSER: " << i + 1 << endl;
//print_user_vars(&users[i]);
}
static container con;
con.size = usercount;
for(int i = 0; i < usercount; i++){
if(i <= MAX_USERS){
// con.users[i] = users[i] didnt work, but this does
con.users[i].firstname = users[i].firstname;
con.users[i].age = users[i].age;
con.users[i].name = users[i].name;
con.users[i].pin = users[i].pin;
con.users[i].id = users[i].id;
}
}
print_user_vars(&con.users[0]);
return &con;
}
main.cpp (Calls the function)
#include <iostream>
#include "includes/users.h"
using namespace std;
int main(void){
string wasd = "w";
int id;
int pin;
cout << "\n Welcome\n\n ID\n>>> ";
cin >> id;
cout << " PIN\n>>> ";
cin >> pin;
container *con = get_users("users");
int size = con->size;
cout << "Age: " << con->users[0].age << ", PIN: " << con->users[0].pin << ", Firstname: " << con->users[0].firstname << ", Name: "
<< con->users[0].name << ", ID: " << con->users[0].id << endl;
//Functionality
return 0;
}
Simpler.cpp (Just like users.cpp, but with test values, included in main.cpp)
#include <fstream>
#include <string>
#include <iostream>
#define STRING_ERROR 4294967295
#define MAX_USERS 100000
using namespace std;
struct user
{
int id;
string firstname;
string name;
int age;
int pin;
};
struct user_container{
int size;
user users [MAX_USERS];
};
typedef struct user User;
typedef struct user_container container;
container * get_users(string path){
const int usercount = 2;
User users[usercount];
users[0].age = 59;
users[0].firstname = "Peter";
users[0].name = "Bremer";
users[0].id = 456878;
users[0].pin = 1234;
users[1].age = 8;
users[1].firstname = "a";
users[1].name = "b";
users[1].id = 456;
users[1].pin = 1111;
static container con;
con.size = usercount;
for(int i = 0; i < usercount; i++){
if(i <= MAX_USERS){
// con.users[i] = users[i] didnt work, but this does
con.users[i].firstname = users[i].firstname;
con.users[i].age = users[i].age;
con.users[i].name = users[i].name;
con.users[i].pin = users[i].pin;
con.users[i].id = users[i].id;
}
}
cout << "Usercount " << usercount << endl;
return &con;
}
int main(void){
container *con = get_users("users");
int size = con->size;
cout << "Age: " << con->users[0].age << ", PIN: " << con->users[0].pin << ", Firstname: " << con->users[0].firstname << ", Name: "
<< con->users[0].name << ", ID: " << con->users[0].id << endl;
return 0;
}
Not really the answer you are looking for:
Avoid using typedef when you don't need it. Just name your struct User, it will be available under that name without writing struct User.
And for your container, just use one of the STL containers. std::vector<User> would be a good start. This also removes the need for MAX_USERS.
struct User
{
int id;
std::string firstname;
std::string name;
int age;
int pin;
};
typedef std::vector<User> container;
With the three interfaces in user.cpp you can now just use
void print_user_vars(const User& user);
int get_usercount(const std::string& path);
container get_users(const std::string& path);
and thus get rid of the static container con; in get_users.
With a std::vector I no longer see a need for the get_usercount function.
And instead of macros go for constants (and remove magic numbers):
auto const STRING_ERROR = std::string::npos;
(Though I don't agree with the name STRING_ERROR. It's more a STRING_NOT_FOUND.)
Cleanup of print_user_vars after signature change:
void print_user_vars(const User& user)
{
std::cout << "Id: " << user.id << "\nFirstname: " << user.firstname
<< "\nName: " << user.name << "\nAge: " << user.age
<< "\nPIN: " << user.pin << std::endl;
}
And getting some inspiration from get_usercount (a method I don't believe you need):
int get_usercount(const std::string& path)
{
int usercount = 0;
std::ifstream file(path, std::ios_base::binary);
std::string line;
while(std::getline(file, line))
{
if(line.find("}") != STRING_ERROR)
{
usercount++;
}
}
return usercount;
}
This line in get_users is NOT C++. (It's part of the C99 standard):
User users[usercount];
And as #bruno points out:
else if(values[i] == "name"){
does not work. Consider
else if(std::strcmp(values[i], "name") == 0){

Getting average age of students and youngest student's name

I'm having some trouble with getting the average age of all students including getting the youngest student's name outputted. The output is supposed to come from a function call I wrote called ageCalc(...).
main.cpp
#include <iostream>
#include <fstream>
#include <iomanip>
#include "Student1.h"
#include "Student2.h"
#include "ageCalc.h"
using namespace std;
const int SIZE = 100;
int main()
{
ifstream inFile;
inFile.open("C:\\COMSC200\\a2data.input", ios::in|ios::binary);
// Open the input file – if it fails to open, display an error message and terminate
if(!inFile.is_open())
{
cout << "Unable to open file!";
return 1;
}
else
{
cout << "File successfully open!\n\n";
}
// Use a pointer array to manage all the created student variables.
Student1 **ptrArr = new Student1 *[SIZE];
Student1 s;
int total = 0;
// read the first input record
inFile.read(reinterpret_cast<char *> (&s), sizeof(s));
while(!inFile.eof())
{
// dynamically allocate space for new student variable
ptrArr[total] = new Student1;
// populate the student variable from the input
*ptrArr[total] = s;
total++;
// read the next input record
inFile.read(reinterpret_cast<char *> (&s), sizeof(s));
}
Student2 *st = new Student2[SIZE];
for(int i = 0; ptrArr[i]; i++)
{
for(char fn: ptrArr[i]->first_name)
st[i].fn += fn;
st[i].mi = ptrArr[i]->middle_int[0];
for(char ln: ptrArr[i]->last_name)
st[i].ln += ln;
st[i].cc = ptrArr[i]->campus_code;
for(char sID: ptrArr[i]->student_ID)
st[i].sID += sID;
st[i].age = atoi(ptrArr[i]->age);
}
cout << "First Name" << setw(9)
<< "MI" << setw(15)
<< "Last Name" << setw(17)
<< "Campus Code" << setw(16)
<< "Student ID" << setw(15)
<< "Age" << endl;
cout << "===================================================================================" << endl;
for(int j = 0; st[j].age != 0; j++)
{
cout << st[j].fn << setw(8);
cout << st[j].mi << " ";
cout << st[j].ln << setw(2);
cout << st[j].cc << " ";
cout << st[j].sID << setw(16);
cout << st[j].age << " " << endl;
}
Student2 *y;
int avg = ageCalc(&st, y);
cout << "Average student age is: " << avg << " years." << endl;
cout << "Youngest student is: " << arr[i]->fn << " " << arr[i]->mi << " " << arr[i]->ln << endl;
for(int x = 0; ptrArr[x]; x++)
{
delete ptrArr[x];
}
delete [] st;
inFile.close();
return 0;
}
ageCalc.cpp
#include "Student2.h"
using namespace std;
int ageCalc(Student2 *arr[], Student2 *&y)
{
int i = 0, sum = 0, index = 0, avg;
while(arr[i] != nullptr)
{
sum = arr[i]->age + sum;
i++;
if(arr[i]->age < arr[index]->age)
{
index = i;
}
}
y = arr[index];
avg = sum / i;
return avg;
}
Student1.h
#ifndef STUDENT1_H_
#define STUDENT1_H_
#include <iostream>
using namespace std;
struct Student1
{
char first_name[10];
char middle_int[10];
char last_name[20];
char campus_code;
char student_ID[8];
char age[3];
};
#endif
Student2.h
#ifndef STUDENT2_H_
#define STUDENT2_H_
#include <iostream>
#include <string>
using namespace std;
struct Student2
{
string fn;
char mi;
string ln;
char cc;
string sID;
short int age;
};
#endif
ageCalc.h
#ifndef AGECALC_H_
#define AGECALC_H_
#include "Student2.h"
int ageCalc(Student2 *[], Student2 *&);
#endif

ifstream::read not working?

I am trying to read from a .csv file. There are two functions below, one for writing and one for reading.
The file contains a simple table:
date,first,second
1 a one
2 b two
3 c three
4 c four
For some reason, the statement while(file_stream.read(&c,1)); does not read anything. It stops at the first character and I'm dumbfounded as to why. Any clues?
#include <iostream>
#include <sstream>
#include <fstream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <cstdlib>
using namespace std;
std::string filename;
std::string line_string;
ifstream file_stream;
stringstream ss;
vector< vector<string> > vec;
char c;
void read_file()
{
filename = "test.csv";
cout << filename << endl;
file_stream.open(filename.c_str(),ios::out|ios::binary);
if(file_stream.fail())
{
cout << "File didn't open" << endl;
return;
}
if(file_stream.is_open())
cout << "file opened" << endl;
while(file_stream.read(&c,1)); // this isn't working
{
cout <<"char c is: " << c;
ss << noskipws << c;
}
file_stream.close();
cout << "string is: " << ss.str() << endl;
//get each line
int counter = 0;
vector<string> invec;
while(getline(ss,line_string,'\n'))
{
string header_string;
stringstream header_stream;
header_stream << line_string;
while(getline(header_stream, header_string,','))
{
invec.push_back(header_string);
}
invec.push_back(header_string);
vec.push_back(invec);
invec.clear();
counter++;
}
}
void test_output()
{
for(int i = 0; i < vec.size();i++)
{
for(int in = 0; in < vec[0].size(); in++)
cout << vec[i][in] << " ";
cout << endl;
}
}
int main()
{
read_file();
test_output();
}
Look very very carefully at the line that is not working:
while(file_stream.read(&c,1)); // this isn't working
{
cout <<"char c is: " << c;
ss << noskipws << c;
}
The ; character at the end of the while statement does NOT belong! You are running a no-body loop that does not terminate until read() fails, and THEN your code enters the bracketed block to output the last character that was successfully read (if any).
You need to remove that erroneous ; character:
while(file_stream.read(&c,1)) // this works
{
cout <<"char c is: " << c;
ss << noskipws << c;
}
Now, the real question is - why are you reading the input file character-by-character into a std::stringstream in the first place? You can use std::getline() with the input std::ifstream directly:
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
std::vector< std::vector<std::string> > vec;
void read_file()
{
std::string filename = "test.csv";
std::cout << filename << std::endl;
std::ifstream file_stream;
file_stream.open(filename.c_str(), ios::binary);
if (!file_stream)
{
std::cout << "File didn't open" << std::endl;
return;
}
std::cout << "file opened" << std::endl;
//get each line
std::vector<std::string> invec;
std::string line;
int counter = 0;
if (std::getline(file_stream, line))
{
std::istringstream iss(line);
while (std::getline(iss, line, ','))
invec.push_back(line);
vec.push_back(invec);
invec.clear();
++counter;
while (std::getline(file_stream, line))
{
iss.str(line);
while (iss >> line)
invec.push_back(line);
vec.push_back(invec);
invec.clear();
++counter;
}
}
}
void test_output()
{
if (!vec.empty())
{
for(int in = 0; in < vec[0].size(); ++in)
std::cout << vec[0][in] << ",";
std::cout << std::endl;
for(int i = 1; i < vec.size(); ++i)
{
for(int in = 0; in < vec[i].size(); ++in)
std::cout << vec[i][in] << " ";
std::cout << std::endl;
}
}
}
int main()
{
read_file();
test_output();
}

Floating Point Exception while reading from file

the program should read from 2 files (author.dat and citation.dat) and save them into a map and set;
first it reads the citationlist without problem, then it seems to properly read the authors and after it went through the whole list (author.dat) a floating point exception arises .. can't quite figure out why
seems to happen in author.cpp inside the constructor for authorlist
author.cpp:
#include <fstream>
#include <iostream>
#include "authors.h"
using namespace std;
AuthorList::AuthorList(char *fileName) {
ifstream s (fileName);
int idTemp;
int nrTemp;
string nameTemp;
try {
while (true){
s >> idTemp >> nrTemp >> nameTemp;
cout << idTemp << " " << nrTemp << " " << nameTemp << " test_string";
authors.insert(std::make_pair(idTemp,Author(idTemp,nrTemp,nameTemp)));
if (!s){
cout << "IF-CLAUSE";
throw EOFException();
}
cout << "WHILE-LOOP_END" << endl;
}
} catch (EOFException){}
}
author.h:
#ifndef CPP_AUTHORS_H
#define CPP_AUTHORS_H
#include <iostream>
#include <map>
#include <string>
#include "citations.h"
class Author {
public:
Author (int id, int nr, std::string name) :
articleID(id),
authorNR(nr),
authorName(name){}
int getArticleID() const {
return articleID;
}
std::string getAuthorName() const {
return authorName;
}
private:
int articleID;
int authorNR;
std::string authorName;
};
class AuthorList {
public:
AuthorList(char *fileName);
std::pair<std::multimap<int,Author>::const_iterator, std::multimap<int,Author>::const_iterator> findAuthors(int articleID) {
return authors.equal_range(articleID);
}
private:
std::multimap<int,Author> authors;
};
#endif //CPP_AUTHORS_H
programm.cpp:
#include <iostream>
#include <cstdlib>
#include "citations.h"
#include "authors.h"
#include "authorCitation.h"
using namespace std;
int main(int argc, char *argv[]){
CitationList *cl;
AuthorList *al;
//check if argv array has its supposed length
if (argc != 4){
cerr << "usage: programm article.dat citation.dat author.dat";
return EXIT_FAILURE;
}
//inserting citation.dat and author.dat in corresponding lists (article.dat not used)
cl = new CitationList(argv[2]);
al = new AuthorList(argv[3]);
try {
AuthorCitationList *acl;
acl->createAuthorCitationList(al,cl);
acl->printAuthorCitationList2File("authorcitation.dat");
} catch (EOFException){
cerr << "something went wrong while writing to file";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
All files:
https://drive.google.com/file/d/0B734gx5Q_mVAV0xWRG1KX0JuYW8/view?usp=sharing
I am willing to bet that the problem is caused by the following lines of code:
AuthorCitationList *acl;
acl->createAuthorCitationList(al,cl);
You are calling a member function using an uninitialized pointer. I suggest changing the first line to:
AuthorCitationList *acl = new AuthorCitationList;
Add any necessary arguments to the constructor.
While you are at it, change the loop for reading the data also. You have:
while (true){
s >> idTemp >> nrTemp >> nameTemp;
cout << idTemp << " " << nrTemp << " " << nameTemp << " test_string";
authors.insert(std::make_pair(idTemp,Author(idTemp,nrTemp,nameTemp)));
if (!s){
cout << "IF-CLAUSE";
throw EOFException();
}
cout << "WHILE-LOOP_END" << endl;
}
When you do that, you end up adding data once after the end of line has been reached. Also, you seem to have the last line in the wrong place. It seems to me that it should be outside the while loop.
You can use:
while (true){
s >> idTemp >> nrTemp >> nameTemp;
// Break out of the loop when reading the
// data is not successful.
if (!s){
cout << "IF-CLAUSE";
throw EOFException();
}
cout << idTemp << " " << nrTemp << " " << nameTemp << " test_string";
authors.insert(std::make_pair(idTemp,Author(idTemp,nrTemp,nameTemp)));
}
cout << "WHILE-LOOP_END" << endl;
You can simplify it further by using:
while (s >> idTemp >> nrTemp >> nameTemp){
cout << idTemp << " " << nrTemp << " " << nameTemp << " test_string";
authors.insert(std::make_pair(idTemp,Author(idTemp,nrTemp,nameTemp)));
}
cout << "WHILE-LOOP_END" << endl;

C++ read/write to binary file. on program exit it gives System.AccessViolationException

This C++ program is created using Visual Studio 2010. It's a group project that has everyone in class stumped.
The program initially starts fine and the user can run through the program and add items that are written out to file. the items are read back in and displayed. When the user is done, on the program exiting return 0; it gives me "An unhandled exception of type System.AccessViolationException occurred. Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
When this happens it opens up a file called utility here => for (_Iterator_base12 **_Pnext = &_Myproxy->_Myfirstiter; *_Pnext != 0; *_Pnext = (*_Pnext)->_Mynextiter) (*_Pnext)->_Myproxy = 0.
I can fix this by replacing return 0; with exit(0);
I know it's not a real fix though and just a band-aid over a bullet hole that is causing this issue.
After fixing (used very loosely here) that, then running the program again, it attempts to load the data file from the file system. It reads and loads the 1st item into a vector correctly but when it goes back to the start of the loop we see the same exception pop up, An unhandled exception of type System.AccessViolationException occurred.
This is the first project we have worked on using fstream and binary i/o. We had worked through a similar program that was just reading and writing strings w/out any issues.I believe that the issue stems from something in the fileHandler class but am having a difficult time pinpointing what is causing this issue.Any advice/help is greatly appreciated.Here is the code.stdafx.h
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <sstream>
#include <fstream>
#include <string.h>
#include <string>
#include <vector>
#include <time.h>
Week2.cpp (the main file for the project)
//Week2.cpp *******************
#include "stdafx.h"
#include "fileHandler.h"
using namespace std;
using namespace System;
int main(array<System::String ^> ^args)
{
fileHandler theFile("store.pkl");
vector<item> itemStack = theFile.getFile();
cout << "SKU Name Dept Vendor Max Order onHand" << endl;
cout << "-------------------------------------------" << endl;
for (int i = 0; i < itemStack.size(); i++)
{
cout << itemStack[i].toString() << endl;
}
vector<item> newStack;
//prompt for input
bool doneEditing = false;
while(!doneEditing)
{
int A;
int E;
int F;
int G;
string B;
string C;
string D;
string tempString;
cout << "Enter item info:" << endl << "Item SKU: ";
cin >> A;
cout << endl << "Item Name: ";
cin >> B;
cout << endl << "Item Dept: ";
cin >> C;
cout << endl << "Vendor Name: ";
cin >> D;
cout << endl << "Max Number: ";
cin >> E;
cout << endl << "Reorder Number: ";
cin >> F;
cout << endl << "OnHand Number: ";
cin >> G;
cout << endl << "Done?? Y/N: ";
cin >> tempString;
cout << endl;
item tempItem = item(A, B, C, D, E, F, G);
newStack.push_back(tempItem);
if (tempString == "Y" || tempString == "y")
{
doneEditing = true;
}
}
cout << "Saving stack to file" << endl;
theFile.putFile(newStack);
cout << "Items written to file" << endl;
vector<item> newFileStack = theFile.getFile();
cout << "After reload: " << endl;
cout << "SKU Name Dept Vendor Max Order onHand" << endl;
cout << "-------------------------------------------" << endl;
for (int i = 0; i < newFileStack.size(); i++)
{
cout << newFileStack[i].toString() << endl;
}
cout << "Thank you for using the Awesome Grocery Inventory Application" << endl;
system("PAUSE");
/*return 0; this breaks with same error as
when reading in saved file after application restart
*/
exit(0);
}
item.h
using namespace std;
#pragma once
class item
{
public:
item();
item(int sku, string name, string dept, string vendor, int max, int reorder, int onhand);
~item(void);
string toString();
int ItemSKU() const;
void ItemSKU(int val);
string ItemName() const;
void ItemName(string val);
string VendorName() const;
void VendorName(string val);
int MaxNumb() const;
void MaxNumb(int val);
int ReorderNumb() const;
void ReorderNumb(int val);
int OnHandNumb() const;
void OnHandNumb(int val);
private:
int itemSKU;
string itemName;
string itemDept;
string vendorName;
int maxNumb;
int reorderNumb;
int onHandNumb;
};
item.cpp
#include "StdAfx.h"
#include "item.h"
using namespace std;
item::item()
{
};
item::item(int sku, string name, string dept, string vendor, int max, int reorder, int onhand)
{
itemSKU = sku;
itemName = name;
itemDept = dept;
vendorName = vendor;
maxNumb = max;
reorderNumb = reorder;
onHandNumb = onhand;
}
item::~item(void)
{
}
string item::toString()
{
stringstream ss;
ss << itemSKU << "\t" << itemName << "\t" << itemDept << "\t" << vendorName << "\t" << maxNumb << "\t" << reorderNumb << "\t" << onHandNumb;
string s = ss.str();
return s;
}
int item::ItemSKU() const { return itemSKU; }
void item::ItemSKU(int val) { itemSKU = val; }
string item::ItemName() const { return itemName; }
void item::ItemName(string val) { itemName = val; }
string item::VendorName() const { return vendorName; }
void item::VendorName(string val) { vendorName = val; }
int item::MaxNumb() const { return maxNumb; }
void item::MaxNumb(int val) { maxNumb = val; }
int item::ReorderNumb() const { return reorderNumb; }
void item::ReorderNumb(int val) { reorderNumb = val; }
int item::OnHandNumb() const { return onHandNumb; }
void item::OnHandNumb(int val) { onHandNumb = val; }
fileHandler.h
#include "item.h"
using namespace std;
#pragma once
class fileHandler
{
public:
fileHandler(string);
~fileHandler(void);
vector<item> getFile();
void putFile(vector<item> &);
private:
string theFileName;
};
fileHandler.cpp
#include "stdafx.h"
#include "fileHandler.h"
using namespace std;
fileHandler::fileHandler(string name)
{
theFileName = name.c_str();
}
fileHandler::~fileHandler(void)
{
}
vector<item> fileHandler::getFile()
{
ifstream inFile;
string fileLine;
vector<item> localStack;
inFile.open(theFileName, ios::in|ios::binary);
if (inFile)
{
cout << "Getting file..." << endl;
cout << endl;
// not working on initial load if file is present at start
inFile.seekg(0);
while(!inFile.eof())
{
item tempItem;
inFile.read(reinterpret_cast< char * >(&tempItem), sizeof(item));
localStack.push_back(tempItem);
cout << "item added to stack" << endl;
} //breaks from here after reading in 1 item from saved file on reopen
} else {
ofstream newFile;
newFile.open(theFileName, ios::out|ios::binary);
newFile.close();
cout << "Creating new file..." << endl;
cout << endl;
inFile.open(theFileName, ios::in|ios::binary);
}
inFile.clear();
inFile.close();
if (localStack.size() > 0)
{
//removes some dirty data from end of stack
localStack.pop_back();
}
return localStack;
}
void fileHandler::putFile( vector<item> &items )
{
ofstream outFile;
outFile.open(theFileName, ios::out|ios::binary);
if(!outFile)
{
cerr<<"File could not be created"<<endl;
system("pause");
exit(1);
}
for (int i = 0; i < items.size(); i++)
{
outFile.write(reinterpret_cast<const char *>(&items[i]), sizeof(item));
}
outFile.clear();
outFile.close();
}
You cannot perform binary I/O this way with an object that contains std::string members. A std::string contains pointer(s) to dynamically allocated memory for its actual contents. You need to perform some type of serialization instead. The usual suggestion is Boost serialization.