How to detect the end of a line from a file stream in C++ - c++

I have csv file input where I read in multiple lines which contain multiple fields related to that line. How do I write a loop which reads a line of text from the csv file, then keeps looping until it reaches the end of that line. This while loop would be nested in an !infile.eof while loop. Here is what I has so far but doesn't work exactly.
while (getline(infile, currentline))
{
getline(infile, ID, ',');
getline(infile, Name, ';');
Person p = new Person(ID, Name);
}
A line in the csv file looks like this:
111, james; 222, lynda; 333, luke;
Each line represents a classroom so there would be multiple lines.

Try this:
while (getline(infile, currentline))
{
std::istringstream line{currentline};
if(getline(line, ID, ',') && getline(line, Name, ';'))
Person p = new Person(ID, Name);
}
This while loop would be nested in an !infile.eof while loop.
As a side note, never iterate while( !infile.eof() ) - this is pretty much guaranteed to be a bug. An input stream has multiple failure conditions (eof, failed read etc).
You should simply cast the stream to a boolean value for checking.

The question's a mess, but I think this is what you want:
while (std::getline(infile, currentline))
{
std::istringstream iss(currentline);
if (getline(iss, ID, ',') &&
getline(iss, Name, ';') &&
...)
{
Person p = new Person(ID, Name);
...
}
else
...bad person ;-P...
}

Your while loop seems to already extract a line from the "infile" and stores it in "currentline". Inside the loop you should make a stream out of this string, and use the getlines for "ID" and "Name" on the "currentline"-stream. Otherwise, as it is now, I think you lose every other line.

Related

How to skip a line of a file if it starts with # in c++

So say I have a txt file that goes like:
#unwanted line
something=another thing
something2=another thing 2
#unwanted_line_2=unwanted
something3=another thing 3
and I am reading it with
getline(inFile,astring,'=');
to separate a something from its value (inside a while loop). How do I skip the entire lines that start with # ?
Also I'm storing this in a vector, if it is of any matter.
Use getline() without a delimiter to read an entire line up to \n. Then check if the line begins with #, and if so then discard it and move on. Otherwise, put the string into an istringstream and use getline() with '=' as the delimiter to split the line (or, just use astring.find() and astring.substr() instead).
For example:
while (getline(inFile, astring))
{
if (!asstring.empty() && astring[0] != '#')
{
istringstream iss(astring);
getline(iss, aname, '=');
getline(iss, avalue);
...
}
}

ifstream from next/new line in c++

I am having set of data stored in a file which are basically names. My task is to get all the first letters from each name. Here is the file:
Jack fisher
goldi jones
Kane Williamson
Steaven Smith
I want to take out just first word from each line(ex. jack, goldi, kane, Steaven)
I wrote following code for it, just to take take out 2 names. Here it is:
string first,last;
ifstream Name_file("names.txt");
Name_file>>first;
Name_file>>endl;
Name_file>>last;
cout<<first<<" "<<last;
it is giving error. If I remove endl, it takes the first full name(Jack, fisher) whereas I want it should take (jack ,goldi). How to do it ? Any idea? Thanks in advance for help.
Name_file>>endl; is always wrong.
Even then, you can't use >> like that, it will stop on a space, which is why when you remove endl you see the problem that first and last contain only the first line.
Use std::getline to loop over your file instead and get the full names, then split the line on the first space to get the first name:
ifstream Name_file("names.txt");
std::string line;
while (std::getline(Name_file, line))
{
std::string firstName = line.substr(0, line.find(' '));
//do stuff with firstName..
}
Though I don't mind "Hatted Rooster"implementation I think it can be a little less efficient when the input suddenly contains a very long line.
I would use ignore() to remove the rest of the line:
int main()
{
std::ifstream nameFile("names.txt");
std::string firstName;
while (nameFile >> firstName)
{
// You got a first name.
// Now dump the remaing part of the line.
nameFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
I hope this solves your query.
ifstream Name_file;
string line;
Name_file.open("names.txt");
if(Name_file.fail()){ cerr<<"Error opening file names.txt !!"<<endl;return;}
vector<string> v; // array to store file names;
while(Name_file >> line){
string word;
getline(Name_file, word);
v.push_back(line);
}
// printing the first names
for(int i = 0; i < v.size();i++){
cout<<v[i]<<endl;
}

C++: Using getline to input from a text file either skips the first line or messes up the rest

I'm trying to read in from a specially formatted text file to search for specific names, numbers, etc. In this case I want to read the first number, then get the name, then move on to the next line. My problem seems to be with while loop condition for reading through the file line by line. Here is a sample of the txt file format:
5-Jon-4-Vegetable Pot Pie-398-22-31-Tue May 07 15:30:22
8-Robb-9-Pesto Pasta Salad-143-27-22-Tue May 07 15:30:28
1-Ned-4-Vegetable Pot Pie-398-22-31-Tue May 07 15:30:33
I'll show you two solutions I've tried, one that skips the first line in the file and one that doesn't take in the very last line. I've tried the typical while(!iFile.eof()) as a last ditch effort but got nothing.
transactionLog.clear();
transactionLog.seekg(0, std::ios::beg);
std::string currentName, line, tempString1, tempString2;
int restNum, mealNum;
bool nameFound = false;
int mealCount[NUMMEALS];
std::ifstream in("patronlog.txt");
while(getline(in, line))
{
getline(in, tempString1, '-');
getline(in, currentName, '-');
if(currentName == targetName)
{
if(getline(in, tempString2, '-'))
{
mealNum = std::stoi(tempString2);
mealCount[mealNum - 1] += 1;
nameFound = true;
}
}
I believe I understand what's going in this one. The "getline(in, line)" is taking in the first line entirely, and since I'm not using it, it's essentially being skipped. At the very least, it's taking in the first number, followed by the name, and then doing the operations correctly. The following is the modification to the code that I thought would fix this.
while(getline(in, tempString1, '-'))
{
getline(in, currentName, '-');
// same code past here
}
I figured changing the while loop condition to the actual getline of the first item in the text file would work, but now when I look at it through the debugger, on the second loop it sets tempString1 to "Vegetable Pot Pie" rather than the next name on the next line. Ironically though this one does fine on line #1, but not for the rest of the list. Overall I feel like this has gotten me farther from my intended behavior than before.
You need to parse the contents of lines after they are read. You can use a std::istringstream to help you with that.
while(getline(in, line))
{
// At this point, the varible line contains the entire line.
// Use a std::istringstream to parse its contents.
std::istringstream istr(line);
getline(istr, tempString1, '-'); // Use istr, not in.
getline(istr, currentName, '-'); // ditto
...
}

reading and filling separate variables from file

I am doing a homework assignment where we are to read company data from a file and then process it for errors.
What I have so far I think will work with the first line, but I'm not sure how to make it read each line after. Each line is a record with ID, name, and payments. Basically I want to know how I can skip to the next line after I've processed the first. I haven't included the error checking yet but I think it will be in the last do while loop after 1 record is read. If the information read into each variable is wrong I can check it and output it to either the summary file or error file.
void processFile()
{
string filename;
ifstream recordFile;
ofstream summary("summary.dat");
ofstream error("error.dat");
cout << "Please enter a filename\n";
do
{
cin >> filename;
recordFile.open(filename);
if (!recordFile.is_open())
cout << "No file by that name. Please enter another filename\n";
}
while(!recordFile.is_open());
int ID = 0;
string firstName;
string lastName;
double payment1, payment2, payment3 = (0.00, 0.00, 0.00);
string numberOfRecords;
getline(recordFile, numberOfRecords);
do
{
ws(recordFile);
recordFile >> ID;
recordFile >> firstName;
recordFile >> lastName;
recordFile >> payment1;
recordFile >> payment2;
recordFile >> payment3;
}
while(!recordFile.eof());
}
*edit : I found part of my problem, I actually need to skip the first line and read on from that point. The first line in each file has useless data in it.
Use the getline function on the ifstream object
Two things. The first is if you're going to have to read multiple
records, and each record is a new line, the best solution is almost
always to read line by line, using std::getline, and then use
std::istringstream to break up the line (record) into the desired
fields. This has the advantage of keeping your input synchronized, even
in case of errors; you don't have to worry about how much to skp ahead
or ignore.
The second point is that you're checking for eof(). This is almost
always an error; sometimes, it will lead you to reading one line too
many, and in other cases, of ignoring the last line or field. If the
input is successful (and you can only check for end of file after
trying to input beyond it), the stream will behave as true in a
conditional context; if not, it will behave as false. So your loop
should be:
std::string line;
while ( std::getline( recordFile, line ) ) {
std::istringstream record( line );
record >> ID;
if ( ! record ) ...
// ...
}
And one final comment: all of the >> operators strip leading spaces,
so you don't need your call to ws. On the other hand, with the above
schema, you might want to do something like:
if ( record >> ws && record.get() != EOF ) {
// Unexpected garbage at end of line...
}
at the very end of your loop, to verify that there isn't extra text.

trying to read a text file data into an array to be manipulated then spit back out

My aim is to take the data from the file, split it up and place them into an array for future modification.
The is what the data looks like:
course1-Maths|course1-3215|number-3|professor-Mark
sam|scott|12|H|3.4|1/11/1991|3/15/2012
john|rummer|12|A|3|1/11/1982|7/15/2004
sammy|brown|12|C|2.4|1/11/1991|4/12/2006
end_Roster1|
I want to take maths, 3215, 3 and Mark and put into an array,
then sam scott 12 H 3.4 1/11/1991 3/15/2012.
This is what I have so far:
infile.open("file.txt", fstream::in | fstream::out | fstream::app);
while(!infile.eof())
{
while ( getline(infile, line, '-') )
{
if ( getline(infile, line, '|') )
{
r = new data;
r->setRcourse_name(line);
r->setRcourse_code(3);//error not a string
r->setRcredit(3);//error not a string pre filled
r->setRinstructor(line);
cout << line << endl;
}
}
}
Then I tried to view it nothing is stored.
Firstly line 1 is very different to the remaining lines so you need a different parsing algorithm for them. Something like:
bool first = true;
while(!infile.eof())
{
if (first)
{
// read header line
first = false;
}
else
{
// read lines 2..n
}
}
Reading lines 2..n can be handled by making a stringstream for each line, then passing that in to another getline using '|' as a delimeter, to get each token (sam, scott, 12, H, 3.4, 1/11/1991, 3/15/2012)
if (getline(infile, line, '\n'))
{
stringstream ssline(line);
string token;
while (getline(ssline, token, '|'))
vector.push_back(token);
}
Reading the header line takes the exact same concept one step further where each token is then further parsed with another getline with '-' as a delimiter. You'll ignore each time the first tokens (course1, course1, number, professor) and use the second tokens (Maths, 3215, 3, Mark).
You are completely ignoring the line that you get inside the condition of the nested while loop. You should call getline from a single spot in your while loop, and then examine its content using a sequence of if-then-else conditions.