0
struct dict {
    int len;
    char (*dict0)[MAX_WORD_LEN+1];
    char (*dict1)[MAX_WORD_LEN+1];
};

/* the memory allocation */
void createDict(struct dict* myDict)
{
    (*myDict).dict0 = malloc((*myDict).len*sizeof(char));
    (*myDict).dict1 = malloc((*myDict).len*sizeof(char));
    if(((*myDict).dict0==0)||((*myDict).dict1==0))
        exit(1);
}

for(int i = 0; i < words; i++)
{
   scanf("%s", p_diction->dict0[i]);
   scanf("%s", p_diction->dict1[i]);
}

for(int i=0; i<words; i++)
{
   printf("%s ", &p_diction->dict0[i]);
   printf("%s\n", &p_diction->dict1[i]);

}

p_diction型へのポインタdictです。

11に設定wordsし、次のように入力します。

one lo
two ba
three li
day night
work eat
great terrible
terrible disaster
A a
start delay
finish never
I you

しかしprintf、文字列を確認すると、次のように出力されます。

one ree
two y
three rk
day eat
work rrible
great terrible
terrible art
A nish
start delay
finish never
I you

scanf1 つ目は完全に読み取り、2 つ目は後で来る単語からランダムなものを読み取るだけの理由について何か考えはありますか?

4

2 に答える 2

0

1次元配列を使用して複数の文字列(単語)を保持しているように見えます。これは、各文字列(単語)を単語の終わりを示す一意の文字で終了する場合に可能です。しかし、バニラ関数scanf()とprintf()を使用してそれを行うことはできず、独自に作成する必要があります。たとえば、各単語を@で終了するとします。次のループは、すべての単語を画面に出力します。

int i = 0;
while((*myDict).dict0[i] != '\0')//While index dose not point to end of array
{
  for(; (*myDict).dict0[i] != '@'; i++)//Print one word a single character at a time
  {
    printf("%c", (*myDict).dict0[i]);
  }
  printf("\n"); i++;//Print a newline after the word and then increase the index by one
                    //so that it does not point to '@'.
}

ただし、dict0配列とdict1配列を、各要素が1つの単語を指すポインターであるポインターの配列にすることもできます。

于 2013-01-13T21:40:01.300 に答える
0

あなたは i を再宣言していますが、(printfループのために)する必要はありません。2 番目のループでは、i は既に存在するためi=0、変数を「再初期化」するのに十分です。

読み取りループについては、scanfエンター/リターンで単語を区切ると「安全」です。それらをスペースで区切っている場合、scanf は適切なオプションではありません。2 番目の scanf はそのエンター/リターンを探しています。標準入力で指定しないと失敗し、エンター/リターン (\n) が見つかるまでおそらくガベージを格納します。

もう1つ、どのように宣言していpdictionますか?もしあなたがそうするなら:

struct dict *pdiction = malloc(sizeof(struct dict));

その「内部」変数にアクセスするには、次のようにします。

pdiction->len = 10; /*Setting len to 10*/

しかし、次のように、読み取り/書き込みループと同じ関数内で宣言すると、次のようになります。

struct dict pdiction;

この方法で「内部」変数にアクセスします。

pdiction.len = 10;

2 番目の方法は、C 構造体に通常アクセスする方法です。いわゆるドット表記。最初の方法は、C の進化のようなものです。構造体へのポインターに「フィールド内でポイントされる」を使用するのが非常に一般的であったため、C はそれを行うためのより優れた、より簡単な、より読みやすい方法である矢印表記を提供します。最初のケースで書いたことは、次とまったく同じです。

(*pdiction).len = 10; /*The (structure) pointed by pdiction in the field len*/

そのため、注意してください。

最後に、意図的にそれを行ったと思いますが、メモリアドレスの「セレクタ」アンパサンドを使用しているため、printfはおそらく実際の文字列ではなくメモリアドレスを印刷しています。

[編集] - あなたの編集を見た後、間違いの可能性が 1 つあります。構造体で静的な値を持つ文字列を宣言した場合:

char (*dict0)[MAX_WORD_LEN+1];
char (*dict1)[MAX_WORD_LEN+1];

それらのためにスペースを「再割り当て」する必要はありません。必要なのは、文字列のベクトルまたは辞書のベクトルを持つことです。アクセスpdiction->dict[i]は char のみです。代わりにベクトルが必要な場合は、割り当てを変更する必要があります。

dicts(structs) のベクトルを使用する代わりに、構造体でポインターのみを宣言し、後でベクトル割り当てを行うことでそれを行います。

これを行うには、構造体を次のように変更します。

struct dict {
    int len;
    char **dict0;
    char **dict1;
};

次に、関数にベクトルを割り当てる必要があります。

pdiciton->dict0 = malloc(NUMBER_OF WORDS * sizeof (char*));
for(i=0;i<NUMBER_OF_WORDS;i++)
   pdiction->dict0[i] = malloc(MAXIMUM_SIZE_OF_A_WORD*sizeof(char));

dict1 についても同様です。これは奇妙に思えるかもしれませんが、考えてみれば実際には論理です。文字列が文字のベクトルである場合、文字列のベクトルは文字の行列です。

ただし、scanf の問題は同じようです。Enter/Return で使用しても安全ですが、スペースでは使用できません。スペースの代わりにエンター/リターンを使用してすべてのデータを挿入し、それが機能するかどうかを確認してください。

お役に立てれば。

于 2013-01-13T21:15:15.800 に答える