1


0

XCodeのEOF文字(ctrl + d)

私はハードウェアの割り当てを行っており、教授はこのコードを使用してプログラムをテストしています。

int main()
{
   const int SZ1 = 10;
   const int SZ2 = 7;
   const int SZ3 = 5;
   float array1[SZ1];
   float array2[SZ2];
   float array3[SZ3];

   DisplayValues(SortValues(GetValues(array1, SZ1), SZ1), SZ1);
   DisplayValues(SortValues(GetValues(array2, SZ2), SZ2), SZ2);
   DisplayValues(SortValues(GetValues(array3, SZ3), SZ3), SZ3);

   return EXIT_SUCCESS;
}

float *DisplayValues(float *p, size_t n)
{
   float previous = *p, *ptr, *end = p + n;

   setiosflags(ios_base::fixed);
   for (ptr = p; ptr < end; ++ptr)  // get each element
   {
      cout << *ptr << '\n';
      if (ptr != p)                 // if not first element...
      {
         if (previous < *ptr)       // ...check sort order
         {
            cerr << "Error - Array sorted incorrectly\n";
            return NULL;
         }
      }
      previous = *ptr;              // save this element
   }
   resetiosflags(ios_base::fixed);

   return p;
}
#endif

私が使う

float *GetValues(float *p, size_t n)
{
    float input;
    float *start = p;

    cout << "Enter " << n << " float values separated by whitespace: \n";

    while (scanf("%f", &input) == 1) {
        *p++ = input;
    }
    return start;
}

彼が指示したとおりにターミナルウィンドウから入力を取得し、DisplayValues(SortValues(GetValues(array1、SZ1)、SZ1)、SZ1)への最初の呼び出しが発生するように、ctrl + dを使用してEOF文字を入力します。 ただし、プログラムの残りの部分は、DisplayValues(SortValues(GetValues(array2、SZ2)、SZ2)、SZ2);と呼ばれます。 これには理由や回避策がありますか? ありがとう。

2 Answer


4


[.kbd] CTRL [。kbd] D 文字(16進数04)は、それ自体がファイルの終わりの文字ではありません。 そのキーシーケンスを押すと、これが入力ストリームの終わりであることをターミナルドライバに通知し、そのストリームからの以降の読み取りは、「ファイル」が終了したかのように扱われます。 実際、UNIXの `stty`コマンドでこれに使用される文字を変更できます。

そのシーケンスを押すと、プログラムにそれ以上の入力が与えられなくなります。 データを区切るために、よりインテリジェントなシーケンスを見つける必要があります(たとえば、改行(0x10)など)。

しかし、これはフロートではなく文字列を入力する必要があります(空の行をチェックした後、文字列を取得するには fgets`を、フロートを抽出するには sscanf`を使用できます)。

別の可能性は、-1を特別なセンチネル値として使用することです(-1が有効な入力ではないと仮定します)が、浮動小数点の比較に注意してください。

私の提案は、 fgets / sscanf`ルートに行くことですが、 n`フロートを取得する必要があるため、 `GetValues`は次のようになります。

float *GetValues (float *p, size_t n) {
    float input;
    float *start = p;
    cout << "Enter " << n << " float values separated by whitespace: \n";
    while (scanf("%f", &input) == 1) {
        *p++ = input;
        if (--n >= 0)
            break;
    }
    return start;
}

制限に達すると値の取得が停止します。 完璧ではないことに注意してください。 宿題であるという事実のために、少なくとも1つの問題を残しました(入力データによっては、決して攻撃しないでください)。

また、C とC I / Oのセマンティクス( `cout`と` scanf`)を混在させることはやや珍しいことにも言及する必要があります。実際にどちらかを選択する必要があります。 これがC の割り当てである場合、C ++にはより豊富なI / Oの方法があることがわかります。 Cの場合、 cout`にはコード内に場所がないため、おそらく printf`を使用する必要があります。 私はそれが_work_しないと言っているのではなく、ただそれが異常なミックスだというだけです。


0


問題は、区切り文字としてEOFを使用することです。 scanf`は、次の必要なfloatを取得する前にEOFを読み込みます。 `scanf`はEOFを返し、見つかった内容を通知しますが、EOFはバッファーを離れないため、次回に scanf`を呼び出すと、EOFを読み取ってすぐに戻ります。 参照:http://www.cplusplus.com/reference/clibrary/cstdio/scanf/[scanf]

GetValues関数では、配列のサイズがあるため、EOFを待つのではなく、その数の浮動小数点数が得られるまで数値を読み込む必要があります。 そうすることで、オーバーフローを防ぎ、EOFの不適切な使用を防ぐことができます。