3

私はここで少し困惑しています。主に:

int main() {
    char **symbols = (char **) malloc(3 * sizeof(char *)); // allocate 3 (char *)'s
    for (int i = 0; i < 3; i++)
        symbols[i] = (char *)malloc(3); // allocate string of length 3

}

次に、ユーザーは、スペースで区切られた 3 つの文字列記号を 1 行に入力します。

111 010 101

次に、このバッファリングされた文字列を次のように解析して文字列の配列にします。

void parseSymbols(char *line, int k, char **symbols) {
    // k == 3
    // Ignore leading spaces
    while (*line != '\0' && is_whitespace(*line))
            line++;

    char *p = strtok(line, " ");
    int cnt = 0;
    symbols[cnt++] = p;
    while (p) {
            p = strtok(NULL, " \n");
            symbols[cnt++] = p;
    }

    // Let's call this FOOBAR
    //for (int i = 0; i < k; i++)
    //        printf("%d. %s\n", i, symbols[i]);

}

メインに戻ると、3 つの文字列をシンボルで printf すると、次のようになります。

0. '111'
1. '010'
2. ' s'

しかし、parseSymbols の最後の 2 行のコメントを外すと、次のようになります。

0. '111'
1. '010'
2. '101'

FOOBAR ブロックが文字列配列を「修正」するのはなぜですか? さらに重要なことに、何かを画面に出力することなく、parseSymbols を適切に機能させるにはどうすればよいですか? シンボル[2] は '\0' で終了する必要がありますか? (しかし、strtok は私のためにそれをしませんか?)

4

1 に答える 1

1

最初の問題は、結果のポインターをstrtokシンボル テーブルに割り当てることによってメモリ リークが発生しているという事実です。これは、これらの行で結果の文字列をコピーするのではなく、トークンの次の開始への参照をコピーしているだけだからです。symbols[cnt++] = p;

次に、結果をシンボル テーブルに割り当てて、k を超えていないことを確認する必要があります。コードは常に、シンボル テーブルの最後の位置に NULL を書き込みます。3 つのシンボルを解析するとすぐに、未割り当てのメモリに書き込み、未定義の動作を引き起こします。

最初にこれらのことを修正してから、もう一度やり直すことをお勧めします。

strtok は、トークンの末尾にある区切り文字を '\0' に置き換えることで元のバッファーを変更するため、文字列をコピーする必要がないことに注意してください。strtok は区切り文字の 1 つの連続した発生をスキップすることにも注意してください。したがって、最初のループは、最初のトークンの長さが >0 の場合 (つまり、結果の文字列の最初のバイトが!= '\0'

C-String は常に、保存したいスペースよりも 1 バイト多いスペースが必要であることに注意してください。この余分なバイトは、'\0' 終了に使用されます。あなたの例では、チャンクごとに 3 バイトのみを割り当てながら、3 バイトのチャンクを解析しています (4 のはずです):symbols[i] = (char *)malloc(3); // allocate string of length 3

于 2013-01-27T08:20:20.923 に答える