Last line being printed twice (C++) [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 7 years ago.
I have a text file called scores.txt with the following data:
John T Smith 90
Eric K Jones 103
Ram S Krishnan 25
Marie A Bell 50
I am trying to read the data from this file and print it using the following C++ code:
ifstream input;
input.open("scores.txt");
string firstName;
char mi;
string lastName;
int score;
while (input) {
input>>firstName>>mi>>lastName>>score;
cout<<firstName<<" "<<mi<<" "<<lastName<<" "<<score<<endl;
}
input.close();
cout<<"Done"<<endl;
The output is:
John T Smith 90
Eric K Jones 103
Ram S Krishnan 25
Marie A Bell 50
Marie A Bell 50
Why is the last line (Marie A Bell 50) being printed twice? How can I prevent this from happening?

It's because just after you read the file's last line, input is not yet at end of file. Your program enters the while loop a fifth time, reads input (which set it to its end of file state), does not alter your variables and prints them.
A way (amongst many) to avoid this is to write something like
while (input >> var1 >> var2)
{
std::cout << var1 << "," << var2 << std::endl;
}

Related

Console output and file contents unmatched

I desire to output the file contents to the console using file handling. The variable marks is user defined.Now the contents are saved in the file correctly(I have attached a screenshot below). When I want to read the file the user defined functions gives inaccuarte output for the last two times.
Contents of file:
Calculus 11
FoP 22
AP 33
LCA 44
Workshop 55
Pak Studies 66
English 77
Output
Calculus 11
FoP 22
AP 33
LCA 44
Workshop 55
Pak Studies 0
English 1875928375
int marks[7],i=0;
string subject[7]={"Calculus","FoP","AP","LCA","Workshop","Pak Studies","English"};
ifstream file3("Task4.txt");
while(!file3.eof())
{
file3>>subject[i]>>marks[i];
cout<<subject[i]<<" "<<marks[i]<<"\n";
i++;
}
file3.close();
You have multiple problems here:
eof flag is only set on a failed read. This means by the time you check for it you already have a failed read.
streams read one token at a time, meaning you do not read the entire Pak Studies string (just "Pak").
then you attempt to read the second token into an integer ("Studies") which puts the stream in an error state. The stream is not in eof state though, so your loop continues, possibly traversing memory with i > 7 (and triggering undefined behavior).
The correct way (or rather "a more correct way") to do it:
read input as long as you have input lines:
std::string line;
while(std::getline(file3, line))
{
// find position of last space
int pos = line.rfind(' ');
subject[i] = line.substr(0, pos - 1);
mark[i] = std::stoi(line.substr(pos, std::npos));
i++;
if(i == 7)
break;
}
Your loop should be:
while (file3>>subject[i]>>marks[i])
{
++i;
cout<<subject[i]<<" "<<marks[i]<<"\n";
}
See Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong? for more details.

Getline skips last semicolon (csv) c++

I have a really big csv file with 10 comma seperated values in each line, at the end of each line is a \n.
Now I have a row with just semicolons. The amount of values corresponds to how many comma seperated values are in the other lines
5696;Neusser Strasse;49;1;50670;Neustadt-Nord;18.09.1990;um;1890;Wohn- u. Geschäftshaus
;;;;;;;;;
5698;Richard-Wagner-Strasse;18;1;50674;Neustadt-Süd;18.09.1990;;1905;Wohnhaus
When I now start to run my program, it gets the "5698" from the 3rd line as the last value of the 2nd line, so what I get is this:
0 Denkmalnummer: 5696
1 Strasse: Neusser Strasse
2 Nummer: 49
3 Bezirk: 1
4 PLZ: 50670
5 Ort: Neustadt-Nord
6 unter Schutz: 18.09.1990
7 Baujahr Zusatz: um
8 Baujahr: 1890
9 Kurzbezeichnung: Wohn- u. Geschäftshaus
****************
0 Denkmalnummer:
1 Strasse:
2 Nummer:
3 Bezirk:
4 PLZ:
5 Ort:
6 unter Schutz:
7 Baujahr Zusatz:
8 Baujahr:
9 Kurzbezeichnung: 5698
****************
0 Denkmalnummer: Richard-Wagner-Strasse
1 Strasse: 18
2 Nummer: 1
3 Bezirk: 50674
4 PLZ: Neustadt-S├╝d
5 Ort: 18.09.1990
6 unter Schutz:
7 Baujahr Zusatz: 1905
8 Baujahr: Wohnhaus
9 Kurzbezeichnung: 5699
This continues and messes up the proper alignment of the data.
My major code looks like this (via getline the file's data is stored in a vector):
if (denkmallist.is_open()) {
if (counter < 1) {
while (getline(denkmallist, line)) {
stringstream ss(line);
while (getline(ss, line, ';')) {
ausgelesenes.push_back(line);
counter++;
daten.push_back(ausgelesenes);
ausgelesenes.clear();
}
}
}
else{
while (getline(denkmallist, line)){
ausgelesenes.push_back(line);
}
daten.push_back(ausgelesenes);
ausgelesenes.clear();
}
}
and the code which then displays the results looks like this:
for(int x=0, y=semis; x<=semi2+2, y<daten.size(); x++, y++){
if (x > semi2-1){
x = 0;
cout << '\n' << "****************" << '\n' << endl;
}
cout << x << " " << daten[x][0] << ": " << daten[y][0] << endl;
}
Semi represents the amount of entires.
I would be very happy if someone could help me out :)
The inner loop uses the call to getline to decide when it has finished parsing the text string that was read by the outer call to getline. That's okay, but you have to watch out for extraneous failures.
For the first line, the inner loop runs ten times; once for each field that ends with a ; and once more to read the remaining text.
For the second line, there is no text after the last ;. After the ninth time through the loop, getline sees no text and no delimiter, so it concludes that it's at the end of the input. The call fails, and the inner loop exits after reading only nine inputs instead of the expected ten.

Why is there a blank line? [duplicate]

This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed 7 years ago.
I have the following C++ program:
ofstream output("scores.txt");
output<<"John"<<" "<<"T"<<" "<<"Smith"<<" "<<90<<endl;
output<<"Eric"<<" "<<"K"<<" "<<"Jones"<<" "<<103<<endl;
output.close();
ifstream input;
input.open("scores.txt");
string line;
while (!input.eof()) {
getline(input, line);
cout<<line<<endl;
}
input.close();
cout<<"Done";
The output is:
John T Smith 90
Eric K Jones 103
Done
Why is there a blank line between Eric K Jones 103 and Done?
Structure your loop like this:
while (getline(input, line)) {
cout<<line<<endl;
}
Your duplicate line is because the way your read loop is structured, once you read the last line the eof bit is not set yet because readline succeeded. Therefore, you iterate one more time, doing a readline that does set the eof bit, then you do cout<<line<<endl and that last endl is your extra blank line.

Input file reading error [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 9 years ago.
Hi i currently wrote a program but I'm having problems with reading the file. It seems to have read the last line twice, as a result, producing the same results twice.
I had put the getline() function to read the first line, in order to store the string for the variable G.
The rest, I had stored it in a vector of the class object.
basically the file is opened and it performs this loop
file.open("bodies1.txt");
getline(file, G1);
....
while(!file.eof)
{
file >> body;
bodies.push_back(body);
}
this is what the text file look like (this is just a sample. not the actual thing)
0.02932
Sun 32 42 53 2 2
Moon 49 32 4 2 1
Jupiter 32 53 2 3 2
I really was wondering why it read the last line twice. Any suggestions?
while(!file.eof())
{
file >> body;
bodies.push_back(body);
}
After reading the last object in to body, eof is the next character. Then
file >> body;
tries to read it and fails. So whatever was in body before is still there and will be pushed in to the vector.
instead you should read like
while(file >> body)
{
bodies.push_back(body);
}
This way your while stops as soon as you encounter eof() and you will not do an extra push in to the vector.

Getting input from external files?

I need to get very basic input from an external file in C++. I tried searching the internet a few times but nothing really applied to what I need. This would be a .txt file that the input it coming from, and it would be filled with lines like this:
131
241
371
481
I have code already to manually get this input, and it looks like this:
using namespace std;
//Gets the initial values from the user.
int control=0;
while (rowb!=0){
cout << "Row: ";
cin >> rowb;
cout << "Column: ";
cin >> columnb;
cout << "Number: ";
cin >> numb;
row[control]=rowb-1;
column[control]=columnb-1;
num[control]=numb;
control++;
}
This is part of a program that solves sudoko boards. The inputed numbers are the initial values that a sudoko board holds, and the user is inputing the row, column, and number that comes from a board.
What I need is to be able to create a .txt file with these numbers stored in rows so that I do not have to enter so many numbers. I have very little idea how to go about doing this. Mainly I'll only be using the txt file for testing my program as I move along with adding more code to it. It takes 150+ entered numbers within my program just to get a single board, and it takes a lot of time. Any accidentally wrong entered value is also a huge problem as I have to start again. So how would I get C++ to read a text file and use those numbers as input?
Aside from the other suggestions, you can simply redirect a file to standard input, like so (where $ is the command prompt):
$ myprogram < mytextfile.txt
That will run myprogram just as normal but take input from mytextfile.txt as if you had typed it in. No need to adjust your own program at all.
(This works on both Unix/Linux systems and on Windows.)
You can open a file for input with std::ifstream from the header <fstream>, then read from it as you would from std::cin.
int main()
{
std::ifstream input("somefile.txt");
int a;
input >> a; // reads a number from somefile.txt
}
Obviously, you can use >> in a loop to read multiple numbers.
Create an std::ifstream object, and read from it just like you would from std::cin. At least if I understand what you're trying to do, the 131 as the first input is really intended to be three separate numbers (1, 3, and 1). If so, it's probably easiest to change your input file a bit to put a space between each:
1 3 1
2 4 1
3 7 1
4 8 1
Personally, I would start with a different format of the file: enter a value for each cell. That is, each row in the input file would represent a row in the sudoko board. Empty fields would use a space character. The immediate advantage is that the input actually pretty much looks like the sudoko board. Also, you would enter at most 90 characters: 9 characters for the board and a newline for each line:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
int main(int ac, char* av[])
{
std::ifstream in(ac == 1? "sudoko.init": av[1]);
char board[9][9];
for (int i(0); i != 9; ++i)
{
in.read(board[i], 9).ignore();
}
if (!in)
{
std::cout << "failed to read the initial board\n";
}
else
{
typedef std::ostream_iterator<char> iterator;
std::fill_n(iterator(std::cout << "board:\n\n+", "+"), 9, '=');
for (int i(0); i != 9; ++i)
{
std::copy(board[i] + 0, board[i] + 9, iterator(std::cout << "\n|", "|"));
std::fill_n(iterator(std::cout << "\n+", "+"), 9, (i + 1) % 3? '-': '=');
}
std::cout << "\n";
}
}
This would take input like this:
4 5 3 8
71 3
16 7
6 4 7
6 8
1 9 5
6 42
5 94
4 7 9 3
Note that each of these lines uses 9 characters. You might want to use something more visible like ..