I\'m reading lines off of text file and I\'m wondering if this is a good way to go? I had to write the function numberoflines
to decrease the number_of_li
Your hack of decrementing the count at the end is exactly that -- a hack.
Far better to write your loop correctly in the first place, so it doesn't count the last line twice.
int main() {
int number_of_lines = 0;
std::string line;
std::ifstream myfile("textexample.txt");
while (std::getline(myfile, line))
++number_of_lines;
std::cout << "Number of lines in text file: " << number_of_lines;
return 0;
}
Personally, I think in this case, C-style code is perfectly acceptable:
int main() {
unsigned int number_of_lines = 0;
FILE *infile = fopen("textexample.txt", "r");
int ch;
while (EOF != (ch=getc(infile)))
if ('\n' == ch)
++number_of_lines;
printf("%u\n", number_of_lines);
return 0;
}
Edit: Of course, C++ will also let you do something a bit similar:
int main() {
std::ifstream myfile("textexample.txt");
// new lines will be skipped unless we stop it from happening:
myfile.unsetf(std::ios_base::skipws);
// count the newlines with an algorithm specialized for counting:
unsigned line_count = std::count(
std::istream_iterator<char>(myfile),
std::istream_iterator<char>(),
'\n');
std::cout << "Lines: " << line_count << "\n";
return 0;
}
with for-loop:
std::ifstream myFile;
std::string line;
int lines;
myFile.open(path);
for(lines = 0; std::getline(myFile,line); lines++);
std::cout << lines << std::endl;
In C if you implement count line it will never fail. Yes you can get one extra line if there is stray "ENTER KEY" generally at the end of the file.
File might look some thing like this:
"hello 1
"Hello 2
"
Code below
#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "file1.txt"
int main() {
FILE *fd = NULL;
int cnt, ch;
fd = fopen(FILE_NAME,"r");
if (fd == NULL) {
perror(FILE_NAME);
exit(-1);
}
while(EOF != (ch = fgetc(fd))) {
/*
* int fgetc(FILE *) returns unsigned char cast to int
* Because it has to return EOF or error also.
*/
if (ch == '\n')
++cnt;
}
printf("cnt line in %s is %d\n", FILE_NAME, cnt);
fclose(fd);
return 0;
}
I think your question is, "why am I getting one more line than there is in the file?"
Imagine a file:
line 1
line 2
line 3
The file may be represented in ASCII like this:
line 1\nline 2\nline 3\n
(Where \n
is byte 0x10
.)
Now let's see what happens before and after each getline
call:
Before 1: line 1\nline 2\nline 3\n
Stream: ^
After 1: line 1\nline 2\nline 3\n
Stream: ^
Before 2: line 1\nline 2\nline 3\n
Stream: ^
After 2: line 1\nline 2\nline 3\n
Stream: ^
Before 2: line 1\nline 2\nline 3\n
Stream: ^
After 2: line 1\nline 2\nline 3\n
Stream: ^
Now, you'd think the stream would mark eof
to indicate the end of the file, right? Nope! This is because getline
sets eof
if the end-of-file marker is reached "during it's operation". Because getline
terminates when it reaches \n
, the end-of-file marker isn't read, and eof
isn't flagged. Thus, myfile.eof()
returns false, and the loop goes through another iteration:
Before 3: line 1\nline 2\nline 3\n
Stream: ^
After 3: line 1\nline 2\nline 3\n
Stream: ^ EOF
How do you fix this? Instead of checking for eof()
, see if .peek()
returns EOF
:
while(myfile.peek() != EOF){
getline ...
You can also check the return value of getline
(implicitly casting to bool):
while(getline(myfile,line)){
cout<< ...