Whats the optimal conditional for counting number of lines in text file? - c++

I've got the following code where I'm trying to count the number of lines in an input file, and I've tried several different ways of implementing it, but no luck.
int checkData(string File)
{
string temp;
int linecount = 0;
ifstream input(File);
input.open(File);
while ()
{
getline(input,temp);
linecount++;
temp.clear();
}
return linecount;
}
So far, I've tried:
while(!input.eof())
{
...
}
and
while(getline(input,temp).good())
{
...
}
The first doesnt break the loop, and I'm not quite sure why. (I'm fairly sure) that getline has a built in stream buffer, so it should automatically read the net line everytime I pull in a line and throw it back out, but no dice. For the second, the loop doesn't execute at all, which still doesn't make sense to me (that says that the first line of file isn't good input?).
The test file I'm using is:
this is a test this Cake
this is a test this Cake
this is a test this Cake
this is a test this Cake
So linecount should be returning as 4 when executing correctly. Before I execute this, I've already checked to make sure the file is opening correctly.
output

int number_of_lines = 0;
string line;
ifstream myfile("textexample.txt");
while (std::getline(myfile, line))
++number_of_lines;
Hope it helps.

Related

I can't load text from file properly

I can't seem to find what's wrong with this piece of code. It's a function that will load a couple of simple settings from a file. The problem is that the cout in the while loop doesn't show anything, only blank and an end line. It was put there for testing. Also the array "config_temp" only has blanks. I always used this method and even looked in previous projects and tutorials how it was written there. I can't find the expenation for this. Please help.
void load()
{
string config_temp[5];//temporary array into which the config is loaded to
int cc=1;//config counter
int ac=0;//array counter
ifstream file;
string line;
file.open("config.txt",ios::in);
while(getline(file,line))
{
if(cc%2!=1)
{
cout<<line<<endl;
config_temp[ac]=line;
ac++;
}
cc++;
}
file.close();
for(int i=0;i<=4;i++)
{
cout<<config_temp[i]<<endl;
}
frames=sti(config_temp[0]);
res_width=sti(config_temp[1]);
res_height=sti(config_temp[2]);
states=sti(config_temp[3]);
frequency=sti(config_temp[4]);
global_state=0;
}

Issue reading multiple lines from .txt file in C++

I'm trying to create a student database system for a school project. I'm trying to create a function that will search a .txt file for the student id and return all of the other variables on the string. This is working great if I search for the id of the student on the first line of the txt file but isn't capturing anything if I search for a student on another line. Am I missing something obvious?
The student data is 16 strings delimited by commas on each line. The student ID is the first string.
Thanks for any assistance!
StudentType findStudent(int studentToFind)
{
ifstream inFile;
inFile.open("students.txt");
string currentLine;
string dataRead[16];
istringstream is;
int currentStudent;
if (inFile)
{
while (getline(inFile, currentLine))
{
is.str(currentLine);
for (int i = 0; i < 16; i++)
{
getline(is, dataRead[i], ',');
}
currentStudent = stoi(dataRead[0]);
if (currentStudent == studentToFind)
{
/*
Do stuff here
*/
inFile.close();
return foundStudent;
}
cin.ignore(); // Not sure if this is needed but I was trying to
// clear the \n char if that was causing the issue
}
}
}
First : you aren't using cin, so get rid of cin.ignore().
Second : you should make sure you ALWAYS close infile at the end... so I would suggest not returning early or closing early, but using a break statement to exit your loop and then have a single return of whether you found it or not.
Third: Now that you removed all the 'gorp' we can finally hone in on the problem ... effectively the question is do we read all the lines?
Well let's check that, try printing out currentLine each time at the beginning of the while loop, if you know currentLine is updated properly, is is getting updated each time? yes...
ok then look at your next loop let's print out currentStudent each time... does currentStudent print the right value for each line? i.e. is the getline write into dataRead[i] actually writing what you think it should be to the right space?
Did you find the problem yet?
This is the kind of problem you need to learn how to solve yourself using print statements and a debugger. That what its for. If you are in visual studio run in debug mode and step through it... if not, use gdb. learn it and get used to it, you'll be using it a lot!
good luck

Problems using getline()

I'm running out of hair to pull out, so I thought maybe someone here could help me with this frustration.
I'm trying to read a file line by line, which seems simple enough, using getline(). Problem is, my code seems to keep ignoring the \n, and putting the entire file into one string, which is problematic to say the least.
void MakeRandomLayout(int rows, int cols)
{
string fiveByFive = "cubes25.txt";
string fourByFour = "cubes16.txt";
ifstream infile;
while (true) {
infile.open(fourByFour.c_str());
if (infile.fail()) {
infile.clear();
cout << "No such file found";
} else {
break;
}
}
Vector<string> cubes;
string cube;
while (std::getline(infile, cube)) {
cubes.add(cube);
}
}
Edits: Running OSX 10.7.
The infinite loop for the file is unfinished, will eventually ask for a file.
No luck with extended getline() version, tried that earlier.
Same system for dev and build/run.
The text file i'm reading in looks as follows:
AAEEGN
ABBJOO
ACHOPS
AFFKPS
AOOTTW
CIMOTU
DEILRX
DELRVY
DISTTY
EEGHNW
EEINSU
EHRTVW
EIOSST
ELRTTY
HIMNQU
HLNNRZ
Each string is on a new line in the file. The second one that I'm not reading in is the same but 25 lines instead of 16
Mac software recognizes either '\r' or '\n' as line-endings, for backward compatibility with Mac OS Classic. Make sure that your text editor hasn't put '\r' line endings in your file when your processing code is expecting '\n' (and verify that the '\n' characters you think are in the middle of the string aren't in fact '\r' instead.
I suspect that you are failing to display the contents of Vector correctly. When you dump the Vector, do you print a \n after each entry? You should, because getline discards the newlines on input.
FYI: the typical pattern for reading line-by-line is this:
Vector<string> cubes;
string cube;
while(std::getline(infile, cube)) {
cubes.add(cube);
}
Note that this will discard the newlines, but will put one line per entry in Vector.
EDIT: For whatever it is worth, if you were using an std::vector, you could slurp the file in thusly:
std::ifstream ifile(av[1]);
std::vector<std::string> v(
(std::istream_iterator<std::string>(ifile)),
std::istream_iterator<std::string>());

Reading BSDF data format

I have been required to write a function that reads the BSDF data format defined by Zemax
An example of such file can be found at the following page: BSDF file example
I would like to use, if possible, only standard ifstream functions.
I have already prepared all the necessary datamembers inside a dedicated class.
I am now trying to write the function that reads the data from the file.
Problems:
how do I exclude comment lines? as documented, they start with an hash # I was going for something like
void ReadBSDFFile(myclass &object)
{
ifstream infile;
infile.open(object.BRDFfilename);
char c;
infile.get(c);
while (c == "#") // Problem, apparently I cannot compare in this way. How should I do it?
{
getline(infile, line);
infile.get(c);
}
// at this point I would like to go back one character (because I do not want to lose the non-hash character that ended up in *c*)
infile.seekg(-1, ios_base::cur);
// Do all the rest
infile.close();
}
in a similar way, I would like to verify that I am at the correct line later on (e.g. the "AngleOfIncidence" line). Could I do it in this way?
string AngleInc;
infile >> AngleInc;
if (AngleInc != "AngleOfIncidence")
{
//error
}
Thanks to anyone who will comment/help. Constructive criticism is welcomed.
Federico
EDIT:
Thanks to Joachim Pileborg below, I managed to proceed up to the data blocks part of the file.
Now I have the following problem. When reaching the datablocks, I wrote the following piece of code, but at the second iteration (i = 1) i receive the error message for the TIS line.
Could someone help me understand why this does not work?
Thanks
Note: blocks is the number on the AngleOfIncidence line, rows the one on the ScatterAzimuth line and columns the one on the ScatterRadial. I tested and verified that this part of the function works as desired.
// now reading the data blocks.
for (int i=0; i<blocks; i++)
{
// TIS line
getline(infile, line);
if (line.find("TIS") == string::npos)
{
// if not, error message
}
// Data block
for (int j=0; j<rows; j++)
{
for (int k=0; k<columns; k++)
{
infile >> object.BRDFData[i][j][k];
}
}
}
EDIT 2:
solved adding infile.seekg(+2, ios_base::cur); as a last line of the i loop.
The reading loop could be simplified like this:
std::string line;
while (getline(infile, line))
{
if (line[0] != '#')
{
// Not a comment, do something with the line
if (line.find("AngleOfIncidence") != std::string::npos)
{
// On the AngleOfIncidence line, do special things here
}
}
}
It's might not be optimal, just something written at the top of my head, but should work.
From the description of the format you provided:
Any line that starts with the # symbol is ignored as a comment line.
So what you need to do is the following
Read the file line by line
If the line starts with # ignore it
Otherwise process the line.
The while you have used is wrong. Use the getLine function instead and compare its first character with the #.

getline() reads an extra line

ifstream file("file.txt");
if(file.fail())
{
cout<<"Could not open the file";
exit(1);
}
else
{
while(file)
{
file.getline(line[l],80);
cout<<line[l++]<<"\n";
}
}
I am using a two dimensional character array to keep the text (more than one line) read from a file to count the number of lines and words in the file but the problem is that getline always reads an extra line.
Your code as I'm writing this:
ifstream file("file.txt");
if(file.fail())
{
cout<<"Could not open the file";
exit(1);
}
else
{
while(file)
{
file.getline(line[l],80);
cout<<line[l++]<<"\n";
}
}
The first time getline fails, you still increment the line counter and output the (non-existing) line.
Always check for an error.
extra advice: use std::string from the <string> header, and use its getline function.
cheers & hth.
The problem is when you're at the end of the file the test on file will still succeed because you have not yet read past the end of file. So you need to test the return from getline() as well.
Since you need to test the return from getline() to see if it succeeded, you may as well put it right in the while loop:
while (file.getline(line[l], 80))
cout << line[l++] << "\n";
This way you don't need a separate test on file and getline().
This will solve your problem:
ifstream file("file.txt");
if(!file.good())
{
cout<<"Could not open the file";
exit(1);
}
else
{
while(file)
{
file.getline(line[l],80);
if(!file.eof())
cout<<line[l++]<<"\n";
}
}
Its more robust
Does the file end with a newline? If it does, the EOF flag will not be triggered until one extra loop passes. For example, if the file is
abc\n
def\n
Then the loop will be run 3 times, the first time it will get abc, the second time it will get def and the third time it will get nothing. That's probably why you see an additional line.
Try checking the failbit on the stream AFTER the getline.
Only do the cout if file.good() is true. The extra line you're seeing comes from the last call to file.getline() which reads past the end of the file.