1

以下は、lex の C コードです。以下に示す 3 つの入力文字列があります。最初の 2 つは正しく出力されます。3 番目の入力文字列の最後に、出力される 2 つの奇妙な文字があります。これはヌル文字が原因であることはわかっています。しかし、私のコードはそれを処理し、最初の 2 つの入力文字列では発生しません。

1 番目の入力文字列 : (c,a,b,ma,mb,low) 2 番目の入力文字列 : (c,a,b,ma,mb+1,low) 3 番目の入力文字列 : (c,data, istart, mid,BASE )

コードが実行されると、func_initial_var には文字列に従って「(」が含まれ、func_var には残りの文字列が含まれます。

問題は、3 番目の入力文字列のみです。3 番目の文字列の末尾に 2 つの余分な文字を追加すると、適切に出力され、割り当てられる余分なスペースが 2 つあるとします。私の質問は、なぜ 3 番目の入力文字列だけにあるのですか? なぜ最初の2つにしないのですか?助けてください。これは昨日の朝から私を悩ませています。ありがとう。

    char *func_var = "";
    char *func_initial_var = "";

<SOME_STATE>.       { char c;
                    func_initial_var = strdup(yytext);
                    c = input();
                    func_var = (char*) malloc(sizeof(char));
                    for(q=0;;q++) {
                        if(c == ')')
                        {
                          func_var[q] = c;
                          printf("%s\n",func_var);
                          BEGIN SOME_STATE_X;
                          break;
                        }
                    func_var[q] = c;
                    printf("%s\n",func_var);
                    temp_func = (char*) realloc(func_var,(q+2)*sizeof(char));
                    if(temp_func != NULL) 
                        {
                        func_var = temp_func;
                        } else {
                      free(func_var);
                      printf("Error allocating memory\n");
                      return 1;
                        }
                    c = input();
                      }
                    }
4

2 に答える 2

0

次のように、より多くのメモリを割り当ててみることができます。

func_var = (char*) malloc(sizeof(char)* strlen(func_initial_var));

あなたのコードでは、4 バイト (sizeof char) を割り当てています。

于 2013-07-26T15:35:14.340 に答える
0

これはしばらくの間未公開のままでしたが、答えのヒントはコメントにあります。問題は、lex/flex に関するものではありません。Cの文字、文字の配列、および文字列の違いを理解するのは単なる問題です。作成されたコーディング エラーから、質問は、文字ポインターと文字配列を使用してコーディングする際に、初心者がそれらの違いを理解する際に混乱することを示しています。要約は、混乱のポイントのいくつかを示すのに役立つ場合があります。

Cのこれらの構造を図形式で見てみましょう。

1 つの文字は次のようになります。

           .---.
char c;    | c |
           `---'

2 文字の配列は次のようになります。

           .----.----.
char c[2]; |c[0]|c[1]|
           `----'----'

2 文字の文字列は次のようになります。

           .---.  .----.----.---.
char *s;   | s--->|s[0]|s[1]|0x0|
           `---'  `----'----'---'

単一の文字を含む文字列は、次のようになります。

           .---.  .----.---.
char *s;   | s--->|s[0]|0x0|
           `---'  `----'---'

結果として、文字または文字の配列が文字列にコピーされるか、文字列として使用されるように変換される場合、終端のnull バイトにより、同等の非文字列よりも長くなります。文字列は可変長構造であるため、null バイトが存在します文字列の終わりを示します。この知識を使用して、元の例を修正して正しいストレージ長を使用し、文字列ターミネータを正しい場所に配置することもできます。

%{
    char *func_var = "";
    char *func_initial_var = "";
    char *temp_func;
    static int q;
    #include <string.h>
%}
%s SOME_STATE_X
%%
<INITIAL>.       { char c;
                    func_initial_var = strdup(yytext);
                    c = input();
                    func_var = (char*) malloc(sizeof(char)+1);
                    for(q=0;;q++) {
                        if(c == ')')
                        {
                          func_var[q] = c;
                          func_var[q+1] = 0;
                          printf("%s\n",func_var);
                          BEGIN SOME_STATE_X;
                          break;
                        }
                    func_var[q] = c;
                    func_var[q+1] = 0;
                    printf("%s\n",func_var);
                    temp_func = (char*) realloc(func_var,(q+2)*sizeof(char)+1);
                    if(temp_func != NULL) 
                        {
                        func_var = temp_func;
                        } else {
                      free(func_var);
                      printf("Error allocating memory\n");
                      return 1;
                        }
                    c = input();
                      }
                    }

このコードが実行され、テスト ケースの例として以下が生成されます。

(c,data, istart, mid,BASE)
c
c,
c,d
c,da
c,dat
c,data
c,data,
c,data,
c,data, i
c,data, is
c,data, ist
c,data, ista
c,data, istar
c,data, istart
c,data, istart,
c,data, istart,
c,data, istart, m
c,data, istart, mi
c,data, istart, mid
c,data, istart, mid,
c,data, istart, mid,B
c,data, istart, mid,BA
c,data, istart, mid,BAS
c,data, istart, mid,BASE
c,data, istart, mid,BASE)

コードはおそらくlexツールを使用する最良の方法ではありませんが、これは lexチュートリアルではありません!

于 2015-04-21T10:32:11.167 に答える