2012-01-07 94 views
2

這裏是一個簡單的問題。我寫這個C++代碼:在C++中使用cin和Width()來避免緩衝區溢出

char chaine[12]; 
    cin.width(12); 
    cin >> chaine; 

但如果我輸入一些文字longuer不是在運行12個字符,視覺工作室告訴我,堆棧現在損壞。

我知道問題是緩衝區溢出。但我認爲「寬度」方法可以防止這種情況發生。

有人可以向我解釋如果寬度方法不能防止緩衝區溢出,寬度方法的功能是什麼?我在網上搜索,但我沒有找到任何東西。

謝謝!

+1

是否有更多的代碼?這對我來說看起來沒問題。我看到的唯一問題是'chaine'不會被零終止,這可能會在稍後導致問題。 – 2012-01-07 01:46:04

+2

你知道還有更好的方法嗎? 'std :: string chaine; std :: cin >> chaine;'。無需擔心緩衝區溢出。 – cHao 2012-01-07 01:47:16

+0

這是整個代碼: int main() { \t char chaine [12]; \t cin.width(12); \t cin >> chaine; return 0; } – Phil 2012-01-07 01:47:49

回答

3

此代碼確實顯然應該將輸入限制爲11個字符(第12個字符用於終止空字符)。該標準在27.7.2.2.3 [istream :: extractors]第7和8段中明確指出:

...如果width()大於零,則n是寬度()。 ...提取並存儲字符,直到發生以下任何情況: - 存儲n-1個字符; ...

我也試過用gcc,它顯然只讀了11個字符。我不知道這個問題最好的解決辦法是什麼。通常情況下,我不會遇到這樣的問題,因爲我簡單地閱讀std::string對象,它們可以隨意增長。那麼,還有一些巨大的限制,我從來沒有嘗試過會發生什麼,當這將超過。如果您絕對需要讀入一個char數組,你可以做兩件事情:

  1. 您可以char陣列創建一個適配器,並確定合適的輸入操作自己
  2. 你可以創建一個過濾流緩衝區,是臨時安裝的,它限制了字符的數量或假裝讀取空格字符。

下面是一個關於如何做後者的例子。創建適配器的技術實際上可以用於根據陣列的大小自動設置寬度。

#include <iostream> 
#include <cctype> 

struct adaptor 
{ 
    template <int Size> 
    adaptor(char (&array)[Size]): it(array), end(array + Size - 1) {} 
    mutable char* it, * end; 
}; 

std::istream& operator>> (std::istream& in, adaptor const& value) 
{ 
    std::istreambuf_iterator<char> it(in), end; 
    if (it == end) 
    { 
     in.setstate(std::ios_base::failbit); 
    } 
    for (; it != end && value.it != value.end && !std::isspace(static_cast<unsigned char>(*it)); 
     ++it, ++value.it) 
    { 
     *value.it = *it; 
    } 
    *value.it = 0; 
    return in; 
} 

int main() 
{ 
    char buffer[12]; 
    if (std::cin >> adaptor(buffer)) 
     std::cout << "read='" << buffer << "'\n"; 
    else 
     std::cout << "input failed\n"; 
}