2010-02-21 65 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。我不是說它不會工作,只是它是一個不尋常的組合。