Understanding class object [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am trying to create object that will store inside vector using pointers
I can store object inside vector when I don t use pointers, but when I try to use pointers I can not do that
// created class that combine some attributes for file "datum" = date, "vrijeme" = creation of file etc.
class datoteka{
public:
string datum;
string vrijeme;
string velicina;
string ime;
datoteka();
datoteka(string datum, string vrijeme, string velicina, string ime)
{
this -> datum = datum;
this -> vrijeme = vrijeme;
this -> velicina = velicina;
this -> ime = ime;
}
~datoteka();
};
int main()
{
vector <datoteka> fajlovi;
string linija;
string prva;
int i = 0;
datoteka * pokObjDatoteke;
pokObjDatoteke = new datoteka();
std::ifstream pisi("list.txt"); //file is open
while(getline(pisi,linija)) //get first line of file
{
string vrijednost;
stringstream red; //create stream from line
string datoteka[4]; // create array to store seperate information
red << linija;
while(!red.eof() && i != 4) // since line containt lot of tabs i
read just first for values
{
red >> vrijednost;
datoteka[i]= vrijednost;
i++;
cout << vrijednost << " ovo je vrijednost" << endl;
}
pokObjDatoteke->datum = datoteka[0];
pokObjDatoteke->vrijeme = datoteka[1];
pokObjDatoteke->velicina = datoteka[2];
pokObjDatoteke->ime = datoteka[3];
fajlovi.push_back(*pokObjDatoteke); /**** problem ****
}
return 0;
}
I want to store objects in vector, instead I get just some memory location, probably from pointer but how can I store object and not address

This:
fajlovi.push_back(*pokObjDatoteke);
stores a copy of the object pokObjDatoteke points to in the vector. The pointed-to object is then leaked, since you never delete it.
Do you really need pointers here though? Your vector contains value types, not pointers, so just use emplace_back to construct your objects directly in the vector:
while (getline(pisi, linija))
{
string vrijednost;
stringstream red;
string datoteka[4];
red << linija;
while (!red.eof() && i != 4) {
red >> vrijednost;
datoteka[i]= vrijednost;
i++;
cout << vrijednost << " ovo je vrijednost" << endl;
}
fajlovi.emplace_back(datoteka[0], datoteka[1], datoteka[2],
datoteka[3]);
}
However, if you really want pointers in your vector, then declare it as such:
vector <datoteka*> fajlovi;
and then change the push_back call in your original code to:
fajlovi.push_back(pokObjDatoteke);
This will push the pointers into the vector. You need to remember to delete them when the vector is destroyed, or else all the objects will get leaked:
for (auto* obj : fajlovi) {
delete obj;
}
Manual memory management like this is error-prone and a headache. Don't do it. Use smart pointers instead, like shared_ptr. Remove these lines in your original code:
vector <datoteka> fajlovi;
// ...
datoteka * pokObjDatoteke;
pokObjDatoteke = new datoteka();
and replace them with:
#include <memory>
// ...
vector <shared_ptr<datoteka>> fajlovi;
// ...
auto pokObjDatoteke = make_shared<datoteka>();
and then push_back with:
fajlovi.push_back(pokObjDatoteke);
No need to call new or delete.
However, again, it does not look like you need pointers at all. You can just use value types as shown in the beginning of this answer.

If you want to store objects, then why are you using pointers?
datoteka pokObjDatoteke;
while (...)
{
...
pokObjDatoteke.datum = datoteka[0];
pokObjDatoteke.vrijeme = datoteka[1];
pokObjDatoteke.velicina = datoteka[2];
pokObjDatoteke.ime = datoteka[3];
fajlovi.push_back(pokObjDatoteke);
}
Why are you trying to use pointers when, like you said, not using pointers works?

While the OP didn't disclose an example of the input file, this line (besides all the issues pointed out in the other answers) seems suspicious
while(!red.eof() && i != 4) {...}
See e.g. Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
A better pattern is to perform the extraction and then check if it was successful.
while( some_stream >> some_data ) {...}
OP's code could be rewritten into something like this
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
class datum
{
std::string a_, b_, c_, d_;
public:
datum() = default;
datum(std::string const &a, std::string const &b, std::string const &c, std::string const &d)
: a_(a), b_(b), c_(c), d_(d)
{}
friend std::istream &operator>> (std::istream &is, datum &obj)
{
return is >> obj.a_ >> obj.b_ >> obj.c_ >> obj.d_;
}
friend std::ostream &operator<< (std::ostream &os, datum const &obj)
{
return os << "a: '" << obj.a_ << "', b: '"<< obj.b_
<< "', c: '" << obj.c_ << "', d: '" << obj.d_ << '\'';
}
};
int main()
{
std::vector<datum> data;
std::ifstream in_stream {"list.txt"};
if ( !in_stream )
{
std::cout << "Error: unable to open input file.\n";
return -1;
}
std::string line, junk;
while(getline(in_stream, line))
{
// This won't consider an error to have empty lines in the file
if (line.empty())
continue;
std::istringstream iss(line);
datum dd;
iss >> dd;
// Stops if there are more or less strings than required in the line
if ( !iss or iss >> junk)
break;
data.push_back(std::move(dd));
}
for (auto const & d : data)
std::cout << d << '\n';
}
Testable here.

Related

Writing a vector of objects to file and then reading it

I'm new to C++ and stackoverflow so forgive me any mistakes in my post ;). I need to create a code, which allows me to fill new objects with data from std::cin and export these objects to binary file later. Also, I need to import objects exported to file at some point. Objects represent users with standard user information like username, ID, lvl etc.
#include <vector>
#include <string>
#include <iostream>
class User {
std::string username;
unsigned int ID, lvl;
public:
User(std::string un, int uID, int ulvl) {
username = un;
ID = uID;
lvl = ulvl;
}
};
int main() {
std::string u_name;
int u_ID,u_lvl;
bool finish = false;
char choice;
std::vector<User> test_user_vec;
do {
std::cout << "Enter username: ";
std::cin >> u_name;
std::cout << "Enter ID: ";
std::cin >> u_ID;
std::cout << "Enter lvl: ";
std::cin >> u_lvl;
test_user_vec.push_back(User(u_name, u_ID, u_lvl));
std::cout << "Do you want to add another user? (y/n)?";
choice = getch();
if (choice == 'y') finish = true;
} while (!finish);
return 0;
}
I assume that test_user_vec stores every object I created while my program is running. My problem occurs when I want to export that vector to file. The purpose of this action is to store objects' data even after my program terminates and import all the data when I run my program again.
I was trying to solve this problem on my own, nothing really came to my mind. While I was looking for some info i found something like this:
#include <fstream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> v{ "one", "two", "three" };
std::ofstream outFile("my_file.txt");
// the important part
for (const auto &e : v) outFile << e << "\n";
}
I've tested it with <string> and <int> vectors and my variables. It's good until I try to export <object>vector.
Also i found another solution and tried to do something with it on another test code:
class Test {
public:
int number;
float number2;
};
int main(){
Test test1;
test1.number = 122;
test1.number2=12;
std::fstream testfile("test1.bin", std::ios::out | std::ios::binary);
testfile.write((char*)&test1, sizeof(test1));
testfile.close();
//ater writing an object with variables i commented this section
//then uncommented this section and run the program again
std::fstream testfile2("test1.bin", std::ios::in);
testfile2.read((char*)&test1, sizeof(test1));
std::cout << test1.number;
testfile2.close();
return 0;
}
Again, it works, i can read test1.number until I want to use vector of objects, not a single object. With vector of objects my cout printed some random values like 11314123e-03.
I was trying to somehow combine these 2 solutions, but nothing worked out. I would like to have a binary file, because i heard it's faster and has any data protection (i can't just open it in notepad and read the data) I'm new to c++, there is a great chance of me trying to do it reeeeeealy inefficient way, so pls help :D.
Data member getter functions can be added to the User class and used in fstream output operations. This should provide the general idea:
std::string userName;
for (const auto &u : v)
{
outFile.write(u.GetID(), sizeof(int));
outFile.write(u.GetLvl(), sizeof(int));
userName = u.GetName();
outFile.write(username.length(), sizeof(size_t));
outFile.write(userName.data(), username.length());
}
For userName, the length is written to precede the userName string data in the file so that the file can be parsed when read. The binary encoding/convention is designer's decision as there are several options. Another option would be to encode the entire object as a null-terminated string, although this would generally be less size efficient except for the userName string itself.
Note: test_user_vec.push_back(User(u_name, u_ID, u_lvl)); is creating temporary User objects on the stack. As #drescherjm and #RaymondChen pointed out, that is OK, but this is a better alternative: test_user_vec.emplace_back(...);

c++ String from file to vector - more elegant way

I write a code in which I want to pass several strings from text file to string vector. Currently I do this that way:
using namespace std;
int main()
{
string list_name="LIST";
ifstream REF;
REF.open(list_name.c_str());
vector<string> titles;
for(auto i=0;;i++)
{
REF>>list_name;
if(list_name=="-1"){break;}
titles.push_back(list_name);
}
REF.close();
cout<<titles.size();
for(unsigned int i=0; i<titles.size(); i++)
{
cout<<endl<<titles[i];
}
It works fine, I get the output as expected. My concern is is there more elegant way to pass string from text file to vector directly, avoiding this fragment, when passing string from filestream to string object and assigning it to the vector with push_back as separate step:
REF>>list_name;
if(list_name=="-1"){break;}
titles.push_back(list_name);
More elegant way with algorithms
std::copy_if(std::istream_iterator<std::string>(REF),
std::istream_iterator<std::string>(),
std::back_inserter(titles),
[](const std::string& t) { return t != "-1"; });
The other answers are maybe too complicated or too complex.
Let me first do a small review of your code. Please see my comments within the code:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std; // You should not open the full std namespace. Better to use full qualifiacation
int main()
{
string list_name = "LIST";
ifstream REF; // Here you coud directly use the construct ofr the istream, which will open the file for you
REF.open(list_name.c_str()); // No need to use c_str
vector<string> titles; // All variables should be initialized. Use {}
for (auto i = 0;; i++) // Endless loop. You could also write for(;;), but bad design
{
REF >> list_name;
if (list_name == "-1") { break; } // Break out of the endless loop. Bad design. Curly braces not needed
titles.push_back(list_name);
}
REF.close(); // No nbeed to close the file. With RAII, the destructor of the istream will close the file for you
cout << titles.size();
for (unsigned int i = 0; i < titles.size(); i++) // Better to use a range based for loop
{
cout << endl << titles[i]; // end not recommended. For cout`'\n' is beter, because it does not call flush unneccesarily.
}
}
You see many points for improvement.
Let me explain some of the more important topics to you.
You should use the std::ifstreams constructor to directly open the file.
Always check the result of such an operation. The bool and ! operator for the std::ifstream are overwritten. So a simple test can be done
Not need to close the file. The Destructor of the std::ifstream will do that for you.
There is a standard approach on how to read a file. Please see below.
If you want to read file until EOF (end of file) or any other condition, you can simply use a while loop and call the extraction operator >>
For example:
while (REF >> list_name) {
titles.push_back(list_name);
}
Why does this work? The extraction operator will always return a reference to the stream with what it was called. So, you can imagine that after reading the string, the while would contain while (REF), because REF was returned by (REF >> list_name. And, as mentioned already, the bool operator of the stream is overwritten and returns the state of the stream. If there would be any error or EOF, then if (REF) would be false.
So and now the additional condition: A comparison with "-1" can be easily added to the while statement.
while ((REF >> list_name) and (list_name != "-1")) {
titles.push_back(list_name);
}
This is a safe operatrion, because of boolean short-cut evaluation. If the first condition is already false, the second will not be evaluated.
With all the knwo-how above, the code could be refactored to:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
int main() {
// Here our source data is stored
const std::string fileName{ "list.txt" };
// Open the file and check, if it could be opened
std::ifstream fileStream{ fileName };
if (fileStream) {
// Here we will store all titles that we read from the file
std::vector<std::string> titles{};
// Now read all data and store vit in our resulting vector
std::string tempTitle{};
while ((fileStream >> tempTitle) and (tempTitle != "-1"))
titles.push_back(tempTitle);
// For debug purposes. Show all titles on screen:
for (const std::string title : titles)
std::cout << '\n' << title;
}
else std::cerr << "\n*** Error: Could not open file '" << fileName << "'\n";
}
If you knew the number of strings to read beforehand, you could
using StringVector = std::vector<std::string>;
int main(int argc, const char* argv) {
constexpr size_t N = 4; // or however many strings you want...
StringVector data(N);
std::ifstream stream("foo.txt");
for (size_t i =0; (i < N) && stream; i++) {
stream >> data[i];
}
}
But this would be less flexible and it would be trickier to implement your "-1" "terminator" convention.
If that "-1" thing is a true requirement (in contrast to an arbitrary choice), and if you use this more than once, it might pay off to "abstract", how you read those strings. Abstraction is usually done in form of a function.
// compile with:
// clang++-13 -std=c++20 -g -O3 -o words words.cpp
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using StringVector = std::vector<std::string>;
std::istream& operator>> (std::istream& stream, StringVector& sv)
{
std::string word;
while (stream) {
stream >> word;
if (word == "-1")
return stream;
sv.push_back(word);
}
return stream;
}
std::ostream& operator<< (std::ostream& stream,
const StringVector& sv) {
for (const auto& s : sv) {
stream << s << std::endl;
}
return stream;
}
int main(int argc, const char* argv[]) {
std::string file_data{R"(word1 word2
word3
word4 -1)"};
std::istringstream stream(file_data);
StringVector data;
data.reserve(10);
stream >> data;
std::cout
<< "Number of strings loaded: "
<< data.size() << std::endl;
std::cout << data;
return 0;
}
The above operator>>() works for streams in general, so it also works for file streams.
As an aside: One reason, why people would not like the "-1" terminator approach is performance. If you keep pushing into a vector an arbitrary amount of times, the storage of the vector needs to be re-allocated as the vector grows, which is avoidable overhead. So, usually people would use another file format, e.g. giving the number of strings first, then the strings, which would allow for:
size_t n;
stream >> n;
StringVector data;
data.reserve(n); // avoids "spurious reallocs as we load the strings"
for (size_t i = 0; i < n; i++) { ... }

C++ map empty after inserting data.

Firstly, Happy new year to those who come across my question.
I'm currently learning C++ and I have a class project to complete.
In a nutshell, my code (so far) is supposed to instantiate student objects with details read from a txt file (name, reg-number, and a map of ) and add the student to a list.
I then read a second txt file (consisting of reg-number, course code and mark) and check if there is a match of student reg numbers between whats read and the list.
if there is a match, I should insert the marks read from the txt file into the map (part of the student object), such that afterwards, each student has a map containing the courses taken and marks achieved
I seem to be creating the list fine, then I use a stringstream to read the second file and loop through the list to compare reg-numbers.
if there is a match I then call the add mark method to add marks to the map.
Here's the thing.. If after I completed the map inserting, I loop and print a map of a student, the map is empty. for all students. To confirm this I used map.size().
I have tried many ways to understand and rectify the issue but it seems i'm missing the point of something. Instinct tells me that the add mark method is copying a reference to the variable passed, which is then destroyed by the stringstream in the main method, thus showing no data in the map. unfortunately, I can't change any code within the header files, only implement what's declared.
after reading the std library docs for strings, maps etc, and attempting numerous ways of correcting the behaviour, I'm at a loss.
Any advice would be greatly appreciated so I can continue with the project and better understand what is happening. I have added the files below. there is also a Person base class but I havnt changed this as it consists of only a setter and getter.
Many thanks in advance.
student Header:
#ifndef _STUDENT_H_
#define _STUDENT_H_
#include <string>
#include <map>
#include <stdexcept>
#include "Person.h"
using namespace std;
class NoMarkException: public exception
{
};
class Student: public Person
{ public:
// constructor should initialise name and registration number using arguments
// and initialise marks map to be empty
Student(const string &name, int regNo);
// method to return registration number
int getRegNo() const;
// method to add the mark to the map
// if a mark for the module is already present it should be overwritten
void addMark(const string& module, float mark);
// method to retrieve the mark for a module
// should throw NoMarkException if student has no mark for that module
float getMark(const string &module) const throw (NoMarkException);
private:
int regNo;
map<string, float> marks; // keys are modules, values are marks in range 0.0 to 100.0
// friend function to output details of student to stream
// should output name, regno, and minimum, maximum and average marks on a single line
// if the student has no marks "has no marks" should be output instead of the marks
friend ostream& operator<<(ostream &str, const Student &s);
};
#endif
Student.cpp file:
#include <iostream>
#include "Student.h"
#include "Person.h"
using namespace std;
//constructor makes a student object and initialises the map; marks.
Student::Student(const string &name, int regNo) : Person(name) {
this->name = name;
this->regNo = regNo;
map<string, float> marks;
}
//implemented from the header file. Returns the registration number.
int Student::getRegNo() const {
return regNo;
}
// implemented as per header file request. adds marks to the map. if a mark exists, then it is overwritten.
void Student::addMark(const string &module, float mark) {
marks[module] = mark;
cout << "added: " << marks[module]<< endl;
}
//used to find marks in a map.
float Student::getMark(const string &module) const throw (NoMarkException) {
auto search = marks.find(module);
//line to test the map size after using addMark.
cout << "size after inputted values: "<< marks.size();
return marks[module];
}
main.cpp file
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <list>
#include "Student.h"
using namespace std;
//main method to obtain a file name from a user and read the file.
//method passes each .. to student.cpp
int main() {
//setting up variables required
string fileName;
const string fileEnd = ".txt";
string line;
string line2;
ifstream file;
int reg;
int reg2;
string studName;
string lastName;
float mark;
string module;
list<Student> listOfStudents;
cout << "Please enter a file name to access..." << std::endl;
cin >> fileName;
fileName += fileEnd;
// opening file an reading its contents. values are prepared and sent to the Student constructor. Fills a list
// with student objects created with variables read from the studs.txt file.
//checks file is found and exits the program if not
file.open(fileName);
if (!file) {
cerr << "Unable to open file " << fileName << endl;
exit(1);
}
while (getline (file, line)) {
stringstream stream (line);
stream >> reg >> studName >> lastName;
studName += (' ' + lastName);
cout << "Student: " << studName << " has been created." << endl;
listOfStudents.push_front(Student(studName, reg));
}
file.close();
cout << "The list of students has been created :)" << endl << endl;
cout << "Please enter the name of the next file to open"<< endl;
cout << listOfStudents.size()<<endl;
// opening second file. If file not found, exit with an error code.
// otherwise read each line, separate the three words into variables, then loop through the previously created list
//and look for a match of regNo. if true then call the addMark method to add the module and mark to the student's map.
cin >> fileName;
fileName += fileEnd;
file.open(fileName);
if (!file) {
cerr << "Unable to open file " << fileName << endl;
exit(1);
}
while(getline(file, line))
{
istringstream line_stream(line);
line_stream >> reg2 >> module >> mark;
for(Student stud : listOfStudents){
if(stud.getRegNo() == reg2){//out << "Match reg2: " << reg2 << " with stud: " << stud.getName() <<stud.getRegNo()<< endl;
stud.addMark(module,mark); }
}
}
//testing the get mark method of student class. with a module that is in the map. expecting a result
for(Student s :listOfStudents){
cout << s.getMark("CE151") << endl;
}
return 0;
}
You create a temporary copy of Student each time you're going to addMark, and discard it afterwards. You need not to copy it, but use reference, like this:
for (auto& stud: listOfStudents) /* stud.addMark */
It would also be a good idea to avoid copying Student when you print the results:
for (const auto& stud: listOfStudents) /* stud.getMark */
Aaaand one more thing:
float getMark(const string &module) const throw (NoMarkException);
Dynamic exception specification is deprecated in C++11 and removed in later standards. It is considered to be a bad practice and should be avoided.
The answer by user: grungegurunge is pretty much the one you are looking for. However, after looking at your class. I noticed that in the private section for the member variables you have declared map<string, float> marks which is okay. Yet when I look at your class's constructor after you set the name and regNo it appears that you are declaring another map<string, float> named marks where this one is local to the constructor only and does nothing. You create local memory on the stack with automatic storage, never use it, then it gets destroyed after the object goes out of scope; it is unnecessary to have it declared here.
//constructor makes a student object and initialises the map; marks.
Student::Student(const string &name, int regNo) : Person(name) {
this->name = name;
this->regNo = regNo;
// map<string, float> marks; // this line is not needed.
}

C++ Read in a file like a grid

I'm coding in C++ and I'm trying to read in a file that I'd like to access certain chars at later. As in, what is the char at (line x, char y), at any given point in the file.
My only thought right now is to look for a newline character, and somehow index them so that I can refer back to newline x, check the length of a line, and pull a char at whatever position given the line length.
I'm not sure if that is a good approach or not.
Try this (for character in line "lineNum" and column "columnNum"):
ifstream inf;
inf.open(filename); //filename being c-string
string str;
for (int i = 0; i < lineNum; i++)
{
std::getline(inf, str);
}
This way "str" stores the line you are interested in (automatically checks for newline character and stops).
Then you can use:
char chr = str[columnNum];
to store the character you want in "chr" variable. And don't forget:
inf.close();
Unfortunately, to my knowledge you need to repeat this process every time you want to access a character.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#define FILENAME "File.txt"
class FileGrid {
public:
typedef std::vector<std::string> Line;
typedef std::vector<std::string>::const_iterator LineIter;
typedef std::vector<std::vector<std::string>> StringMap;
typedef std::vector<std::vector<std::string>>::const_iterator StringMapIter;
void FillGrid(char* fileName) {
grid.clear();
std::ifstream in(FILENAME, std::ifstream::in);
if (!in.is_open()) {
std::cout << "problem reading " << FILENAME << std::endl;
return;
}
std::string words;
std::string word;
std::stringbuf buffer;
while (in.is_open() && std::getline(in, words)) {
std::stringstream ss(words);
Line line;
while (ss >> word) {
line.push_back(word);
}
grid.push_back(line);
}
}
void PrintGrid() {
StringMapIter b = grid.begin();
StringMapIter e = grid.end();
std::cout << "\t\tFile Content:" << std::endl;
while(b != e) {
for (unsigned int i = 0; i < b->size(); ++i) {
std::cout << b->operator[](i) << " ";
}
std::cout << std::endl;
++b;
}
}
char const & GetChar(int lineNo, int charNo) {
// LineNo checks etc
Line const & line = grid[lineNo];
for(std::string const & word : line ) {
if(charNo > word.size() + 1) {
charNo -= word.size() + 1;
}
else {
return word[charNo];
}
}
throw std::exception("charNo higher");
}
private:
StringMap grid;
};
void main() {
FileGrid grid;
grid.FillGrid(FILENAME);
grid.PrintGrid();
std::cout << grid.GetChar(0, 3); // should return first line, 4th character
}
Not the best code I've ever written but pretty much what I could do in a short time.
FileGrid handles reading and accessing the data. It reads the file line by line and stores it in a std::vector. When it finishes reading a line, it pushes that into another std::vector. In the end, we have a (sort of) 2D array of strings.
Again, not the best code and definitely not the most optimized code but the idea is still the same: read from the file line by line, separate each word and put them into an array of strings. If you can't use STL, you can dynamically create a 2D array for each line but since I don't know the specific requirements of your question, I just wrote something simple and bruteforce to show you the main way of storing grid of strings into the memory.
As long as it works. But reading the entire file into memory, if that's an option, would be simpler.

std::vector<class> fills on debug but not on release

I have a class A which has several data types defined within it. Within the program, I define a vector of type A and then read from a text file into this vector.
When I am debugging, the vector "fills up" and I can read values from it - everything works as planned. However, when I build the release version and run the .exe, the vector is empty. The rest of the program works fine, it's just not pushing the values.
I'm fairly new to C++, so I am assuming it is something to do with my constructor function, or possibly how I handle the enum?. Here is my MCVE:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
enum class Type
{
Type1
};
Type convertStringToType(std::string input)
{
return Type::Type1;
}
class A
{
public:
int num;
std::string str;
Type typ;
A(int refNumber, std::string name, Type type)
{
num = refNumber;
str = name;
typ = type;
}
};
std::vector<A> readFileIntoVector(std::string filename)
{
std::ifstream readFile(filename);
std::vector<A> tempVector;
std::string tempNum = "";
std::string tempStr = "";
std::string tempTyp = "";
std::getline(readFile, tempNum, ',');
std::getline(readFile, tempStr, ',');
std::getline(readFile, tempTyp, ',');
while (readFile)
{
tempVector.push_back(A(std::stoi(tempNum), tempStr, convertStringToType(tempTyp)));
std::getline(readFile, tempNum, ',');
std::getline(readFile, tempStr, ',');
std::getline(readFile, tempTyp, ',');
}
return tempVector;
}
int main()
{
std::vector<A> exampleVector = readFileIntoVector("Text.txt");
if (exampleVector.empty() == true)
{
std::cout << "Vector is empty.";
system("PAUSE");
}
else
{
int a = 1;
do
{
std::cin >> a;
if (a == 0 || a == 1)
{
std::cout << exampleVector.at(a).num << "\n";
std::cout << exampleVector.at(a).str << "\n";
}
} while (a == 0 || a == 1);
return 0;
}
}
This is Text.txt:
1, String1, Type1,
2, String2, Type1,
As I mentioned in the comments, the most likely problem is that when you created a release build for the project, the text file which the program depends on was not included in the respective folder.
To fix it, you must include this file in that folder yourself, or find a way to indicate to VS that the program depends on that text file, that way it is copied to the release folder automatically for you. I don't use VS, so I don't know how possible that last part is, but I hope you get the idea.
There are two possibilities:
As you mentioned that you are able to get correct value while debugging in debug mode, there is a chance that you are able to read correctly from the .txt file and getting correct values in your vector, but as you are debugging in release mode you are not able to see the correct value set in the watchlist, as you may find watchlist containing garbage value in release mode even if your vector is getting the correct value.
You are not getting .txt file, but in that case you should not get velue even in debug version.