2011-07-12 8 views
0

私は学校プロジェクトのためのコンパイラを書くことに取り組んでいます。この割り当てでは、テキストファイルのトークンをコンソールウィンドウに印刷するように求められています。私はそれを明確にしたいです私の宿題は私のために完了します。デバッグアサーションエラーの原因は何ですか?具体的には、私のコードで

私はこのファイルを反復処理し、charまたはc-stringの値(私の先生は彼の指示のこの部分をあいまいにしていました...)を連結して "token"という文字列変数に連結するこの愚かな関数を使っています" "main()"というファイルの最初の行を処理することはできますが、次の行にアクセスしようとすると2つのエラーのうちの1つが発生します。最初は、範囲外の文字列の下付き文字ですが、これは、存在しなかった文字列配列の一部にアクセスしようとしていたためだと思います。

Debug Assertion Failed Final.exe File:f:\dd\vctools\crt_bld\self_x86\crt\src\isctype.c Expression: (unsigned)(c+1) <= 256

私は私の機能とそれに関連するヘッダファイルが含まれている:私は取得しています最も普及エラーは、デバッグアサーションエラーです。関数呼び出し以外はmainで何も起こっていません。可能であれば、私が見ていないものを見ることができますか?私のコード体系は貧弱だと分かります。私はうそをつくことはありません(私は結局学校に通っています)。だから、コメント、批判、提案は大歓迎です。そしていつも、いつもありがとうございました。

.cppファイル(それが今のように)

#include <iostream> 
    #include <string> 

    using namespace std; 

    void tokenWork::openFile() 
    { 
     fileName = "test.txt"; 

     source.open(fileName); 

     if(!source.is_open()) 
     { 
     cout << "Cannot find file " << endl; 
     } 
    } 

    void tokenWork::traveseLine() 
    { 

    pos = 0; 
    while (!source.eof()) 
    { 
      getline(source,myLine); 
      int length = myLine.length(); 
      letters = new char[length]; 
      myLine.copy(letters,length); 

      c = letters[pos]; 

      if (isalpha(c)) 
      token = token + myLine[pos]; 
      else if (isdigit(c)) 
      token = token + letters; 
      else 
      { 
      cout << token << endl; 
      token = ""; 
      } 

      if (c == '{' || c == '}' || c == '+' || c == '=' || myLine[pos] == '(' || c == ')' || c == ';') 
       cout << myLine[pos] << endl; 
      c = letters[pos++]; 
    } 
} 

.hファイル

#ifndef H_LEX 
    #define H_LEX 

    #include <string> 
    #include <iostream> 
    #include <fstream> 

    using namespace std; 

    class tokenWork 
    { 
    public: 
    std::string fileName; 
    std::string myLine; 
    std::string token; 

    int pos; 
    int length; 
    int c; 

    char *letters; 

    ifstream source; 

    void openFile(); 
    void traveseLine(); 
    void closeFile(); 

}; 

    #endif 
+0

私の提案は、デバッガを使用する方法を学ぶことです。関数内にブレークポイントを設定し、エラーの原因を正確に調べるためにデバッグします。 – Chad

+0

このラインは何をしていますか? if(c == '{' || c == '}' || c == '+' || c == '=' || myLine [pos] == '(' || c == ') '|| c =='; ')。 – kmdent

+0

2行入力を提供できますか? – Arkadiy

答えて

1

あなただけ与えられた各ライン上のトークンを印刷したい場合は、私はすべてのことで非常に混乱していますあなたがやっている余分な仕事。あなたの関数ダウン(と小さな変更)を縮小すると、あなたのスタートを取得する必要があります。

// note, poorly named function, it traverses the whole file 
void tokenWork::traveseLine() 
{ 

pos = 0; 
while (!source.eof()) 
{ 
    getline(source,myLine); 

    int len = myLine.size(); 

    // NOTE: This was missing from your code, it traverses the line 
    //  that was read in with getline() above. 
    for(int x = 0; x < len; ++x) 
    { 
     // NOTE: This is (in my opinion) a slightly more readable 
     //  version of your if() statement above on tokens 
     //  It doesn't have all your tokens, additional ones 
     //  can be added by adding a case for them above the 
     //  line that prints them out. Since there is no break 
     //  statement, the functionality for all the cases above 
     //  fall through so they all get printed out. 
     switch(myLine[x]) 
     { 
      case '{': 
      case '}': 
      case '+': 
      case '=': 
      // add additional tokens as case statements as necessary 
      cout << myLine[x] << endl; // print it out 
      break; 
      default: // not a token 
      break; 
     } 
    } 
} 
+1

これはうまく見えますが、myLine.size()を格納するにはsize_tを使用してください(理由はありますが、コンパイラは64ビットプラットフォームで不平を言います)か、より良いconst_t size – stijn

+0

True - OPとの快適性を狙い、あまりにも多くの種類(それはまだ見られていない可能性が高い)を通過したいと思っています。 lenがsize_tに変更された場合、forループのxも同様になるはずです。 – Chad

2

あなたはそれを最大値である> 255値で引数を渡すとき、デバッグアサーションエラーが呼び出しからstd::isalpha/isdigitに発信することタイプchar(ここではintの代わりに使用しているはずです)を保持できます。私はソースファイルを提供していないので、正確な起源を知ることはできませんが、あなたは非常に簡単にそれを理解することができます。デバッガの下でプログラムを実行すると、アサートで破損します。コールスタックで上に移動し、あなたの手掛かりを与える変数の値を調べます。

ヒントのカップル:あなたがここにC++を使用している

  • 、生のchar配列を使用する必要はありません。代わりにstd :: stringを使用してください。
  • namepsace stdを使用しないでください。そのファイルを含むすべてのファイルはstd名前空間全体をインポートします
  • ヘッダにインクルードした場合、ソースファイルに再度インクルードする必要はありません
  • デバッガの使い方を学ぶことは、貴重なツールですなぜ何かが間違っているのを学ぶのを助けるでしょう
0

それはコードの特定の場所を指すのは難しいです - それは非常に多くの問題があります...

あなたはおそらく

token = token + letters; 

文字から結果を確認エラーがそう、nullで終わる(文字列::コピーはNULL終了を提供していない、とあなたはとにかくヌルのためのスペースを確保していない)ではありません+オペレータが最後に落ち、不快なものに遭遇します。

さらに、posを約getlineに1回増分してリセットしないように見えます。あなたのコードは内部ループがあったはずのように見えますが、私は何も見ません。あなたは(isdigitを使用するために

#include <cctype> 

に忘れてしまった

1

)とはisalpha()

この

c = letters[pos++]; 

は、バグの原因のように見えます。 posは常に増加しますが、それは今まで止まっていますか?最後の文字(letters.length() - 1)に達した場合はどうなり、この行にヒットしますか?私が疑う範囲外の配列。

関連する問題