2010-02-21 63 views
1

我正在做一个硬件分配和我的教授使用此代码来测试我们的程序: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; 
} 

从中获取输入按照他的指示终端窗口,然后使用ctrl + d输入一个EOF字符,以便第一次调用DisplayValues(SortValues(GetValues(array1,SZ1),SZ1),SZ1)。但是,当DisplayValues(SortValues(GetValues(array2,SZ2),SZ2),SZ2)时,程序的其余部分刚刚结束而不让我输入值。叫做。是否有这样的理由或解决方法?谢谢。

+0

注意您的GetValues在读取值(在您的scanf循环中)时根本不使用* n *。 – 2010-02-21 07:31:03

回答

0

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

在您的GetValues函数中,由于您拥有数组的大小,因此您应该只读数字,直到拥有多个浮点数为止,而不是等待EOF。这样你防止溢出以及不当使用EOF。

4

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

按下该顺序后会发生什么情况,将不会再给该程序提供任何输入。你需要找到一个更智能的序列来分隔你的数据(比如换行符(0x10))。

但是,这将要求您输入字符串,而不是花车(你可以用fgets得到一个字符串和sscanf给你检查一个空行后提取浮动)。

另一种可能性是使用-1作为特殊的sentinel值(假设-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++和C I/O语义(coutscanf) - 你真的应该选择其中之一。如果这是一个C++任务,你会发现C++有更丰富的I/O方式。如果是C,那么cout在代码中没有地位,你应该使用printf。我不是说它不会工作,只是它是一个不寻常的组合。