2016-12-07 9 views
0

テキストファイル内のコメント、空白行、余分なスペースを削除して残りの要素をトークン化しようとしています。各トークンは前後にスペースが必要です。ここでC++でコメント、余分な空白、空白行を削除して、テキストファイルから要素をトークン化します。

exampleFile.txt 
var 

/* declare variables */a1 , 
b2a ,  c, 

は今のとして働いているものだ、

string line; //line: represents one line of text from file 
ifstream InputFile("exampleFile", ios::in); //read from exampleFile.txt 

//Remove comments 
while (InputFile && getline(InputFile, line, '\0')) 
{ 
    while (line.find("/*") != string::npos) 
    { 
     size_t Begin = line.find("/*"); 
     line.erase(Begin, (line.find("*/", Begin) - Begin) + 2); 
     // Start at Begin, erase from Begin to where */ is found 
    } 
} 

これは、コメントを削除しますが、私はこの問題が発生している間トークン化する方法を見つけ出すように見えることはできません。

だから私の質問は以下のとおりです。

  • はそれがコメント、スペース、空行を削除して、このwhile文ですべてをトークン化することは可能ですか?
  • トークン化される前に各トークン間にスペースを追加する機能を実装するにはどうすればよいですか? cのようなトークンは、cと、個々に認識される必要があります。

ありがとうございました!

+1

トピックをオフにする:あなた自身の検索を保存します。 'while((size_t Begin = line.find( "/ *"))!= string :: npos) ' – user4581301

+0

オフトピック:ブロックコメントが同じ行ですか? – user4581301

+1

そして別の話題:プログラムがwhile(line.find( "/ *")!= string :: npos)で/ *を見つけたときに何が起こるか考えてみましょう。 – user4581301

答えて

0

空白文字をスキップする必要があり、新しい行を気にしない場合は、operator>>でファイルを読むことをおすすめします。あなたは、単に書くことができ :ヘルパー関数として実装することができ

std::string word; 
bool isComment = false; 
while(file >> word) 
{ 
    if (isInsideComment(word, isComment)) 
     continue; 

    // do processing of the tokens here 
    std::cout << word << std::endl; 
} 

は、次のとおりです。

bool isInsideComment(std::string &word, bool &isComment) 
{ 
    const std::string tagStart = "/*"; 
    const std::string tagStop = "*/"; 

    // match start marker 
    if (std::equal(tagStart.rbegin(), tagStart.rend(), word.rbegin())) // ends with tagStart 
    { 
     isComment = true; 
     if (word == tagStart) 
      return true; 

     word = word.substr(0, word.find(tagStart)); 
     return false; 
    } 

    // match end marker 
    if (isComment) 
    { 
     if (std::equal(tagStop.begin(), tagStop.end(), word.begin())) // starts with tagStop 
     { 
      isComment = false; 
      word = word.substr(tagStop.size()); 
      return false; 
     } 

     return true; 
    } 

    return false; 
} 

あなたの例では、これは、プリントアウトします:

var 
a1 
, 
b2a 
, 
c, 

上記のロジックをすべきも興味があれば、複数のコメントを扱います。

ただし、関数の実装は、コメントトークンに関する前提条件に応じて変更する必要があることを示します。たとえば、それらは常に他のwordsの空白で区切られていますか?または、var1/*comment*/var2式が解析される可能性はありますか?上記の例は、このような状況では機能しません。

したがって、別のオプション(ファイルの開始点と終了点のトークンが一致することを保証するために)を読み取る行またはさらにはデータの断片を読み込み、コメントマーカーの位置をfindまたはregexから学習することもできます後でそれらを取り除く。

+0

私は理解しています、これは役に立ちます!ありがとうございました! –

+0

'line == tagStart'は文字列全体を捕捉するだけです。ファイルから行を読み込むとき、行は行全体に設定されます。ですから、私はline [i] + line [i + 1]のように文字列の一部を "/ *"や "* /"と比較する必要があります。 –

+0

あなたが正しいことを理解しているかわかりません。混乱を避けるために、私は変数名 'line'を' word'に更新しました。これはそれが含んでいるものです(一般的なファイル行ではありません)。 'var/* comment */var'のようなケースを扱う必要があるなら、' std :: equal'を使うように関数を更新しました。しかし、私が書いたように、これは一般的な考えであり、あなたの特定のニーズに適応する必要があります。おそらく、あなたが実装の更新を必要とする質問で共有していない詳細があります。 – Dusteh

関連する問題