0

特定の入力を受け取り、動的に割り当て、出力し、解放する単純なプログラムを作成しようとしています。問題は、それが正しく出力されないことです。入力のスタイルは次のとおりです。

最初の行は、私が読む必要がある行の数です - i.

それからi行があります。各行で 1 つの単語を読み、次に整数がいくつ続くかを示す整数 n を読み、次に n 個の整数が続きます。

例えば、

2
yellow 2 32 44
green 3 123 3213 3213

説明:

1 行目 - 2 行が必要です。

2 行目と 3 行目 - 単語 + 整数の数 + 整数。

私の試み:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i, j;
    int n; /* n - number of words */
    char **words; /* words - array of keywords */
    int **data;
    scanf ("%d\n", &n);

    words = (char **) malloc (n * sizeof (char *));
    data = (int **) malloc (n * sizeof (int *));

    for (i = 0; i < n; ++i)
    {
        words[i] = (char *) malloc (sizeof (char));
        for (j = 0 ;; ++j)
        {
            words[i] = (char *) realloc (words[i], sizeof (char) * (j + 2));
            scanf ("%c", &words[i][j]);

            if (words[i][j] == ' ')
                break;
            else if (words[i][j] == '\n')
                --j;

        }

        words[i][j] = '\0';
        data[i] = (int *) malloc (sizeof (int));
        scanf ("%d", &data[i][0]);

        for (j = 0; j < data[i][0]; ++j)
        {
            data[i] = (int *) realloc (data[i], sizeof (int) * (j + 2));
            scanf ("%d", &data[i][j]);
        }
    }

    for (i = 0; i < n; ++i)
    {
        printf ("%s ", words[i]);
        printf ("%d ", data[i][0]);
        for (j = 0; j < data[i][0]; ++j)
        {
            printf ("%d ", data[i][j]);
        }
        printf ("\n");
    }

    for (i = 0; i < n; ++i)
    {
        free (words[i]);
        free (data[i]);
    }
    free (words);
    free (data);
    return 0;
}
4

1 に答える 1

1

data = (int **) malloc (n * sizeof (char *));これは意味がありません...戻り値は を指してint *いますが、 の倍数で割り当てていますsizeof (char *)。これら 2 つは同じ表現である必要はありません。つまり、同じ幅である必要はありません。詳細については、このページを参照してください。PS: malloc をキャストしないでください。そこにいる間、ウェブサイトの残りの部分を読んでください。将来の一般的な問題に遭遇するのを防ぎます。それまでの間、私はあなたが意図していたと仮定しますdata = malloc(n * sizeof *data);.

n、ちなみに、おそらくsize_tではなく である必要がありintます。size_tusingを受け取るには、フォーマット指定子scanfを使用します。%zuこの例を以下に示します。


    data[i] = (int *) malloc (sizeof (int));
    scanf ("%d", &data[i][0]);
    for (j = 0; j < data[i][0]; ++j)
    {
        data[i] = (int *) realloc (data[i], sizeof (int) * (j + 2));
            scanf ("%d", &data[i][j]);
    }

このインデントが不十分なコードの例 (インデントが不十分なため、誰も読みたくない) には、問題が存在します。問題は通常、正しくフォーマットされ、不要なキャストが削除され、提示されるばかげたロジックが考慮されるまで誰も読みたがらないため、検出されません。

ループは のときに終了するはずj == data[i][0]です。ループの最初の繰り返しで、data[i][0]変更されるため、ループの条件が変更されます。したがって、このループはあなたがやりたいことをしていません。おそらく、あなたは次のようなものを書くつもりでした:

    size_t count;
    /* Note how scanf returns a value, and when that value isn't 1 an assertion error
     * is raised? An exercise for you is to get that assertion error to raise, or read
     * the manual... */
    assert(scanf("%zu", &count) == 1);

    /* Note how malloc doesn't need a cast? */
    data[i] = malloc(count * sizeof data[i][0]);
    for (j = 0; j < count; ++j)
    {
        /* Note how count never changes, in this loop? */
        assert(scanf("%d ", &data[i][j]) == 1);
    }

scanfこのトピックに取り組んでいる間に、最後の書式文字列の末尾にスペースを追加したことに気付くでしょう。そのスペースは、から可能な限り多くの空白を消費しますstdin。この理由は、おそらく前のループの壊れたコードと同じ目的で'\n'、次の項目「単語」を読み取る前に文字を読み取って破棄するためです。


    words[i] = (char *) malloc (sizeof (char));
    for (j = 0 ;; ++j)
    {
        words[i] = (char *) realloc (words[i], sizeof (char) * (j + 2));
        scanf ("%c", &words[i][j]);
        if (words[i][j] == ' ')
            break;
        else if (words[i][j] == '\n')
            --j;
    }
    words[i][j] = '\0';

'\n'ユーザーが単語を入力せずにエンターを悪意を持って押すことを除いて、先頭文字の可能性は事実上排除されました。mallocキャストが削除され、ビジョンでより賢明な割り当てアルゴリズムが提供されました。

    size_t j = 0;
    words[i] = NULL;
    for (int c = getchar(); c >= 0; c = getchar()) {
        /* Reallocate when j is a power of two, eg: 0, 1, 2, 4, 8, 16...
         * ... and double the size of the buffer each time
         */
        if (j & (j - 1) == 0) {
            char *temp = realloc(words[i], j * 2 + 1);
            /* hint: Check *all* return values */
            assert(temp != NULL);
            words[i] = temp;
        }

        if (strchr(" \n", c) == NULL) { break; }
        words[i][j] = c;
        j++;
    }

    words[i][j] = '\0';
于 2013-04-14T12:19:20.317 に答える