[解決済み] std :: ifstream で LF, CR, CRLF を扱えるようにする?
質問
具体的に興味があるのは
istream& getline ( istream& is, string& str );
. ifstream のコンストラクタに、すべての改行エンコーディングを '\n' に変換するよう指示するオプションはありますか? を呼び出すことができるようにしたいです。
getline
を呼び出すことができ、それがすべての行末を優雅に処理するようにしたいのです。
更新 : はっきり言って、私はほとんどどこでもコンパイルできて、ほとんどどこからでも入力を受けられるようなコードを書きたいのです。その中には、稀に '\r' が '\n' と共に存在するファイルも含まれます。
この問題を回避するのは簡単ですが、すべてのテキストファイル形式を柔軟に処理するための、標準の正しい方法について、私はまだ興味を持っています。
getline
は全行、'˶'までを文字列に読み込んでいます。この'˶'はストリームから消費されますが、getlineは'˶'を文字列に含めません。ここまではいいのですが、'˶'の直前に'˶'があって、それが文字列に含まれるかもしれません。
があるのですが の3種類の改行があります。 がある。 Unix系では'en'、古いMac系では'en'、Windowsでは'en'と'en'が対になっていることが多い。
問題なのは
getline
では文字列の末尾に '\r' が残ってしまうことです。
ifstream f("a_text_file_of_unknown_origin");
string line;
getline(f, line);
if(!f.fail()) { // a non-empty line was read
// BUT, there might be an '\r' at the end now.
}
編集
Neil の指摘に感謝します。
f.good()
は私が望んでいたものではないことを指摘してくれたNeilに感謝します。
!f.fail()
は私が欲しいものです。
私はそれを自分で手動で削除することができます(この質問の編集を参照)、それはWindowsのテキストファイルのために簡単です。しかし、私は、誰かが '\r' だけを含むファイルを送り込むことを心配しています。その場合、getline はそれが 1 行であると考え、ファイル全体を消費すると推測されます!
...そしてそれは、Unicode を考慮さえしていません :-)
...多分Boostはどんなテキストファイルタイプからでも一度に1行ずつ消費する素晴らしい方法をもっているのでしょう?
編集 Windowsのファイルを処理するために、これを使っているのですが、やはり必要ないような気がします そして、これは、'˶'ᴗ'ᴗ'ᴗ'のみのファイルにはフォークしません。
if(!line.empty() && *line.rbegin() == '\r') {
line.erase( line.length()-1, 1);
}
どのように解決するのですか?
Neil が指摘したように、"C++ ランタイムは、特定のプラットフォームの行末規則が何であれ、正しく対処するはずです。
しかし、人々は異なるプラットフォーム間でテキスト ファイルを移動させるので、それでは十分ではありません。
しかし、異なるプラットフォーム間でテキストファイルを移動させることもあるので、それだけでは不十分です。
std::istream& safeGetline(std::istream& is, std::string& t)
{
t.clear();
// The characters in the stream are read one-by-one using a std::streambuf.
// That is faster than reading them one-by-one using the std::istream.
// Code that uses streambuf this way must be guarded by a sentry object.
// The sentry object performs various tasks,
// such as thread synchronization and updating the stream state.
std::istream::sentry se(is, true);
std::streambuf* sb = is.rdbuf();
for(;;) {
int c = sb->sbumpc();
switch (c) {
case '\n':
return is;
case '\r':
if(sb->sgetc() == '\n')
sb->sbumpc();
return is;
case std::streambuf::traits_type::eof():
// Also handle the case when the last line has no line ending
if(t.empty())
is.setstate(std::ios::eofbit);
return is;
default:
t += (char)c;
}
}
}
そして、これがテストプログラムです。
int main()
{
std::string path = ... // insert path to test file here
std::ifstream ifs(path.c_str());
if(!ifs) {
std::cout << "Failed to open the file." << std::endl;
return EXIT_FAILURE;
}
int n = 0;
std::string t;
while(!safeGetline(ifs, t).eof())
++n;
std::cout << "The file contains " << n << " lines." << std::endl;
return EXIT_SUCCESS;
}
関連
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み] 数値定数の前にunqualified-idを付けて、数値を定義することを期待する。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー
-
[解決済み] using namespace std;」はなぜバッドプラクティスだと言われるのですか?
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] static_cast, dynamic_cast, const_cast, reinterpret_cast はいつ使うべきですか?
-
[解決済み] GitでCRLF(キャリッジリターン、ラインフィード)を処理するための戦略とは?
-
[解決済み] テキストファイルの行末を調べるには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み】C++でランダムな2倍数を生成する
-
[解決済み] error: 'if' の前に unqualified-id を期待した。
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む