Unhandled exception when using getline [duplicate] - c++

This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 4 years ago.
I keep getting the Unhandled exception when I try to get the first letter after using getline function.
Error:
Unhandled exception at 0x7535DB52 in Lab2 - Containers and Regex.exe:
Microsoft C++ exception: std::out_of_range at memory location
0x00B5F43C.
class CodeMap
{
private:
vector<string> code;
vector<char> character;
public:
CodeMap() { character.resize(11000); }
~CodeMap() {};
void setChar(string filename)
{
string fileName = filename;
ifstream fin;
fin.open(fileName.c_str());
string line = " ";
char codeChar;
while (!fin.eof())
{
getline(fin, line);
codeChar = line.at(0); //Unhandled exception, tried to use [] instead, still error.
}
fin.close();
}
I wondered what is going on here.
Anyway to fix this?
Thanks for helping.

As the linked answer says (in the comment by #NeilButterworth), you cannot use the EOF condition to determine if you can do another read, only if the last read "failed". In the code above when getline finally fails (which it will), you'll have an empty line variable, which you then do an access on.
Try to do while(std::getline(fin, line)) { ... instead. That way, when getline fails, you're not using the contents of the (empty) line.

Related

trying to give a variable to ifstream in c++ [duplicate]

This question already has answers here:
Put A String In A ifstream Method [duplicate]
(2 answers)
No matching function - ifstream open()
(1 answer)
Closed 3 years ago.
im new to c++ and trying to put a variable in this line : ifstream studentPaper(paper);
ill pass paper to this function and want to use it there. string paper has my files location (/name/file.txt)
if i put my file name there i dont get any errors = ifstream studentPaper("/name/file.txt");
but when i save my files location in to a string and give string to it ill get error = ifstream studentPaper(paper);
how can i do that without getting errors
void matchGrades(string paper) {
string aa= "asd";
ifstream studentPaper(paper);
ifstream base("base.txt");
int grade=3;
while ((!studentPaper.eof()) && (!base.eof())) {
string l1,l2;
getline(studentPaper,l1);
getline(base,l2);
if(l1==l2){
grade += 3;
} else {
grade -= 3;
}
}
studentPaper.close();
base.close();
cout << grade;
I think that You have to use removed string parameter "/name/file.txt" because parameter split space.
Try doing ifstream studentPaper(paper.c_str()).
Also if your file is located where your main.cpp is you won't need to specify the path. Something like this:
string studentFile = "student_file.txt";
Based on the information provided. If you are still getting an error please post it so that I can adjust my answer.

C++ read from file last record shows two times [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why is iostream::eof inside a loop condition considered wrong?
I have the following piece of code:
ifstream f("x.txt");
string line;
while (f.good()) {
getline(f, line);
// Use line here.
}
But this reads the last line twice. Why does this happen and how do I fix it?
Something very similar happens with:
ifstream f("x.txt");
string line;
while (!f.eof()) {
getline(f, line);
// Use line here.
}
You very, very rarely want to check bad, eof, and good. In particular for eof (as !stream.eof() is a common mistake), the stream currently being at EOF does not necessarily mean the last input operation failed; conversely, not being at EOF does not mean the last input was successful.
All of the stream state functions – fail, bad, eof, and good – tell you the current state of the stream rather than predicting the success of a future operation. Check the stream itself (which is equivalent to an inverted fail check) after the desired operation:
if (getline(stream, line)) {
use(line);
}
else {
handle_error();
}
if (stream >> foo >> bar) {
use(foo, bar);
}
else {
handle_error();
}
if (!(stream >> foo)) { // operator! is overloaded for streams
throw SomeException();
}
use(foo);
To read and process all lines:
for (std::string line; getline(stream, line);) {
process(line);
}
Pointedly, good() is misnamed and is not equivalent to testing the stream itself (which the above examples do).
Just use
ifstream f("x.txt");
while (getline(f, line)) {
// whatever
}
This is the idiomatic way to write such a loop. I've not been able to reproduce the error (on a Linux machine).
It didn't read the last line twice but because it failed to read when it reached eof, your string line has the value it had previously.
That is because f is no longer "good" when it has read EOF, not when it is about to read it.

Number of Words in a file, c++ [duplicate]

This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 7 years ago.
I am trying to count the number of words in a file, I know this question has been asked but I have tried some implementations I have seen but I keep getting an error.
The line in the file I am reading is "Super Chill" but when I run the code I get a count 3, where >> gets Super the first time and then Chill twice. I have a couple questions regarding this method:
1) what does While(in) look for? How does it know when to stop?
2) Why is "Chill" getting stored twice with >>?
Here is the code
int countWords(std::istream& in){ // line in file is -> Super Chill
int count = 0;
std::string word;
while (in) {
in >> word;
if (word != "") {
count+= 1;
}
}
return count;
}
while (in) checks if no error has occurred. It's the same as writing while (!in.fail())
After you call in >> word and get the first "Chill", while (in) still is true, until the next call to in >> word. When you hit in >> word again it fails because it's at the end of the file and doesn't write anything to word, but the word variable still has "Chill" in it from the last time, so you count it a second time. Then the while (in) finally fails on the next iteration.
Calling while (in >> word) { ++count; } works because in >> word is actually the function in.operator>>(word) which happens to return an istream&, and an istream has an operator bool method which allows you to use it in a condition instead of writing !in.fail(). Sort of roundabout, I know. Point is, it calls in >> word, then checks if (in) and if it passes then calls ++count; and iterates again. Versus your original technique which counted the previous word even if in >> word failed.
To make this clearer, it might help to know that changing your original code's if statement to if (in) would have also worked, but would be sort of bad code.
As a final conclusion, the entire function could be written as:
int countWords(std::istream& in) {
int count = 0;
for (std::string word; in >> word; ++count) {}
return count;
}
I see you've already gotten one solution to the problem you posted. You might want to consider another possibility though:
int countWords(std::istream& in){
return std::distance(std::istream_iterator<std::string>(in),
std::istream_iterator<std::string>());
}
This doesn't actually eliminate the loop, but it hides it inside of std::distance where it's pretty difficult to mess things up.

Getting an out_of_range: vector error for c++ but can't figure out why

This is my code:
StockAccount::StockAccount() {
vector<string> temp;
string line;
std::ifstream stockfile("Results.txt");
if (stockfile.is_open()) {
while (stockfile.good()) {
getline(stockfile, line);
istringstream ss(line);
string token;
while (std::getline(ss, token, ',')) {
temp.push_back(token);
}
addStock(temp.at(0), temp.at(1), temp.at(2));
temp.clear();
}
stockfile.close();
} else {
cout << "Unable to open file" << std::endl << std::endl;
}
}
I know it isn't THAT efficient, that is what I am trying to fix. What it is supposed to be doing is:
Read that file line by line.
Parse each line and split it by comma.
Take those 3 values and use it in a method.
I am using that vector temp to store the values, add them to the function and then clear it so that it can be empty and used again to store the next ones ...etc.
I tried printing out each value BEFORE the temp.clear() and they all print out and THEN I get the error. So I know that temp.clear() is the problem. Perhaps I am using the wrong method, or there is a much better way.
I want to try and NOT use boost if possible.
This is the error I'm getting:
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: vector
Results.txt is a file that looks like.
goog,525,0
msft,34,10
and so on.
while (stockfile.good()) is wrong, and leads to your reading one extra, non-existent line.
That's because you're checking for stream validity before attempting to read a new line; if there's no new line to read, it's only after the call to getline that this condition would evaluate to false but by then it's too late and you're off trying to handle this non-existent line.
That non-existent line does not have three tokens on it, but you are performing no error checking on the tokenization, nor are you ever verifying the size of the vector temp.
So, when you come to try to access those three vector elements, which don't exist, an exception is thrown.
Your loop should look like this:
while (getline(stockfile, line)) {
istringstream ss(line);
string token;
// ...
}
Notice how I directly check for success in the loop condition, which will prevent the loop body from being executed if the actual getline fails.

reading from file to vector- last line gets repeated [duplicate]

This question already has answers here:
Reading from text file until EOF repeats last line [duplicate]
(7 answers)
Testing stream.good() or !stream.eof() reads last line twice [duplicate]
(3 answers)
reading a line in text file twice
(4 answers)
Closed 9 years ago.
I am trying to read values from a file to a vector
std::vector<float> setTimesArray (std::string flName){
int i=0, dummy=0;
float temp;
std::vector<float> pObs;
std::string line;
std::ifstream inFile;
inFile.open(flName.c_str());
if(!inFile){
std::cout<<"\n.obs file not valid. Quitting programme...";
exit(1);
}
while(inFile.good()){
i++;
getline(inFile, line);
if(i>=3){ //I don't want first two lines
std::istringstream in(line);
in>>dummy;//discards first value in the line
in>>temp;
pObs.push_back(temp);
in.str(""); //discards remaining part of the line
}
}
return pObs;
inFile.close();
}
Problem is, the last value gets repeated. For example, flName had total 975 lines. Thus pObs must be having size=973 (975-2 initial lines). But the size is 974 and I see that the last value is repeating. What mistake have I made?
try:
while (getline(inFile,line))
instead of while(inFile.good())
and remove the getline() call from within the method.
You may also want to change your last two lines of codes to this, as per Daniel Kamil Kozar's suggestion:
inFile.close();
return pObs;
After the last line, good() is still allowed to return true. It doesn't have to return false until after a failed read. Thus, if it returns true, and then fails the read, your line variable won't take a new value. The correct solution would probably be to correct the bounds checking, but in this case, moving the declaration of line into the scope of you while loop and checking for and empty string should correct the issue.