1

我正在做一个硬件作业,我的教授使用这段代码来测试我们的程序:

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;
}

按照他的指示从终端窗口获取输入,并使用 ctrl + d 输入 EOF 字符,以便第一次调用 DisplayValues(SortValues(GetValues(array1, SZ1), SZ1), SZ1) 发生。但是,当 DisplayValues(SortValues(GetValues(array2, SZ2), SZ2), SZ2); 叫做。这有什么原因或解决方法吗?谢谢。

4

2 回答 2

4

字符(CTRLD十六进制 04)本身不是文件结尾字符。按下该键序列将向终端驱动程序发出信号,表明这是输入流的结束,并且从该流中进一步读取将被视为“文件”已完成。事实上,您可以stty在 UNIX 下使用命令更改用于此的字符。

当您按下该序列时会发生什么,不会再向程序提供进一步的输入。您需要找到更智能的序列来分隔数据(例如,换行符 (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;
}

一旦达到极限,它将停止获取值。请记住,这并不完美。我至少留下了一个问题,因为它是家庭作业(您可能永远不会遇到它,具体取决于您的输入数据)。

我还应该提到混合 C++ 和 CI/O 语义(coutscanf)有点不寻常——你真的应该选择其中一个。如果这是一个 C++ 赋值,您会发现 C++ 具有更丰富的 I/O 方式。如果它是 C,则cout在代码中没有位置,您可能应该使用printf. 我并不是说它不起作用,只是说它是一种不寻常的组合。

于 2010-02-21T07:44:34.093 回答
0

问题在于使用 EOF 作为分隔符。scanf将在 EOF 中读取,然后才能获取它想要的下一个浮点数。scanf将返回 EOF 告诉你它找到了什么,但 EOF 不会离开缓冲区,所以下次你调用 时scanf,它仍然会读取 EOF 并立即返回。参见:scanf

在您的 GetValues 函数中,由于您有数组的大小,您应该只读取数字,直到您有那么多浮点数,而不是等待 EOF。这样可以防止溢出以及不正确地使用 EOF。

于 2010-02-21T06:54:51.510 回答