是否可以忽略在cin上使用std操縱器的punctuacion?例如,假設你有一個輸入流(實際上是一個文件),如:「一,二三」。我希望能夠做到:使用操縱器忽略標點符號
f >> ignore_punct >> a;
f >> ignore_punct >> b;
f >> ignore_punct >> c;
末a=="one"
,b=="two"
,c=="three"
。
是否可以忽略在cin上使用std操縱器的punctuacion?例如,假設你有一個輸入流(實際上是一個文件),如:「一,二三」。我希望能夠做到:使用操縱器忽略標點符號
f >> ignore_punct >> a;
f >> ignore_punct >> b;
f >> ignore_punct >> c;
末a=="one"
,b=="two"
,c=="three"
。
試試這個:
它使用本地過濾掉標點符號。
這使得其餘的代碼保持不變。
#include <locale>
#include <string>
#include <iostream>
#include <fstream>
#include <cctype>
class PunctRemove: public std::codecvt<char,char,std::char_traits<char>::state_type>
{
bool do_always_noconv() const throw() { return false;}
int do_encoding() const throw() { return true; }
typedef std::codecvt<char,char,std::char_traits<char>::state_type> MyType;
typedef MyType::state_type state_type;
typedef MyType::result result;
virtual result do_in(state_type& s,
const char* from,const char* from_end,const char*& from_next,
char* to, char* to_limit, char*& to_next ) const
{
/*
* This function is used to filter the input
*/
for(from_next = from, to_next = to;from_next != from_end;++from_next)
{
if (!std::ispunct(*from_next))
{
*to_next = *from_from;
++to_next;
}
}
return ok;
}
/*
* This function is used to filter the output
*/
virtual result do_out(state_type& state,
const char* from, const char* from_end, const char*& from_next,
char* to, char* to_limit, char*& to_next ) const
{ /* I think you can guess this */ }
};
int main()
{
// stream must be imbued before they are opened.
// Otherwise the imbing is ignored.
//
std::ifstream data;
data.imbue(std::locale(std::locale(), new PunctRemove));
data.open("plop");
if (!data)
{
std::cout << "Failed to open plop\n";
return 1;
}
std::string line;
std::getline(data, line);
std::cout << "L(" << line << ")\n";
}
有沒有標準庫的方式來做到這一點,但如果我理解正確,這很容易做到。如果你想讀一個字符串直到一些標點符號,就好像是一個換行符,那麼你可以使用一個版本的getline
接受一個謂語,而不是單一的分隔符:
template<class F>
std::istream& getline(std::istream& stream, std::string& string, F delim) {
string.clear();
// Get characters while the stream is valid and the next character is not the terminating delimiter.
while (stream && !delim(stream.peek()))
string += stream.get();
// Discard delimiter.
stream.ignore(1);
return stream;
};
用例:
#include <iostream>
#include <cctype>
int main(int argc, char** argv) {
std::string s;
getline(std::cin, s, ::ispunct);
std::cout << s << '\n';
return 0;
}
如果你也想在新行上破,那麼你可以寫一個函子:
struct punct_or_newline {
bool operator()(char c) const { return ::ispunct(c) || c == '\n'; }
};
,並調用爲0123改爲。希望這可以幫助!
我認爲有一個標準的方法來做到這一點。您可以使用語言環境上的codecvt構面在標點符號進入主應用程序之前對其進行過濾。 – 2010-10-13 23:26:59
這是一個公平的評估,但可能矯枉過正。 OP詢問(我認爲)基於或類似於'iomanip'的解決方案。 – 2010-10-14 00:01:25
你能舉一個具體的例子嗎? – GManNickG 2010-10-13 22:33:09