Loop won't stop at end of file - c++

I'm working on file io, and i've managed to get the data from the file into the vector i made, but when i print the values, i get garbage numbers after the last part of the data. So i'm guessing its pushing values that don't exist into the vector, or its trying to print parts of the vector that don't exist. Any help would be great.
main.cpp
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
#include "store.h"
using namespace std;
int main ()
{
store data;
ifstream inFile ("C:/Users/Owner/Desktop/Albums.csv");
string line;
string item;
int num;
int itemnum;
int linenum = 1;
ostringstream convert;
string temp;
while (!inFile.eof())
{
while (getline (inFile, line) )
{
istringstream linestream(line);
itemnum = 0;
num = 0;
convert << linenum;
temp = convert.str();
data.addtovectv(temp);
while (getline (linestream, item, ',') )
{
if (itemnum == 1 || itemnum == 2 || itemnum == 3 || itemnum == 5)
{
num++;
data.addtovectfullline(0, item);
}
itemnum++;
}
linenum++;
}
}
data.print();
inFile.close();
return 0;
}
store.h
#ifndef STORE_H
#define STORE_H
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
class store
{
public:
store();
void addtovectv(string);
void addtovectfullline(int, string);
void print();
private:
vector<string> v;
vector< vector<string> > fullline;
};
#endif
store.cpp
#include "store.h"
store::store()
{
}
void store::addtovectv(string a)
{
v.push_back(a);
fullline.push_back(v);
}
void store::addtovectfullline(int a, string c)
{
fullline[a].push_back(c);
}
void store::print()
{
for(unsigned int i=0; i<fullline.size(); i++)
{
for(unsigned int j=0; j<fullline[i].size(); j++)
{
cout << fullline[i][j] << endl;
}
cout << endl;
}
}
edit: some sample data
RS 500 compilations, Various Artists, The Sun Records Collection, 308
Both lists, A Tribe Called Quest, The Low End Theory, 1991, 154, Jive, Skeff Anselm, Zombart JK, USA, 48:08:52
Both lists, AC/DC, Back in Black, 1980, 73, ATCO, Robert John Lange, Bob Defrin, Australia / UK, 41:36:52
Both lists, AC/DC, Highway to Hell, 1979, 199, Albert Productions, Robert John Lange, Bob Defrin Australia / UK, 41:53:52
i need to read the lines, but only put the second, third, fourth, and sixth piece of info into the vectors, which is what it should end up printing, with each individual piece on a new line. All the data is stored in a .csv file
with this sample data, my output is this screenshot: http://puu.sh/bHtHM.png
however, none of those numbers at the bottom should be there, and there is a weird space after the first set of data
edit2: realized that odd space was an absence of the data i asked for, so its fine

In.good() is not the appropriate way to tell if the file is done.
(From http://www.cplusplus.com/reference/ios/ios/good/)
Ios::eof() checks for end of file.
Ios::Good() checks for no errors in opening. It probably exits the loop when an error occurs from reading past EOF.

Related

Why the output not show up according to my txt file?

Why can't I retrieve all of the data from a txt file using c++?
This is the data in the txt file:
Standard ;40 90 120
Delux ;70 150 200
VIP ;110 200 300
This is my coding:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <bits/stdc++.h>
#include <vector>
using namespace std;
struct Room
{
string roomType;
float tripleBed;
float doubleBed;
float singleBed;
};
void displayRoom(Room []);
void inputRoom(ifstream &, Room []);
int main()
{
Room choice[3];
ifstream room("Room.txt");
if(room.fail())
{
cout<<"File does not exist\n";
cout<<"Press any key to exit the program\n";
return -1;
}
inputRoom(room, choice);
displayRoom(choice);
room.close();
return 0;
}
void displayRoom(Room choice[])
{
cout<<"\n\n************** ROOMS SECTION ***************\n"<<endl;
cout<<"ROOM TYPE"<<"\t"<<"TRIPLE BEDDED"<<"\t"<<"DOUBLE BEDDED"<<"\t"<<"SINGLE BEDDED"<<endl;
for(int i=0; i<3; i++)
{
cout<<choice[i].roomType;
cout<<"RM"<<choice[i].tripleBed<<"\t\tRM"<<choice[i].doubleBed<<"\t\tRM"<<choice[i].singleBed<<endl;
}
}
void inputRoom(ifstream &room, Room choice[])
{
string tokens[4];
string line;
int j = 0;
while (room.good())
{
int i = 0;
getline(room, line);
stringstream ss (line);
string temp;
while (getline (ss, temp, ';'))
{
tokens[i] = temp;
i++;
}
choice[j].roomType = tokens[0];
choice[j].tripleBed = atof(tokens[1].c_str());
choice[j].doubleBed = atof(tokens[2].c_str());
choice[j].singleBed = atof(tokens[3].c_str());
j++;
}
}
This is the output
************** ROOMS SECTION ***************
ROOM TYPE TRIPLE BEDDED DOUBLE BEDDED SINGLE BEDDED
Standard RM40 RM0 RM0
Delux RM70 RM0 RM0
VIP RM110 RM0 RM0
--------------------------------
Process exited with return value 0
Press any key to continue . . .
As you can see, at double bedded and single bedded column should have a value that has been defined by me but why the value of the columns zero? can someone help me? Thank you in advance for helping me.
Look at your input loop
while (getline (ss, temp, ';'))
{
tokens[i] = temp;
i++;
}
that reads tokens separated by semicolons.
Look at you actual input
Standard ;40 90 120
Only the first and second token are separated by a semicolon. The rest are separated by spaces.
The simple thing to do would be to edit your data so that it matches your code. E.g.
Standard;40;90;120

C++ Problem with space detection in an Array String

I'm currently writting a program where I try to filter extra spaces so if there are more than 1 spaces in a row, I discard the rest leaving only one
But this is only the first step because the aim of the program is to parse a txt file with mips assembly instructions.
So far I've opened the file, stored the content in a vector and then stored the vector content in an array. Then I check, if you find a char 2 times in a row shift the array to the left.
The problem is that the code works well for any other letter, except for the space character. (On the code below I test it with the 'D' character and it works)
#include <iostream>
#include <cmath>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
class myFile {
vector<string> myVector;
public:
void FileOpening();
void file_filter();
};
void myFile::FileOpening() {
string getcontent;
ifstream openfile; //creating an object so we can open files
char filename[50];
int i = 0;
cout << "Enter the name of the file you wish to open: ";
cin.getline(filename, 50); //whatever name file the user enters, it's going to be stored in filename
openfile.open(filename); //opening the file with the object I created
if (!openfile.is_open()) //if the file is not opened, exit the program
{
cout << "File is not opened! Exiting the program.";
exit(EXIT_FAILURE);
};
while (!openfile.eof()) //as long as it's not the end of the file do..
{
getline(openfile, getcontent); //get the whole text line and store it in the getcontent variable
myVector.push_back(getcontent);
i++;
}
}
void myFile::file_filter() {
unsigned int i = 0, j = 0, flag = 0, NewLineSize, k, r;
string Arr[myVector.size()];
for (i = 0; i < myVector.size(); i++) {
Arr[i] = myVector[i];
}
//removing extra spaces,extra line change
for (i = 0; i < myVector.size(); i++) {
cout << "LINE SIZE" << myVector[i].size() << endl;
for (j = 0; j < myVector[i].size(); j++) {
//If I try with this character for example,
//it works (Meaning that it successfully discards extra 'Ds' leaving only one.
// But if I replace it with ' ', it won't work. It gets out of the loop as soon
//as it detects 2 consecutive spaces.
if ((Arr[i][j] == 'D') && (Arr[i][j + 1] == 'D')) {
for (k = j; k < myVector[i].size(); k++) {
Arr[i][k] = Arr[i][k + 1];
flag = 0;
j--;
}
}
}
}
for (i = 0; i < myVector.size(); i++) {
for (j = 0; j < myVector[i].size(); j++) //edw diapernw tin kathe entoli
{
cout << Arr[i][j];
}
}
}
int main() {
myFile myfile;
myfile.FileOpening();
myfile.file_filter();
}
My question is, why does it work with all the characters except the space one, and how do I fix this?
Thanks in advace.
Wow. Many lines of code. I can only recomend to learn more about the STL and algorithms.
You can read the complete file into a vector using the vectors "range"-constructor and std::istream_iterator. Then you can replace one or more spaces in a string by using a std::regex. This is really not complicated.
In the below example, I do all the work, with 2 lines of code in function main. Please have a look:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <string>
#include <fstream>
#include <regex>
using LineBasedTextFile = std::vector<std::string>;
class CompleteLine { // Proxy for the input Iterator
public:
// Overload extractor. Read a complete line
friend std::istream& operator>>(std::istream& is, CompleteLine& cl) { std::getline(is, cl.completeLine); return is; }
// Cast the type 'CompleteLine' to std::string
operator std::string() const { return completeLine; }
protected:
// Temporary to hold the read string
std::string completeLine{};
};
int main()
{
// Open the input file
std::ifstream inputFile("r:\\input.txt");
if (inputFile)
{
// This vector will hold all lines of the file. Read the complete file into the vector through its range constructor
LineBasedTextFile text{ std::istream_iterator<CompleteLine>(inputFile), std::istream_iterator<CompleteLine>() };
// Replace all "more-than-one" spaces by one space
std::for_each(text.begin(), text.end(), [](std::string& s) { s = std::regex_replace(s, std::regex("[\\ ]+"), " "); });
// For Debug purposes. Print Result to std::out
std::copy(text.begin(), text.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}
return 0;
}
I hope, I could give you some idea on how to proceed.

Reading in input to construct an object

I am trying to read a string line for line down a .txt file in order to initiate an array of objects using a constructor that takes a string.
The text file is written like
TransAm
Mustang
Corvette
I feel like my loop is not iterating the information I want to be set correctly. Is there an easy way of accomplishing this?
main.cc
#include <string>
#include <iostream>
#include "Car.cc"
#include <fstream>
using namespace std;
int main()
{
Car cars[3];
string STRING;
ifstream infile;
infile.open("cars.txt");
// THIS IS HOW IT'S ACHIEVED USING FOR-LOOP - Sam
for(int i = 0; i<3 && infile;++i){
getline(infile,STRING);
cars[i].setName(STRING);
}
/* THIS IS WHAT I HAD
while(!infile)
{
getline(infile,STRING);
for(int i = 0; i<sizeof(cars);i++){
cars[i].setName(STRING);
}
}
*/
infile.close();
for(int j = 0;j<sizeof(cars);j++){
cars[j].print();
}
}
Car.h
#include <string>
using namespace std;
class Car{
public:
Car();
Car(string);
string getName();
void setName(string);
void print();
private:
string name;
};
Car.cc
#include <string>
#include "Car.h"
using namespace std;
Car::Car()
{
}
Car::Car(string s)
{
setName(s);
}
void Car::setName(string s)
{
name = s;
}
string Car::getName()
{
return name;
}
void Car::print()
{
cout << name;
}
These points need to be corrected:
while (!infile) prevents you from entering the loop.
You don't need two loops.
You can modify your loop like this:
for (int i = 0; i < sizeof(cars) && getline(infile, STRING); ++i)
cars[i].setName(STRING);
Or like this:
for (int i = 0; i < sizeof(cars) && infile; ++i) {
getline(infile, STRING);
cars[i].setName(STRING);
}
Your loop does at the moment nothing if the file is correctly opened. It will only enter if the call to open was unsuccessful.
Change your loop to either
while (getline(infile,STRING))
{
//...
}
or
while (infile)
{
//...
}
As it's been said, "Change while(!infile) to while(getline(infile,STRING))" but do not forget to remove the getline(infile,STRING); afterwards.

Searching for an int inside a file

So I am supposed to take all ints in source3.txt and check which of them occur in source.txt. If any of them don't occur, I'm supposed to print a corresponding line from source2.txt to output.txt (source2.txt contains descriptions of the numbers in source 3, in the same order, each description is 1 line). I wrote this code, but it only prints the last line from source2.txt, furthermore it is a wrong line.
I have no idea what might be wrong. Can you help me?
#include <bits/stdc++.h>
using namespace std;
int main()
{
ifstream source ("source.txt");
ifstream source2 ("source2.txt");
ifstream source3 ("source3.txt");
vector<int> tab(1051,0);
vector<string> tab2(857,*new string);
vector<int> tab3(857,0);
ofstream output("output.txt");
for(int i=0;i<1050;++i)
{
source>>tab[i];
}
for(int i=0;i<856;++i)
{
string a;
getline(source2,a);
tab2[i]=a;
source3>>tab3[i];
}
for(int i=0;i<856;++i)
{
if(std::find(tab.begin(), tab.end(), tab3[i]) != tab.end())
{
continue;
}
else
{
output<<tab2[i]<<endl;
}
}
}
I think below modifications to code should work for you . Replace value of SOURCE_COUNT with 1051 and SOURCE2_COUNT with 857
#include <iostream>
#include <fstream>
#include <vector>
#include <vector>
const int SOURCE_COUNT = 4;
const int SOURCE2_COUNT = 3;
//const int SOURCE2_COUNT = 3;
using namespace std;
int main()
{
ifstream source ("source.txt");
ifstream source2 ("source2.txt");
ifstream source3 ("source3.txt");
vector<int> tab(SOURCE_COUNT,0);
vector<string> tab2(SOURCE2_COUNT,"");
vector<int> tab3(SOURCE2_COUNT,0);
ofstream output("output.txt");
for(int i=0;i<SOURCE_COUNT;++i)
{
source>>tab[i];
}
for(int i=0;i<SOURCE2_COUNT;++i)
{
string a;
getline(source2,a);
tab2[i]=a;
source3>>tab3[i];
}
for(int i=0;i<SOURCE2_COUNT;++i)
{
if(std::find(tab.begin(), tab.end(), tab3[i]) != tab.end())
{
continue;
}
else
{
output<<tab2[i]<<endl;
}
}
}
It looks to me like you are printing only in those cases where you have not found the number. In other words, the cases in your if-statement are reversed. It should read:
if(std::find(tab.begin(), tab.end(), tab3[i]) != tab.end())
output<<tab2[i]<<endl;
[EDIT] Oops, I read the question not carefully enough. It should print the line, if the number is NOT contained in source3. So the loop should read:
if(std::find(tab.begin(), tab.end(), tab3[i]) == tab.end())
output<<tab2[i]<<endl;
Also: I would strongly suggest to do away with all those constants like 856 and 1050. Why don't you simply read the file until you reach the end?

seekp() position at the beginnig of new line in file

I have a file "first.txt":
Chun mee |Wuyi |Genmai |
Pu-erth |Green |Flower mix |
Lightly sweet|Strong,smooth|Fresh, strong|
Here '|' is delimiter, the first line has 10 symbols in each block (block is the space between delimiters), the second - 11, the third - 13.
I`d like to combinate these lines like this and write it ("rec.txt"):
Chun mee '\t'Pu-erth '\t'Lightly sweet
Wuyi '\t'Green '\t'Strong,smooth
Genmai '\t'Flower mix '\t'Fresh, strong
Here is my code:
#include <iostream>
#include <fstream>
#include <string.h>
#include <cstdlib>
#include <fstream>
#include <limits>
using namespace std;
fstream& go_line(fstream& file, unsigned int num){
for(int i=0; i < num - 1; ++i){
file.ignore(numeric_limits<streamsize>::max(),'\n');
}
return file;
}
void func(int iter_num){
fstream file;
fstream file_exist;
string str;
file_exist.open("first.txt");
file.open("rec.txt", ios::in | ios::out | ios:: trunc | ios::binary);
if (iter_num < 3){ //iter_num - num of iterations (lines)
for(int i = 0; i < iter_num; i++ ){
for(int t = 1; t< 4; t++ ){ //t-num of columns
if(i>0 && t==1){
file<<endl;
}
if(i == 0){
go_line(file_exist, t);
getline (file_exist, str, '|');
file_exist.seekp(0, ios::beg);
file<<str<<'\t';
}
else{
switch(t){
case 1:
//cout<<"case1 "<<endl;
file_exist.seekp((i*10)+1, ios::beg);
go_line(file_exist, t);
getline (file_exist, str, '|');
file<<str<<'\t';
break;
case 2:
//cout<<i<<endl;
go_line(file_exist, t);
file_exist.seekp((i*11)+1, ios::beg);
getline (file_exist, str, '|');
file<<str<<'\t';
case 3:
//cout<<i<<endl;
go_line(file_exist, t);
file_exist.seekp((i*13)+1, ios::beg);
getline (file_exist, str, '|');
file<<str<<'\t';
}//switch
}//else
}//for
}//for
}//if
}//func
int main(){
int n = 3;
func(n);
return 0;
}
The problem is:
for example, in case 2 seekp() is not at the beginnig of new line, it`s on the first one. But the idea is - set it at the beginnig of new line and get "Green " for "Wuyi ". So, It works incorrect, I have no ideas.
Thank you for help!
You could use setw and left from iomanip for formating.
A quick example:
#include <string>
#include <vector>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <sstream>
using namespace std;
int main()
{
ifstream to_format("test/test.txt");
ofstream formatted("test/formatted.txt");
vector<vector<string>> item_matrix; //
// Populating the matrix.
for (string line; getline(to_format, line);)
{
item_matrix.push_back({});
stringstream line_(line); // string stream used for split the line according to the separator '|'
for (string item; getline(line_, item, '|');)
{
item_matrix.back().push_back(item); // Add items to the last row.
}
}
// Output the matrix to file.
// This assume all lines in the original file have the same number of blocks.
vector<string> new_lines;
for (int i = 0; i < item_matrix[0].size(); i++)
{
new_lines.push_back({});
for_each(item_matrix.begin(), item_matrix.end(), [&](vector<string> row){
formatted << setw(25) << left << row[i];
});
formatted << endl;
}
return 0;
}
Example input:
Chun mee |Wuyi |Genmai |
Pu-erth |Green |Flower mix |
Lightly sweet|Strong,smooth|Fresh, strong|
Example ouput:
Chun mee Pu-erth Lightly sweet
Wuyi Green Strong,smooth
Genmai Flower mix Fresh, strong
Well the go_line function which u use continue reading until the end of file is reached so that loop has no effect read this