2013-04-05 162 views
1

嘿,這裏的人對你們來說都是一個有趣的挑戰。 我收到一個文本文件,我應該逐行處理信息。處理部分是微不足道的,只要我可以獲得單獨的行。然而,這是挑戰:逐行讀取文件無需使用FOR/WHILE循環

  1. 我必須這樣做,而沒有在我的代碼中使用任何FOR/WHILE循環。 (這包括遞歸)
  2. 我只允許使用標準C++庫。

目前,現在我的最好的解決辦法是這樣的: Is there a C++ iterator that can iterate over a file line by line? 但我希望是一個好機會,不涉及創建我自己的迭代器類或者實現了的std :: string的代理。

P.S.這是一所學校的分配,這裏的挑戰是使用std功能和算法的組合來解決這個問題,但我不知道如何去解決它

+0

爲什麼不能使用'for'或'while'循環? – 2013-04-05 16:56:58

+0

這是很沒意思的,如果你逐行解析你的文字循環遍歷文件 – Paranaix 2013-04-05 16:58:24

+4

像這樣愚蠢的要求,'goto'是最好的方法。 – nneonneo 2013-04-05 16:59:55

回答

6
ifstream input("somefile") 

if (!input) { /* Handle error */ } 

//MyDataType needs to implement an operator>> 

std::vector<MyDataType> res; 

std::istream_iterator<MyDataType> first(input); 
std::istream_iterator<MyDataType> last; 
std::copy(first,last, std::back_inserter(res)); 

//etc.. 

你的輸入操作員可以是這樣的:

std::istream& operator>>(std::istream &in,MyDataType & out) 
{ 
    std::string str; 
    std::getline(in,str); 
    //Do something with str without using loops 
    return in; 
} 

有很多循環在這裏(你不」想要使用goto,不是嗎?),但它們都隱藏在std::copystd::getline

+1

您是不是指'operator >>? – Angew 2013-04-05 17:06:45

+0

這實際上非常類似於我發佈的鏈接的答案,如果我找不到任何東西,我會用它作爲最後的手段 – 2013-04-05 17:12:37

+0

@Angew zzz ..對不起,我修正了它 – sbabbi 2013-04-05 17:15:20

0

這只是一個玩具。

它包含一個基於生成器的方式來吸取文件(我發現它很容易編寫),以及一個將Generators變成迭代器的半工作適配器。

在此上下文中的生成器是一個函子,它接受一個lambda,並將該lambda傳遞給該函數並返回true,或返回false。它使得一個非常短的循環:

while(gen([&](std::string line) { 
    // code using line goes here 
})); // <- notice that this is an empty while loop that does stuff 

但你不允許使用它。 (這個設計靈感來自於python生成器,對於許多類型的問題,包括從文件中讀取,我真的發現比C++迭代器更適合使用。

adpator使用此生成器並使其成爲迭代器,因此您可以將它傳遞給for_each

這個問題的關鍵在於你的問題本身就是一個愚蠢的問題,所以我並沒有做一些明顯的事情(goto,或者直接在istream迭代器上使用for_each),我提議用一些愚蠢和不同的東西來搞亂。 :)

線發生器是好的,簡稱:

struct LineGenerator { 
    LineGenerator(std::ostream& os_):os(&os_) {} 
    std::ostream* os; 
    template<typename F> 
    bool operator()(F&& func) { 
    std::string s; 
    bool bRet = std::getline(*os, s); 
    if (!bRet) return false; 
    std::forward<F>(func)(s); 
    return true; 
    } 
}; 

適配器,在另一方面,是相當混亂:(而不是測試)

template<typename Generator> 
struct generator_iterator { 
    typedef generator_iterator<Generator> my_type; 
    typedef typename std::decay< decltype(std::declval<Generator>()()) >::type value_type; 
    Generator g; 
    bool bDone; 
    value_type val; 
    generator_iterator(Generator g_):g(g_), bDone(false) { 
    next(); 
    } 
    generator_iterator(): bDone(true) {} 
private: 
    void next() { 
    if (bDone) return; 
    bDone = g(val); 
    } 
public: 
    generator_iterator& operator++() { 
    next(); 
    return *this; 
    } 
    value_type operator*() { 
    return val; 
    } 
    const value_type operator*() const { 
    return val; 
    } 
    value_type* operator->() { 
    return &val; 
    } 
    value_type const* operator->() const { 
    return &val; 
    } 
    bool operator==(my_type const& o) { 
    if (bDone != o.bDone) return false; 
    if (!bDone && !o.bDone) return true; 
    return false; 
    } 
}; 
template<typename Generator> 
generator_iterator<Generator> make_gen_it(Generator&& g) { 
    return generator_iterator<Generator>(std::forward<Generator>(g)); 
} 
template<typename Generator> 
generator_iterator<Generator> make_end_gen_it() { 
    return generator_iterator<Generator>(); 
} 

我希望這個遊樂!