私はテキストファイルの行を読んでいますが、これが良い方法かどうか疑問に思っていますか? _number_of_lines variable
_を1減らす関数numberoflines
を書く必要がありました。なぜなら、whileループ内では、読み込む行ごとにnumber_of_lines変数に2を追加するからです。
_#include <iostream>
#include <fstream>
using namespace std;
int number_of_lines = 0;
void numberoflines();
int main(){
string line;
ifstream myfile("textexample.txt");
if(myfile.is_open()){
while(!myfile.eof()){
getline(myfile,line);
cout<< line << endl;
number_of_lines++;
}
myfile.close();
}
numberoflines();
}
void numberoflines(){
number_of_lines--;
cout<<"number of lines in text file: " << number_of_lines << endl;
}
_
他のもっと簡単なもっと良い方法はありますか?
最後にカウントを減らすというあなたのハックはまさにそれです-ハックです。
そもそもループを正しく記述する方がはるかに良いので、最後の行を2回カウントしません。
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;
}
個人的には、この場合、Cスタイルのコードは完全に受け入れられると思います。
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;
}
編集:もちろん、C++でも少し似たようなことができます。
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;
}
あなたの質問は、「ファイルにある行よりも1行多くなっているのはなぜですか?」
ファイルを想像してください:
_line 1
line 2
line 3
_
ファイルはASCIIのように表されます:
_line 1\nline 2\nline 3\n
_
(ここで_\n
_はバイト_0x10
_です。)
それでは、各getline
呼び出しの前後に何が起こるか見てみましょう:
_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: ^
_
さて、あなたはストリームがファイルの終わりを示すためにeof
をマークすると思いますよね?いや!これは、ファイルの終わりマーカーに到達するとgetline
がeof
を設定するためです "操作中" 。 getline
は_\n
_に達すると終了するため、ファイルの終わりマーカーは読み取られず、eof
にはフラグが付けられません。したがって、myfile.eof()
はfalseを返し、ループは別の繰り返しを通過します。
_Before 3: line 1\nline 2\nline 3\n
Stream: ^
After 3: line 1\nline 2\nline 3\n
Stream: ^ EOF
_
これをどのように修正しますか? eof()
を確認する代わりに、.peek()
がEOF
を返すかどうかを確認します。
_while(myfile.peek() != EOF){
getline ...
_
getline
の戻り値をチェックすることもできます(暗黙的にブールにキャストします):
_while(getline(myfile,line)){
cout<< ...
_
Cでcount行を実装すると、失敗することはありません。はい。通常、ファイルの最後に迷い"ENTER KEY"がある場合、1行余分に取得できます。
ファイルは次のようになります。
"hello 1
"Hello 2
"
以下のコード
#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;
}
forループあり:
std::ifstream myFile;
std::string line;
int lines;
myFile.open(path);
for(lines = 0; std::getline(myFile,line); lines++);
std::cout << lines << std::endl;