2009-06-24 3 views
1

でのPascalコンパイラを構築するとき、私は、次のポインタ問題C

char *words[29]={ 
     "program", 
     "label", 
     "integer", 
     "word", 
     "char", 
     "byte", 
     "shortint", 
     "logint", 
     "real", 
     "single", 
     "double", 
     "string", 
     "boolean", 
     "var", 
     "procedure", 
     "function", 
     "begin", 
     "end", 
     "if", 
     "then", 
     "else", 
     "or", 
     "and", 
     "div", 
     "not", 
     "do", 
     "while", 
     "mod" 
}; 
char message[30]; 

を宣言していたし、私は機能でそれを使用しようとした私のコンパイラ の字句解析上のいくつかの問題に直面しています

  for(handle=0;(&words[handle] != NULL);handle++) 
      { 
       message = &words[handle]; 
       if(!strcmp(token,message)) 
        message='words'; 
      } 

しかし、実行しようとしたときに、私は次のエラーを受信して​​います:

について(ラインメッセージ= &単語[ハンドル];):警告C4047: '=' 'チャー[30]' に対する 'チャー**'

から 間接のレベルが異なる(ラインメッセージ= &単語[ハンドル];);定数

にあまりにも多くの文字: エラーC2015エラーC2106: '=')は 左のオペランドが(ラインメッセージ= '単語' に関するL値

なければなりません

に関して(行メッセージ= '言葉';): エラーC2106:「=」:左オペランドは

が、私はそのようにポインタを操作することはできません左辺値でなければなりませんか? ご意見はありますか?

答えて

3

3つのこと:

  1. アンパサンド(&)が余分です。 words[handle]のタイプはchar *です。つまり、文字列です。必要なものがあります。あなたはそれのアドレスを取る必要はありませんchar *

  2. messageに直接割り当てることはできません=は配列であるためです。 Cはあまりファンキーな言語ではありません。 messagechar *messageに変更することができるので、配列ではなくポインタです。またはstrcpy(dst, src)関数を使用してコピーすることができます。たとえば、strcpy(message, "words")です。それが停止したときに知っているので、

  3. あなたforループがwords配列のNULLポインタを探します - しかし、あなたは、アレイ内のNULLを持っていません!最後にNULLを追加する必要があります。書かれているように、通常の文字列しかないので、ループはそれが探しているヌルポインタを決して見つけず、メモリの未知のゾーンにチャージします。

希望します。

+0

多くのお役に立てました! –

3

あなたがそこにエラーの数があります、代わりに&言葉[ハンドル]の

  • を 言葉[ハンドル]
  • を使用しているもの、あなたがメッセージ=「言葉」でやろうとしていますか?少なくとも3つのエラーがあります。文字列には二重引用符を使用し、一重引用符は使用しません。メッセージは定数ですが、変更することはできません。文字列をコピーするには、演算子だけでなく、strcpy()を使用する必要があります。
  • 文字列が等しい場合、strcmp()は0を返します。あなたはあなたがあなたのコードで多くの問題を持っているあなたの配列
2

の最後にNULLを含めるのを忘れて

  • あなたのロジックを逆にする必要があります。まず、キーワードの配列をconst char *words[]と宣言してください。 constを使わずに文字列定数をchar *と宣言するのは悪い習慣です。レガシーコードがまだコンパイルできるようにすることだけが許されています。

    脆弱であるため、宣言で配列サイズ29を指定しないでください。空の括弧を使用して、コンパイラに配列のサイズを把握させるだけです。 sizeof(words)/sizeof(words[0])を実行して配列のサイズを取得することができます。これは、wordsから要素を追加または削除しても正しいです。

    次に、forループは決して終了しません(ただし、ある時点でほぼ確実にセグメンテーションが行われます)。値のアドレスを取るとヌルポインタが返されることはないので、&words[handle] != NULLは常にtrueになります。

    for(handle = 0; handle < sizeof(words)/sizeof(words[0]); handle++) 
    

    messageは文字の配列として宣言されます。ループを反復処理する適切な方法は、単にエントリの数を数えることです。配列は割り当て可能ではなく、左辺値ではありません。アレイに割り当てる場合は、strcpy()(選択された場合を除いて、バッファオーバーフローの可能性があるため推奨されません)、strncpy()memcpy()、またはstrncpy_s()(Windowsのみ)などのデータを明示的にデータにコピーする必要があります。

    しかし、この場合でも、配列は必要ありません。ポインタを割り当てたいだけです。代わりにmessageconst char *としてください。 messageが正しく宣言を使用すると、どうなる:

    const char *message; 
    ... 
    message = words[handle]; 
    if(!strcmp(token, message)) 
        message = "words"; 
    

    を最後の文であり、あなたはそれ定数文字列にするwordsの周りに二重引用符を使用する必要があります。一重引用符は一文字定数(例:'A')です。技術的には複数の文字を含むことができますが、結果の整数定数のエンディアンは実装定義であり、この場合は必要ではありません。

    また、message = "words";行で何をしようとしているのかよく分かりません。変数wordsを使って巧妙なトリックをしようとしている場合は、今すぐ停止してください。それはうまくいかないでしょう。 Cには反射がありません。