2011-07-21 14 views
17

C++でカスタムレクサーを実装していて、空白を読み込もうとすると、ifstreamはそれを読み上げません。私は>>を使用して文字で文字を読んでおり、すべての空白がなくなっています。 ifstreamにすべての空白を残してそれを私に読ませる方法はありますか?文字列全体を読むとき、空白で読み込みが止まることは知っていますが、文字で読むことでこの動作を避けることを望んでいました。ifstreamから読み込むと空白が読み込まれない

しようとしました:多くの回答が推奨する.get()、が、それはstd::noskipwsと同じ効果があり、つまり、私は今、すべてのスペースを得るが、ない私はいくつかの構造をlexのために必要な改行文字。ここで

は、問題のあるコード(拡張コメント切り捨て)

while(input >> current) { 
    always_next_struct val = always_next_struct(next); 
    if (current == L' ' || current == L'\n' || current == L'\t' || current == L'\r') { 
     continue; 
    } 
    if (current == L'/') { 
     input >> current; 
     if (current == L'/') { 
      // explicitly empty while loop 
      while(input.get(current) && current != L'\n'); 
      continue; 
     } 

は、私はwhileライン上で破壊し、それが入ってくるようcurrentのすべての値を見て、そして\rまたは\nがthem-間で間違いないですよん入力は入力ファイルの次の行にスキップします。

+0

while行を壊した場合、 'get'がcontinue行とwhile行ではなく' \ n'であるかのように、 'current'に' \ n'が表示されないことを期待しています。それとも私は誤解したことがありますか? –

+0

'L '\ n''は8bit 'char'ではなく16bit' wchar_t'ですが、違いはありません。 –

+0

@Charles:その後、ファイルの次の行の内容の表示が中断され、表示されなくなります。 @ルネ:それは 'wifstream'です。 – Puppy

答えて

-3

私はちょうどWindows APIを開いて、それを使ってファイル全体をバッファに読み込み、最初にバッファを文字単位で読み込みました。みんなありがとう。

13

は空白スキップ動作を無効にするマニピュレータがあります:

stream >> std::noskipws; 
+0

私はすべてのスペースを取得しますが、まだ改行はありません。 – Puppy

+3

また、 'stream.unsetf(ios_base :: skipws)'を使うこともできます。そのフォーマットフラグを手動で削除します。 – sth

+0

@sth:それはまさに 'noskipws'がすることです。 –

7

演算子>>空白(スペース、タブ、改行)を食べます。各文字を読むにはyourstream.get()を使用してください。

編集:

は注意してください:プラットフォーム(Windowsの、UN * X、Macが)改行のコーディングが異なります。 '\ n'、 '\ r'、またはその両方にすることができます。また、ファイルストリーム(テキストまたはバイナリ)を開く方法によって異なります。

編集(コード解析):

while(input.get(current) && current != L'\n'); 
    continue; 

ファイルの終わりではない場合、current\nが存在するであろうが達成されます。その後、あなたは最外whileループを続けます。そこでは、次の行の最初の文字がcurrentに読み込まれます。それはあなたが望むものではありませんか?

//: get.cpp : compile, then run: get < get.cpp 

#include <iostream> 

int main() 
{ 
    char c; 

    while (std::cin.get(c)) 
    { 
    if (c == '/') 
    { 
     char last = c; 
     if (std::cin.get(c) && c == '/') 
     { 
     // std::cout << "Read to EOL\n"; 
     while(std::cin.get(c) && c != '\n'); // this comment will be skipped 
     // std::cout << "go to next line\n"; 
     std::cin.putback(c); 
     continue; 
     } 
    else { std::cin.putback(c); c = last; } 
    } 
    std::cout << c; 
    } 
    return 0; 
} 

自体に適用されるこのプログラムは、その出力のすべてのC++行コメントをなくし:

は、私が( charcinの代わりに、 wchar_twifstreamを使用して)あなたの問題を再現してみました。内側のwhileループは、ファイルの最後までのすべてのテキストを使い果たしません。 putback(c)ステートメントに注意してください。それがなければ、改行は現れないだろう。

それはwifstreamために同じように動作しない場合は、それが一つの理由を除き、奇妙な非常に次のようになります。開かれたテキストファイルが16ビットのcharとして保存し、\n charが間違ったバイトで終わるされていません...

+0

'\ r'も取得しません.WindowsではCRLFというテキストモードで開きます。 – Puppy

+0

@DeadMG: 'int c = std :: cin.get();'を使うと、Enterキーを押したときにWindowsマシンでASCII 10を取得するので、同じ方法で 'ifstream'でも動作するはずです。 –

+0

それは何が起こるかではありません。何が起こるかは、ファイル全体がwhileループで読み込まれ、終了しないということです。意図したことは、あなたが言ったこととほぼ同じです。ラインの終わりが見つかると、ループは終了し、外側のループで続きます。 – Puppy

3

std::streambuf_iteratorにストリーム(またはそのバッファ)をラップしますか?これはすべての書式設定を無視し、素晴らしいイテレータインターフェイスを提供する必要があります。

また、はるかに効率的でばかばかしいアプローチでは、Win32 API(またはBoost)を使用してファイルをメモリマップすることもできます。その後、プレーン・ポインタを使用してそれをトラバースすることができ、実行時に何もスキップまたは変換されないことが保証されます。

+0

興味深いアイデア。私は実際にその特定のイテレータクラスを使用していませんでした。私は一見を受け取ります – Puppy

+0

私はこのイテレータがIOStreamsで動作する唯一の純粋な方法であることを発見しました。何が起きているのかIOStreams(遅い)と文字ごとのI/O(遅い)を組み合わせたものを期待しているので、もちろん遅いです。しかし、それは動作します! – jalf

2

ストリーム抽出プログラムは同じ動作をし、空白をスキップします。

すべてのバイトを読み込みたい場合は、stream.get(c)のような書式なし入力関数を使用できます。

+0

@ CharlesBaileyの答えとして:私はまだ改行文字を取得していません。 – Puppy

2

なぜ単にgetlineを使用しないのはなぜですか?

あなたは、すべての空白を取得し、あなたが行文字の終わりを得ることはありませんしながら、彼らはあなたがバイナリモードでストリームを開くことができます:)

2

をどこにあるか、あなたはまだ知っている:

std::wifstream stream(filename, std::ios::binary); 

これを行うと、ストリームに用意されているフォーマット操作が失われます。もちろん

std::wostringstream ss; 
ss << filestream.rdbuf(); 

、あなたが考えることができるようにostringstreamから文字列を取得すると、文字列の追加コピーをrquires:

他のオプションは、文字列に全体の流れを読み、その文字列を処理することですあなたが冒険している場合は、カスタムストリームを使用するようにこれを変更してください。 EDIT:誰かがistreambuf_iteratorについて言及しています。これはおそらくストリーム全体を文字列に読み込むよりも良い方法です。

関連する問題