I have a problem with C++ File input.
I have a file with n lines that each lines contains 4 variables. I need them read them into a hash table that I created. My problem is that I can't read the file correct way.
For example here the input file variables:
line id cont uniq-number Band
0 10 B 02020213456 DaftPunk
1 11 A 02030213456 Dazy
and so on..
The main problem is to read each variable in line until file EOF.
So I need read in each line these variables id, cout, uniq-number and band and while it is reading put these data inside a hash table to process them even further in C++.
Example
cout << "File" << endl;
int date,id;
string group,line,ch;
datar d;
hasher h1;
ifstream inFile;
inFile.open("file.txt");
while (getline (inFile,line))
{
// "reads" file each variable
inFile >> id >> ch >> date >> group;
//add these variable in line one to first hash line
d.id = id;
d.data = ch;
d.date= date;
d.group = group;
h1.add(d);
//must repeat until file EOF for each line
}
inFile.close();
In this code,
while (getline (inFile,line))
{
// "reads" file each variable
inFile >> id >> ch >> date >> group;
//add these variable in line one to first hash line
d.id = id;
d.data = ch;
d.date= date;
d.group = group;
h1.add(d);
//must repeat until file EOF for each line
}
the getline reads a line.
Then the loop body reads items from the next line.
Instead of that
inFile >> id >> ch >> date >> group;
do e.g.
istringstream linestream( line );
linestream >> id >> ch >> date;
getline( linestream, group );
The last getline in order to handle possible spaces in a name.
This assumes that the name is last on the line, as it currently is, and it assumes that it's not the case that every second line should be ignored (i.e., that that was bug).
It's also a good idea to add failure checking.
If a stream operation fails then the stream enters a failure state, and you can check that via the member function .fail().
Related
I am trying to read a file using ifstream in c++. The file has 5 columns and last column is the name column which contains the name with multiple spaces in the name. Some names have 1 and some have 2 spaces.
I want to read the name in a single variable instead of multiple ones.
I have used :
while (infile >> recordDate >> relativeHumidity >> airTemp >> tempUnit >> name1 >> name2 >>> name3){}
Above code works fine for the names having 2 spaces but when it reads the line which has a name with one space the name3 varialble stores the first value of next line.
Date RelativeHumidity Air Temp Units Meteorologist Name
5/13/2009 1.096000 34.630000 C D. Bernoulli
7/1/1903 0.313000 77.470000 f Sir C. Wren
Use getline to read to the end of line, that way you only need one variable.
while ((inFile >> recordDate >> relativeHumidity >> airTemp >> tempUnit) &&
std::getline(inFile, name))
{
}
You could try something like the following:
while (infile)
{
infile >> recordDate >> relativeHumidity >> airTemp >> tempUnit;
getline(infile, name);
const auto trim = [](const auto& s) {
return s.substr(
s.find_first_not_of(' ', 0),
s.find_last_not_of(' ', 0)
);
};
name = trim(name);
}
I am working on a program that reads from a file and pushes back the contents of that file into a vector. It will read until the file reaches a space and push that string into a vector, then continue after the space. I have written this code.
ifstream inFile;
inFile.open("message1.txt");
if (inFile.fail()) {
cerr << "Could not find file" << endl;
}
while (inFile >> S) {
code1.push_back(S);
}
I am just confused about the while (inFile >> S) actually does. I understand that it reads from the inFile until it reaches the end of file. But what does the inFile >> S condition actually do? Thanks for your time.
What the inFile >> S does is take in the file stream, which is the data in you file, and uses a space delimiter (breaks it up by whitespace) and puts the contents in the variable S.
For example:
If we had a file that had the follow contents
the dog went running
and we used inFile >> S with our file:
ifstream inFile("doginfo.txt")
string words;
while(inFile >> words) {
cout << words << endl;
}
we will get the following output:
the
dog
went
running
The inFile >> S will continue to return true until there are no more items separated by whitespace.
The expression inFile >> S reads a value into S and will return inFile.
This allows you to chain variables together like infile >> a >> b >> c;
Since this inFile is being used in a bool context, it will be converted to bool. And iostream objects are defined to convert to a bool that's true if and only if the object has no current error state.
I am having trouble getting istringstream to continue in while loop shown below. The data file is shown below also. I use getline from Input file to get the first line and put it in a istringstream lineStream. It passes through the while loop once, then it reads in the second line and goes back to the beginning of the loop and exits rather than continue through the loop. I have no clue why, if anyone could help I would thankful.
EDIT: The reason I have this while loop condition is because the file may contain lines of erroneous data. Therefore, I want to make sure the line I am reading in has the proper form shown below in the data file.
while(lineStream >> id >> safety){//keeps scanning in xsections until there is no more xsection IDs
while(lineStream >> concname){//scan in name of xsection
xname = xname + " " +concname;
}
getline(InputFile, inputline);//go to next xsection line
if(InputFile.good()){
//make inputline into istringstream
istringstream lineStream(inputline);
if(lineStream.fail()){
return false;
}
}
}
Data FILE
4 0.2 speedway and mountain
7 0.4 mountain and lee
6 0.5 mountain and santa
In the presented code, …
while(lineStream >> id >> safety){//keeps scanning in xsections until there is no more xsection IDs
while(lineStream >> concname){//scan in name of xsection
xname = xname + " " +concname;
}
getline(InputFile, inputline);//go to next xsection line
if(InputFile.good()){
//make inputline into istringstream
istringstream lineStream(inputline);
if(lineStream.fail()){
return false;
}
}
}
… the inner declaration of lineStream declares a local object, which ceases to exist when the execution passes out of that block, and which doesn't affect the stream used in the outer loop.
One possible fix is to invert the code a little bit, like this:
while( getline(InputFile, inputline) )
{
istringstream lineStream(inputline);
if(lineStream >> id >> safety)
{
while(lineStream >> concname)
{
xname = xname + " " +concname;
}
// Do something with the collected info for this line
}
}
I am having issues trying to get the program to read to the end of a line in a text file.
I am trying to read data from a text file (one item per line) with the following format (space-separated fields):
house (12345)
type (A = Auto or M = motorcylce)
license (WED123)
year (2012)
msrp (23443)
The data will be used to calculate vehicle registration total.
At the moment the program is reading all the lines which are formatted as above, however a house could have more than one vehicle, therefore there is additional data on the line (all but the first fields are repeated in this case).
For example:
111111 A QWE123 2012 13222 M RTW234 2009 9023
// ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
// first vehicle second vehicle
Once I reach a line which has the additional data, the program does not read it and goes into an infinite loop. How can I read the additional data in the line to get to the end of the file and stop the program from an infinite loop.
#include <stdlib.h>
#include <iostream>
#include <fstream>
using namespace std;
int main () // Function Header
{ // Start Function
int house;
char type;
string license;
int year, msrp ;
char ch;
ifstream inData;
ofstream outData;
inData.open("register.txt");
outData.open("vehicle.txt");
inData >> house; // Priming Read
while (inData) { // Test file stream variable
do {
inData >> type;
inData >> license;
inData >> year;
inData >> msrp;
outData << house << type << license << year << msrp << endl;
ch = inData.peek();
inData >> house;
} while(ch != '\n'); // Check for end of line
} // End while
system ("Pause");
return 0;
}
Your program will have a hard time detecting the end of the line. When it tries to read the "extra data" but encounters the next line instead, an error occurs on the stream, preventing you from being able to read again.
You can "fix" your program by not reading the house value in the inner loop. Instead, read it after you have detected the end of line.
ch = inData.peek();
//inData >> house; // WRONG: house might be next vehicle type
} while(ch != '\n'); // Check for end of line
inData >> house; // CORRECT
} // End while
However, a better way to handle this may be to use getline and istringstream. First get an entire line of input with getline. Place the input into an istringstream. Then, get the rest of the data from that. See M. M.'s version for an illustration of this.
in.open(filename.c_str(), ifstream::in);
string name, email, group;
while (in >> name >> email >> group) {
in >> name >> email >> group;
cout << name << email << group);
...
}
in.close();
Consider this code where in is of type ifstream and filename is the name of the file from which we read the data. Format of input file is perfectly fine - many lines with 3 string in each.
This piece should simply print all of the data in the file but what id does is printing all of the lines except for the first line. Why is the first line skipped?
Drop in >> name >> email >> group; from the body of the loop. The one in the condition is enough.
You're reading too much.
while (in >> name >> email >> group)
Already reads the data once, the next line reads it again, overwriting your data. Get rid of the repetition and your cout should work just fine.
in.open(filename.c_str(), ifstream::in);
string name, email, group;
while (in >> name >> email >> group) { //Reads the data into the variables
cout << name << email << group; //Outputs the variables.
...
}
in.close();
Consider this line:
while (in >> name >> email >> group) {
each time the program hits this line, it executes the code inside the brackets. In this case, 'in' is read and populates name, email, group even before actually entering the body of the loop.
Thus, when the body of the loop is executed, the first line has already been read.
If you strings are not seperated by new line operator in the input file use code the blow to read it.
ifstream in;
in.open("urfile.txt",ios::beg);
string name, email, group;
while (in.good()) {
in >> name >> email >> group;
cout << name << email << group;
}
in.close();