2010-10-13 68 views
0

是否可以忽略在cin上使用std操縱器的punctuacion?例如,假設你有一個輸入流(實際上是一個文件),如:「一,二三」。我希望能夠做到:使用操縱器忽略標點符號

f >> ignore_punct >> a; 
f >> ignore_punct >> b; 
f >> ignore_punct >> c; 

a=="one"b=="two"c=="three"

+0

你能舉一個具體的例子嗎? – GManNickG 2010-10-13 22:33:09

回答

1

試試這個:

它使用本地過濾掉標點符號。
這使得其餘的代碼保持不變。

#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"; 
} 
1

有沒有標準庫的方式來做到這一點,但如果我理解正確,這很容易做到。如果你想讀一個字符串直到一些標點符號,就好像是一個換行符,那麼你可以使用一個版本的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改爲。希望這可以幫助!

+1

我認爲有一個標準的方法來做到這一點。您可以使用語言環境上的codecvt構面在標點符號進入主應用程序之前對其進行過濾。 – 2010-10-13 23:26:59

+1

這是一個公平的評估,但可能矯枉過正。 OP詢問(我認爲)基於或類似於'iomanip'的解決方案。 – 2010-10-14 00:01:25