0

人の名前を含むファイルから行を読み取っています。最初の行には男性の名前が含まれ、2 番目の行には女性の名前が含まれています。次に、これらの名前を男性用と女性用の 2 つの配列に保存したいのですが、それらを印刷すると奇妙な結果が得られます。正しく読んでいないのか、間違って印刷しているのかわかりません

    char line[100];      //holds line read
    char *item;         //item in a line
    char *item2;
    int participants = 5;   //number of people in the event

            char* maleNames[participants];
            char* femaleNames[participants];

            fgets(line, 255, file);
            int i;
            item = strtok(line, " ");
            for(i=0; i<participants; i++)
            {
                maleNames[i] = item;  
                item = strtok(NULL, " ");


               }

        //read female names now
        fgets(line, 1024, file);
        item2 = strtok(line, " ");
        for(i=0; i<participants; i++)
        {
            femaleNames[i] = item2;
            item2 = strtok(NULL, " ");
        }

これらの行が読み取られます

John Jeffrey Adam Mark Peter
Jenny Alice Sally Wendy Amanda

ただし、次のように印刷すると:

        for(i=0;i<participants;i++)
        {
            printf("%s %s\n", maleNames[i], femaleNames[i]);
        }

私はとても違うものを手に入れます:

Jenny Jenny
 Alice
ally Sally
Wendy Wendy
 Amanda

注:女性の名前を読む前に男性の名前を読んだ直後に印刷すると、正しく印刷されます

4

3 に答える 3

2

最初に(そして無関係):あなたは ; であると宣言lineしますchar[100]。ただし、 and を使用していますfgets(line, 1024, file)-fgets(line, 255, file)これらは発生するのを待っているバッファオーバーランです。

次に、トークンを読み取ったときに何が起こるかを決定します。たとえば、次のようにします。

for(i=0; i<participants; i++)
{
    maleNames[i] = item;
    printf("Token %d: %s", i, item);
    item = strtok(NULL, " ");
}

これにより、入力または出力に問題があるかどうかがわかります。または、デバッガーを使用してループをステップ実行し、そこで何が起こっているかを正確に確認します。

strtokさらに、戻り値を別の文字配列にコピーする必要があると思います。strdup文字列をコピーするには調べてください。

于 2010-09-26T17:37:33.143 に答える
1

@lacqui が既に述べたように、バッファ オーバーランの可能性がありました。ハードコードされた値の代わりに sizeof(line1)-1 を渡すように fgets を変更しました。そうすれば、後でバッファーサイズを増減することにした場合でも、コンパイラーはどのサイズを渡すかを判断します。マイナス 1 は、fgets が最後にヌル ターミネータを上書きしないようにするためです。また、memset を使用してバッファーを初期化します。

strtok は、指定された区切り文字を null に置き換え、その文字列内のトークン位置へのポインターを返すことによって文字列を変更するため、別のライン バッファーも追加しました... strtok はコピーを作成しません。

区切り文字を変更して、スペースに加えて \r と \n を含めました。

#include <stdio.h>
#include <string.h>

int main() {
   char line1[100];      //holds line read
   char line2[100];
   char *item;         //item in a line
   char *item2;
   const int participants = 5;   //number of people in the event

   char* maleNames[participants];
   char* femaleNames[participants];

   FILE* file = fopen("names.txt", "r");

   memset(line1, 0, sizeof(line1));
   fgets(line1, sizeof(line1)-1, file);

   int i;
   item = strtok(line1, " \r\n");
   for(i=0; i<participants; i++)
   {
      maleNames[i] = item;  
      item = strtok(NULL, " \r\n");
   }

   //read female names now
   memset(line2, 0, sizeof(line2));
   fgets(line2, sizeof(line2)-1, file);

   item2 = strtok(line2, " \r\n");
   for(i=0; i<participants; i++)
   {
      femaleNames[i] = item2;
      item2 = strtok(NULL, " \r\n");
   }

   for(i=0;i<participants;i++)
   {
      printf("%s %s\n", maleNames[i], femaleNames[i]);
   }

   return 1;
}
于 2010-09-26T18:01:10.850 に答える
1

他の問題 (バッファーの長さが 100 文字しかない場合に fgets に渡すサイズ 255 や 1024 など) に注意を払わないでください。この問題は、同じバッファーを使用しているという事実に起因する可能性があります。char 行 [100] 、fgets() への両方の呼び出しに対して。Strtokは行バッファー内の文字へのポインターを返すため、女性の名前を「行」に格納すると、行に男性の名前が含まれていた場合の行に対するこれらのポインターはすべて無効になります。女性の行を他のバッファに保存してみてください。うまくいくはずです。

編集:「注意を払っていない...」が落胆に聞こえる場合は申し訳ありません。私の意図からかけ離れたものは何もありません。特に学習中は、誰もが常に間違いを犯します。プロセスの幸運を祈ります:)

于 2010-09-26T17:36:54.253 に答える