Hi i'm doing some project to read input from csv file, the value i extract from file are Day, Month, Year, Hour, Minute, Windspeed, SolarRadiation.
bool readFile(MasterMap &mastMap){
const string index = "MetData/data.txt"; //<--- container of every file name constant cant change
string temp, temp2, token; // <--temp to store filename from index,
// <-- temp2 to getline from every single line from file
// << token to store temporary data
ifstream myFile(index.c_str()); // create ifstream to read into the index file
if(myFile.is_open()){
while(getline(myFile, temp))
{
cout << temp << endl; // <--- Print out the file name (testing)
string fileName = "MetData/"+temp; // <-- filename is to contain temp
ifstream actualFile(fileName.c_str()); // <--- Open the File
if(actualFile.is_open())
{
time timeValue;
MonthsMap monthMap;
windLog wLog;
solarRadiation SR;
windSpeed WS;
string MonthYear = "";
int MY = 0;
int day = 0;
int totalCount = 0;
getline(actualFile, temp2); //remove the first line of the file.
while(**actualFile.eof()**)
{
getline(actualFile, temp2)
stringstream ss(temp2); // <-- pas line to stream
getline(ss, token,'/'); // <--Token for day;
int dayTemp = atoi(token.c_str());
getline(ss, token,'/'); // <--Token for month;
string month = token.c_str();
getline(ss, token,' '); // <--Token for year;
string year = token.c_str();
MonthYear = month + year;
if(MY == 0 && day == 0){
MY = atoi(MonthYear.c_str());
day = dayTemp;
}
if(day!=dayTemp || actualFile.eof()){
monthMap.insertWindLog(day, wLog);
wLog = windLog();
day = dayTemp;
if(MY!=atoi(MonthYear.c_str()) || actualFile.eof()){
cout << "Entered Month > " << MY << endl;
mastMap.insertData(MY, monthMap);
monthMap = MonthsMap();
MY=atoi(MonthYear.c_str());
}
getline(ss, token,':'); // <-- Token for Hour;
timeValue.setHour(atoi(token.c_str()));
getline(ss, token,','); // <-- Token for Minute;
timeValue.setMinute(atoi(token.c_str()));
for(int i = 0; i<9; i++)
getline(ss, token, ',');
getline(ss, token,','); // <-- Token for WindSpeed
WS.setTime(timeValue);
WS.setWindspeed(atof(token.c_str()));
getline(ss,token,','); // <-- Token for Solar Radiation
SR.setTime(timeValue);
SR.setSolarRadiation(atof(token.c_str()));
wLog.insertDataSR(SR);
wLog.insertDataWS(WS);
}
else{
getline(ss, token,':'); // <-- Token for Hour;
timeValue.setHour(atoi(token.c_str()));
getline(ss, token,','); // <-- Token for Minute;
timeValue.setMinute(atoi(token.c_str()));
for(int i = 0; i<9; i++)
getline(ss, token, ',');
getline(ss, token,','); // <-- Token for WindSpeed
WS.setTime(timeValue);
WS.setWindspeed(atof(token.c_str()));
getline(ss,token,','); // <-- Token for Solar Radiation
SR.setTime(timeValue);
SR.setSolarRadiation(atof(token.c_str()));
wLog.insertDataSR(SR);
wLog.insertDataWS(WS);
}
totalCount++;
}
cout << totalCount << endl;
actualFile.close();
}else
return false;
}
myFile.close();
}else
return false;}
Problem
The problem is when the line reach end-of-file, it will end the loop immediatly but what i need is check if the current line is EOF, so it can enter the last month.
**edited :: Full Code
**edited :: thanks for you input guys, i just rewrite abit of my code, i change the loop param into while(!actualFile.eof()) and for the if statement i put if(day!=dayTemp || actualFile.eof()) and the getline is after the while loop
Sorry for unclear question and title
Take a look here:
http://www.cplusplus.com/reference/istream/istream/getline/
I quote:
The function will also stop extracting characters if the end-of-file is reached. If this is reached prematurely (before either writing n characters or finding delim), the function sets the eofbit flag.
More information here:
http://www.cplusplus.com/reference/ios/ios_base/iostate/
You want to look at rdstate:
http://www.cplusplus.com/reference/ios/ios/rdstate/
And test for the flag eofbit.
That resource also shows you about eof():
http://www.cplusplus.com/reference/ios/ios/eof/
It gives an example:
// ios::eof example
#include <iostream> // std::cout
#include <fstream> // std::ifstream
int main () {
std::ifstream is("example.txt"); // open file
char c;
while (is.get(c)) // loop getting single characters
std::cout << c;
if (is.eof()) // check for EOF
std::cout << "[EoF reached]\n";
else
std::cout << "[error reading]\n";
is.close(); // close file
return 0;
}
So, use eof() to test if you have reached the end of the file. But you can also do that flag test if approrpriate in your case. I think eof() is sufficient.
You could do something like this:
Declare variable bool reach;
getline(file, line);
if(file.eof()) reach = true;
Related
I'm trying to read a CSV file that looks like this:screenshot of a CSV file
When i read a line that says "Cliente" I want to skip it and read the next line. When i read a line "Itinerarios" I also want to skip it and read all the lines untill the next "Cliente" line. Basically Cliente is a class and Itinerario is a different class that is associated with Cliente, that's why i'm trying to read it that way.
I tried using ss.ignore() in this context but it seems to do nothing: My line is still "Cliente" and the code cant extract the values.
if (fe.good()) {
while (!fe.eof()) {
getline(fe, linea);
stringstream ss;
if (linea != "") {
++total;
if (total > 2) {
if (linea == "Cliente") {
ss << linea;
ss.ignore(20,'\n');
// Starts reading Cliente stuff
getline(ss, dni, ';');
getline(ss, pass, ';');
EDIT: Here's a reduced example:
int main(int argc, char** argv) {
ifstream fe;
string linea;
int total = 0; // Counts lines
string dni;
//Reads the file
fe.open("ClientesItinerarios.csv");
if (fe.good()) {
while (!fe.eof()) {
getline(fe, linea); //Toma una l�nea del fichero
stringstream ss;
if (linea != "") {
++total;
if (total > 2) {
if (linea == "Cliente") {
ss << linea;
ss.ignore(20,'\n');
// Read only the first value to make the example shorter
getline(ss, dni, ';'); //Stores the first part into dni
}
}
}
}
fe.close();
} else {
cerr << "Cannot read file" << endl;
}
return 0;
}
and if it helps heres a screenshot of my debugger when its over getline(ss, dni, ';');
I have a text file that has information format like this:
id last,first string
for example:
0 Snow,John nothing
1 Norris,Chuck everything
How do i get last name and first name stored separately?
To get information from file, I did:
#include <fstream>
int id;
string str;
string last;
string first;
int main()
{
ifstream myfile(ex.txt);
myfile >> id;
while (myfile)
{
for (int i = 0; i < 4; i++) // this is the amount of times i'll get information from 1 line
{
id = id; // its actually some_structure.id = id, omit
getline(myfile, last, ','); // i think i need to use another function as getline get the whole line
cout << id;
cout << last; // print out the whole line!
}
}
}
ifstream myfile;
string line;
while (getline(myfile, line))
{
istringstream ss(line);
int id;
ss >> id;
string fullname;
ss >> fullname;
string firstname, lastname;
{
istringstream ss2(fullname);
getline(ss2, lastname, ',');
getline(ss2, firstname);
}
}
if (std::ifstream input(filename))
{
int id;
string lastname, firstname, other_string;
while (input >> id && getline(input, lastname, ',') &&
input >> firstname >> other_string)
... do whatever you like...
if (!input.eof())
std::cerr << "error while parsing input\n";
}
else
std::cerr << "error while opening " << filename << '\n';
The code above has more error checking than the other answers I've seen, but admittedly - because it doesn't read text a line at a time then parse out the fields, it would happily accept e.g.:
10 Chuck,
Norris whatever
Would recomend something like this:
string name;
myfile >> id >> name >> str;
first = name.substr(0, name.find(","));
last = name.substr(name.find(",") + 1);
Note that your EOF checking is incorrect.
// The complete code that will do the job
// Please remove uncomment all code
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("ex.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
string last = line.substr(line.find(" ") + 1, line.find(",") - 2);
string first = line.substr(line.find(",") + 1, line.find(",") + line.find(" ") - 1);
}
myfile.close();
}
else {
cout << "Unable to open file";
}
return 0;
}
How do I read in lines from a file and assign specific segments of that line to the information in structs? And how can I stop at a blank line, then continue again until end of file is reached?
Background: I am building a program that will take an input file, read in information, and use double hashing for that information to be put in the correct index of the hashtable.
Suppose I have the struct:
struct Data
{
string city;
string state;
string zipCode;
};
But the lines in the file are in the following format:
20
85086,Phoenix,Arizona
56065,Minneapolis,Minnesota
85281
56065
I cannot seem to figure this out. I am having a really hard time reading in the file. The first line is basically the size of the hash table to be constructed. The next blank line should be ignored. Then the next two lines are information that should go into the struct and be hashed into the hash table. Then another blank line should be ignored. And finally, the last two lines are input that need to be matched to see if they exist in the hash table or not. So in this case, 85281 is not found. While 56065 is found.
This is what I have and it doesn't seem to be doing what I want it to do:
int main(int argc, char *argv[])
{
string str;
//first line of file is size of hashtable
getline(cin, str);
stringstream ss(str);
int hashSize;
ss >> hashSize;
//construct hash table
Location *hashTable = new Location[hashSize];
//skip next line
getline(cin, str);
string blank = " ";
while(getline(cin, str))
{
{
//next lines are data
Location locate;
string line;
getline(cin, line);
istringstream is(line);
getline(is, locate.zipCode, ',');
getline(is, locate.city, ',');
getline(is, locate.state, ',');
insertElementIntoHash(hashTable, locate, hashSize);
}
}
dispHashTable(hashTable, hashSize);
//read third set of lines that check if the zipCodes are in the hashtable or not
while(getline(cin, str))
{
//stop reading at a blank line or in this case, end of file
stringstream is(str);
string searchZipCode;
is >> searchZipCode;
searchElementInHash(hashTable, hashSize, searchZipCode);
}
//delete hash table after use
delete []hashTable;
return 0;
}
You might read the input this way:
#include <iostream>
#include <sstream>
#include <vector>
struct Location
{
std::string city;
std::string state;
std::string zipCode;
};
int main(int argc, char *argv[]) {
std::istringstream input(
"2\n"
"\n"
"85086,Phoenix,Arizona\n"
"56065,Minneapolis,Minnesota\n"
"\n"
"85281\n"
"56065\n"
);
// Make the size unsigned, to avoid signed/unsigned compare warnings.
unsigned hashSize;
std::string line;
getline(input, line);
std::istringstream hash_line(line);
// Ignore white space.
if( ! (hash_line >> hashSize >> std::ws && hash_line.eof())) {
std::cerr << "Error: Invalid file format [1].\n" << line << '\n';
return -1;
}
else {
getline(input, line);
std::istringstream first_blank_line(line);
// Ignore white space.
first_blank_line >> std::ws;
if( ! first_blank_line.eof()) {
// Missing blank line.
std::cerr << "Error: Invalid file format [2].\n" << line << '\n';
return -2;
}
else {
// Have a local variable (No need to allocate it)
// (Is it a hash table !???)
std::vector<Location> hashTable;
hashTable.reserve(hashSize);
while(hashTable.size() < hashSize && getline(input, line)) {
std::istringstream data_line(line);
Location locate;
getline(data_line, locate.zipCode, ',');
getline(data_line, locate.city, ',');
getline(data_line, locate.state); // Note: No comma here.
if(data_line && data_line.eof()) {
// Note: The fields may have leading and/or trailing white space.
std::cout
<< "Insert the location into the hash table.\n"
<< locate.zipCode << '\n'
<< locate.city << '\n'
<< locate.state << '\n';
hashTable.push_back(locate);
}
else {
std::cerr << "Error: Invalid file format [3].\n" << line << '\n';
return -3;
}
}
if(hashTable.size() != hashSize) {
std::cerr << "Error: Invalid file format [4].\n";
return -4;
}
else {
getline(input, line);
std::istringstream second_blank_line(line);
// Ignore white space.
second_blank_line >> std::ws;
if( ! second_blank_line.eof()) {
// Missing blank line.
std::cerr << "Error: Invalid file format [5].\n";
return -5;
}
else {
std::string searchZipCode;
while(input >> searchZipCode) {
// Search element in the hash table
}
}
}
}
}
return 0;
}
Following modification should work:
//skip next line
getline(cin, str);
string blank = " ";
string line;
while(getline(cin, line) && (line != ""))
{
{
//next lines are data
Location locate;
istringstream is(line);
getline(is, locate.zipCode, ',');
getline(is, locate.city, ',');
getline(is, locate.state, ',');
insertElementIntoHash(hashTable, locate, hashSize);
}
}
I know this post has been made before on stack overflow, and I have combined various tutorials; but why does this code cause an error on execution - it does compile.
void leaderBoard::loadFromFile(void)
{
string line;
ifstream leaderBoardFile ("leaderboard.data");
vector<string> playerInfoVector;
if (leaderBoardFile.is_open())
{
while ( leaderBoardFile.good() )
{
playerInfoVector.clear();
getline (leaderBoardFile,line);
std::string input = line;
std::istringstream ss(input);
std::string token;
//cout << line << endl;
while(getline(ss, token, ',')) {
//for current line;
playerInfoVector.push_back(token);
}
string firstName = playerInfoVector.at(0);
string stringAge = playerInfoVector.at(1);
string stringScore = playerInfoVector.at(2);
//int age;
//stringstream(stringAge) >> age;
//int score;
//stringstream(stringScore) >> score;
//addScore(firstName,age,score);
////stringstream(stringAge) >> age;
////Add text to vector (push back)
playerInfoVector.clear();
}
leaderBoardFile.close();
}
else cout << "Unable to open file";
}
Yes loads of times
while ( leaderBoardFile.good() )
{
playerInfoVector.clear();
getline (leaderBoardFile,line);
should be
while ( getline (leaderBoardFile,line) )
{
playerInfoVector.clear();
It is incredible how many times this error is repeated. You actually got it right in your second while loop, so why wrong in the first one?
Unfortunately some tutorials also get this wrong.
It would also be sensible to add a check that you really do have three items in your vector. Something like this
if (playerInfoVector.size() < 3)
{
cerr << "Not enough items in player info vector\n";
exit(1);
}
string firstName = playerInfoVector.at(0);
string stringAge = playerInfoVector.at(1);
string stringScore = playerInfoVector.at(2);
My program takes in two parameters, first parameter is name to be changed, and 2nd parameter is the name to which change it.
After execution, my textfile is missing the the second line, which suppose to be changed from May to MayMay. I'm not sure if my if else statement has problems or while(!file.fail) has problems.
This is my original textfile.
user; pass; 1234; John; 1111
user1; pass1; 2345; May; 2222
user2; pass2; 3456; Mary; 3333
user3; pass3; 4567; Andy; 4444
hr; hr; 5678; Jonathan; 5555
admin; admin; 6789; Aili; 6666
user10; pass10; 7890; eggy; 9999
user11; pass11; 9807; Mary; 7777
This is my output textfile after program execute.
user; pass; 1111; John;
user2; pass2; 3333; Mary;
user3; pass3; 4444; Andy;
hr; hr; 5555; Jonathan;
admin; admin; 6666; Aili;
user10; pass10; 9999; eggy;
user11; pass11; 7777; Mary;
pass11; 7777; Mary;
This is my code:
bool Employee::changeName(string nnn, string mmm)
{
int i = 0;
ifstream file("login1.txt"); // to open the file
string name, empty, empty2, empty3, empty4; // fusername is use to store the first parameter in textfile,empty is use to store the rest of the line after the ';'
string store[100]; // initialize a array to store textfile contents
while (!file.fail()) // loop if file didn't fail
{
getline(file, empty, ';'); // use ; as delimiter
getline(file, empty2, ';'); // use ; as delimiter
getline(file, empty3, ';'); // use ; as delimiter
getline(file, name, ';'); // use ; as delimiter
getline(file, empty3); // use line end as delimiter, and to skip the rest of the information
string add = ""; //initialize add string to nothing when it loops
if(name != nnn) // to check if the username in textfile do not match the user input name
{
add += empty + ';' + empty2 + ';' + empty3 + ';' + name + ';' + empty4; // adds back the username and rest of the line together back
store[i] = add; // store into an array
cout << "i is: " << i << endl; // debugging.
cout << "store array[] = " << store[i] << endl; // debugging..
i++;
}
else if(name == nnn)
{
add += empty + ';' + empty2 + ';' + empty3 + ';' + mmm + ';' + empty4; // adds back the name and rest of the line together back
store[i];
cout << "i is: " << i <<endl; // debugging.
cout << "store array[] = " << store[i] << endl; // debugging..
i++;
}
else{}
}
remove("login1.txt"); //remove the textfile
ofstream pwd2_file ; // initilize a outputstream textfile
pwd2_file.open("login1.txt"); // create a new file call login1.txt
for (int x = 0; x < i; x++)//for loop to store store[] array into login1.txt
{
pwd2_file << store[x] << endl; // storing into textfile
}
pwd2_file.close(); // close the output stream
}
The problem causing the empty line is that when you replace the name in the else-if statement you have the lines
add += empty+';'+empty2+';'...
store[i];
I'm guessing that should be
store[i] = add;
You're reading into empty3 twice per loop while leaving empty4 empty:
getline(file, empty, ';');
getline(file, empty2, ';');
getline(file, empty3, ';'); // <--- here
getline(file, name, ';'); //
getline(file, empty3); // <--- and here (this is supposed to be empty4, right?)
Then you've got a statement with no effect (already pointed out by Chad Campbell):
store[i];
And finally, an incorrect condition: while(!file.fail()) - you enter the last iteration when the stream is still good - you've read all the data but not yet attempted to read past the end which would put the stream in bad state - next reads fail but you don't check it and silently re-use the data from the previous iteration.
Always use input operations in some boolean context (like while(getline(...)), for example) or at least check the stream after you attempted a read. In your case, something like this:
while (true)
{
getline(file, empty, ';');
getline(file, empty2, ';');
getline(file, empty3, ';');
getline(file, name, ';');
getline(file, empty3);
if (!file) break;
// do stuff with data
}