0

私は単純なシェルのようなインターフェイスを作成しようとしています。これは、ユーザー入力を (char で) 受け取り、ポインター * へのポインターを介して格納します (argv の動作とまったく同じです)。これが私のコードです:

char input[100];
char **argvInput;
char ch;
int charLoop = 0;
int wordCount = 0;

argvInput = malloc(25 * sizeof(char *));

while((ch = getc(stdin))) {
    if ((ch == ' ' || ch == '\n') && charLoop != 0) {
        input[charLoop] = '\0';
        argvInput[wordCount] = malloc((charLoop + 1) * sizeof(char));
        argvInput[wordCount] = input;
        charLoop = 0;
        wordCount++;

        if (ch == '\n') {
            break;
        }

    } else if (ch != ' ' && ch != '\n') {
          input[charLoop] = ch;
          charLoop++;
        } else {
            break;
        }
    }

argvInput をループすると、次のようになります。

int i = 0;
for (i = 0; i < wordCount; i++)
    printf("Word %i: %s\n", i, argvInput[i]);

argvInput[i] のすべての値は、最後の入力割り当てが何であれです。したがって、「幸せな日々がもうすぐ来る」と入力すると、ループの出力は次のようになります。

Word 0: soon
Word 1: soon
Word 2: soon
Word 3: soon
Word 4: soon

私は途方に暮れています。明らかに、各ループは以前の値を上書きしていますが、私は画面を見つめていて、理由がわかりません...

4

3 に答える 3

4

この行はあなたの悩みの種です:

    argvInput[wordCount] = input;

ポインタを別のもの (つまり ) に置き換える場合は、新しい領域を割り当てても問題ありませんinput

むしろ、strncpyの一部を に抽出するために使用しinputますargvInput[wordCount]

于 2013-02-22T01:45:36.887 に答える
2

argvInput[wordCount] = input;入力の内容を新しく割り当てられたメモリにコピーするのargvInput[wordCount]ではなく、メモリを指すポインタを作成するだけです。inputプログラムを修正するには、memcpy または strcpy を使用する必要があります。

ポインタの割り当て後、メモリの状態は下の画像のようになります。によって割り当てられたメモリ (malloc((charLoop + 1) * sizeof(char));グラフの灰色の部分) は、プログラムからアクセスできなくなり、メモリ リークの問題が発生します。よろしくお願いします。

ここに画像の説明を入力

于 2013-02-22T02:01:28.497 に答える
0

この問題を特定するために、argvInput ポインターを %s ではなく %p で出力することをお勧めします。printf("Word %i: %p\n", i, (void *) argvInput[i]);

それが出力する値について何に気づきますか? これは argv の動作とどう違うのですか? argv のポインタを出力してみてください:for (size_t x = 0; x < argc; x++) { printf("Word %zu: %p\n", x, (void *) argv[x]); }

問題を観察したので、説明が簡単になるかもしれません。

このコードはメモリを割り当て、そのメモリへのポインタを argvInput[wordCount] に格納しますargvInput[wordCount] = malloc((charLoop + 1) * sizeof(char));(ちなみに、C では sizeof char は常に1 であるため、不必要に 1 を掛けています)。

このコードは、割り当てられたメモリへのポインタを入力へのポインタに置き換えます: argvInput[wordCount] = input;... したがって、すべてのアイテムには同じ配列へのポインタが含まれます: 入力、および割り当てられたメモリへの参照が失われるため、メモリリークが発生します。明らかに、これは問題のある行です。それはあなたが最初に思っていたことをしません。

malloc 呼び出しを strdup 呼び出しに置き換え、問題のある行を削除することをお勧めします。strdup は C 標準になく、存在する必要がないため、この提案は好きではありません。

strncpy は機能しますが、不必要に複雑です。宛先配列は文字列を格納するのに十分な大きさに割り当てられるため、strcpy も同様に機能することが保証されています。したがって、問題のある行を に置き換えることをお勧めしstrcpy(argvInput[wordCount], input);ます。

詳細に説明されていない別のオプションは strtok です。コードの変更が多すぎるため、これは今のところ未調査のままにしておくのが最善のようです。

私はこのコードで選択する骨を持っています:char ch; ch = getc(stdin);間違っています. getc は、理由により int を返します。成功した文字読み取りは、unsigned char 値の形式で返されます。これは、負になることはありません。getc が EOF またはエラーに遭遇した場合、負の値を返します。戻り値を ch に割り当てたら、エラーと成功をどのように区別しますか?

最初の文字が ' ' の場合に何が起こるか考えたことはありますか? 現在、コードはループから抜け出します。コードが一般的な argv 解析動作を模倣する場合、これはバグのようです。問題を解決するためにこのコードを適応させることは良い考えかもしれません:

for (int c = getc(stdin); c >= 0; c = getc(stdin)) {
    if (c == '\n') {
        /* Terminate your argv array and break out of the loop */
    }
    else if (c != ' ') {
        /* Copy c into input */
    }
    else if (charLoop != 0) {
        /* Allocate argvInput[wordCount] and copy input into it,
         * reset charLoop and increment wordCount */
    }
}
于 2013-02-22T04:41:27.413 に答える