如果你正在尋找專門使用operator>>
,而你沒有在技術上需要專門使用的字符串,你可以簡單地用當它從istream
讀取你想要的行爲的自定義類。它甚至可以(大部分)是一個字符串的包裝,在讀取初始空白時具有自定義行爲。
class StringAndNewline{
std::string str_;
friend std::istream& operator>>(std::istream& in, StringAndNewline& str);
public:
StringAndNewline() : str_(){}
StringAndNewline(std::string str) : str_(str){}
const std::string& str() const noexcept {return str_;}
std::string release() {return std::move(str_);}
};
在操作員讀出的字符串自動地忽略所有preceding whitespace到的非空白字符的序列,由本區域所限定的。這是你想要改變的行爲,事實證明這樣做很簡單。
初始空白的處理通常由稱爲sentry對象的東西執行,該對象還會檢查該流是否有效,並在流的末尾設置流failbit
。雖然它的默認行爲是消耗空白字符,直到遇到非空白字符,但是它的構造函數由一個標誌控制,所以我們可以使用它提供的非常好的封裝流有效性檢查。
operator>>
的字符串重載會產生並檢查一個哨兵,然後讀取,直到遇到空白,流結束或讀取失敗。我們可以簡單地確保它的哨兵通過自己處理它而不會遇到空白。
因此,對於我們的自定義類的終極讀式結構定製operator>>
會是這個樣子:
- 使非空白的飲食放哨
- 檢查崗哨,返回失敗的流,如果它是無效的
- 處理空白
- 將數據讀入包串
- 收益流
由於我們只關心我們空白中的'\ n'字符,它也很簡單:只是在流有效時循環(如果在遇到任一條件之前空間用完了,它會像我們一樣設置failbit
會想要)並退出循環,如果兩個條件之一是淨:我們得到一個換行符,或者我們得到一個非空白字符。同樣,驚喜簡單:
std::istream& operator>>(std::istream& in, StringAndNewline& str){
std::istream::sentry sentry{in, true}; // make a sentry that doesn't eat whitespace
if(!sentry){return in;} // check the sentry
std::locale
presentLocale{}; // get the present locale
char presentChar;
while(in.get(presentChar)){ // while the stream is valid
if(presentChar == '\n'){ // if we get a newline
str.str_ = "\\n"; // set the string to an escaped newline
break; // exit the loop
}
// if we get a non-whitespace character
else if(!std::isspace(presentChar, presentLocale)){
in.unget(); // replace the character in the stream
in >> str.str_; // take advantage of the existing string operator
break; // done with loop
}
}
return in; // return the istream, whatever state it might be in
}
一旦做到這一點,我們成立了一個ostream操作,便於印刷:
和測試我們的代碼:
int main(){
std::istringstream file(
"hello\n"
"world\n"
"C++ is the best tool"
);
StringAndNewline
wordOrNewline;
while(file >> wordOrNewline){
std::cout << wordOrNewline << '\n';
}
}
它打印此:
hello
\n
world
\n
C++
is
the
best
tool
就像我們想要的一樣! Live on Coliru
如果你真的想要很容易地將包裝類轉換爲字符串,你甚至可以編寫一個字符串運算符,但我會把它留給你。
這是XY問題嗎? – emlai
您的輸出與您的輸入不符。如您所示,文件中的hello和world之間有一個換行符。 – NathanOliver
'運算符>>'的字符串重載[不能區分換行符和其他空格](http://en.cppreference.com/w/cpp/string/basic_string/operator_ltltgtgt)除非有一個區域設置可以實現,但'getline'確實。在任何情況下,打印'\ n'而不是實際的換行符都必須是特例。你是否考慮過使用getline獲取每一行,將結果字符串轉換爲一個'istringstream',並在其上調用'operator >>',然後在字符串流完全解析時在它自己的行上打印'\ n'? – jaggedSpire