Re: [討論] C++ 讀取資料後如何抓取目標值?

看板C_and_CPP作者 (髮箍)時間3年前 (2020/10/07 01:43), 3年前編輯推噓6(6022)
留言28則, 3人參與, 3年前最新討論串2/2 (看更多)
※ 引述《forthcoming5 (XDDD)》之銘言: : 最近自學到ifstream等寫法 : 其中有個題目是將ifstream讀出來的檔案 : 做分類+統整,檔案是.txt : txt的內容例如: : &@$@&&@@:((;(& : sh tree f m hi tm it e iuytre : Rule fixed : 100 21 : 200 38 : 300 37 : 400 35 : 500 11 : 如果在rule跟fixed前面的文字、資料不想要 : 直接取下面的Rule跟fixed及後面的數值做處理 : 應該要怎麼做呢? : 老師是有提示用vector搭配parser等作法 : 但想很久一直沒辦法 : 跪求解答,將送上300p幣,感恩 你可以想像 i(f)stream 是由一連串的字元所組成, 要在裡面找尋特定字串可 以用 <algorithm> 裡的 std::search() 來完成, 只是它要求參數必須滿足 ForwardIteartor 概念 (concept), 亦即它預期迭代器 (iterator) 在沒有做 累加時, 多次讀出來的字元必須相同; 但 istream 物件的特性卻是: 沒有做快 取的情況下, 每個字元只能讀一次, 是 InputRange 的概念. 當我們配對到字 串的同時, 我們也丟掉它了. 即使如此, 我們還是可以仿照 std::search() 的 邏輯順勢實作接受 InputIterator 的函式 drop_until(). drop_until() 的架構是這樣的: 本體裡包含一個迴圈, 每次迭代都只對參數做 一次累加還有讀值, 並且複製讀出來的物件往後做參考: template <typename InputIterator, typename InputSentinel> void drop_until(InputIterator first, InputSentinel last) { while (first != last) { auto element = *first++; // do things here } } 接著我們再加入額外的參數 pattern 作為要查找的對象, 它是一種 ForwardR- ange, 到這裡和 std::search() 還蠻像的 (為了能在配對失敗時重來, 我們再 新增一個迭代器物件): template < typename InputIterator, typename InputSentinel, typename ForwardRange > void drop_until(InputIterator first, InputSentinel last, const ForwardRange& pattern) { // match from beginning auto next_to_match = pattern.begin(); while (first != last && next_to_match != pattern.end()) { auto element = *first++; // match succeeding element in next iteration if (element == *next_to_match) { ++next_to_match; // fail to match, start over from second element } else if (element == *pattern.begin()) { next_to_match = std::next(pattern.begin()); // fail to match, start over from first element } else { next_to_match = pattern.begin(); } } } 以上還只是簡單的實作, 雖然沒辦法處理複雜的字串, 但用來解原 po 的問題 已經足夠. 有了 drop_until() 函式, 讀檔程式碼就可以這樣寫: std::ifstream file("input.txt"); drop_until( std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), "Rule fixed\n"sv ); unsigned rule, fixed; while (file >> rule >> fixed) { // do things here } 完整範例: https://wandbox.org/permlink/gAssdOddYQtopotV 不過如果你有辦法把整個檔案都讀進來變成一個大字串, 搭配 std::search() 的話會省下不少功夫 :) -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.216.75.43 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1602006183.A.438.html

10/07 03:06, 3年前 , 1F
說實話原 Po 沒有把檔案的語法講清楚根本無法實作
10/07 03:06, 1F

10/07 03:06, 3年前 , 2F
eg. Rule fixed 出現在上面的部分?多個 Rule fixed?上
10/07 03:06, 2F

10/07 03:06, 3年前 , 3F
面的部分可以為空?...
10/07 03:06, 3F

10/07 03:06, 3年前 , 4F
先把 syntax tree 定義好再來 parse 比較實在吧
10/07 03:06, 4F

10/07 09:41, 3年前 , 5F
也沒那麼無法實作吧,他也講得很清楚上面的東西全捨棄,所
10/07 09:41, 5F

10/07 09:42, 3年前 , 6F
以根本不用考慮上面有多少東西或可能沒有東西,一行一行讀
10/07 09:42, 6F

10/07 09:42, 3年前 , 7F
到某行是Rule fixed即可
10/07 09:42, 7F
※ 編輯: loveme00835 (123.193.76.216 臺灣), 10/07/2020 14:20:05

10/07 15:32, 3年前 , 8F
要是上面可以包含 Rule fixed 你要怎麼知道哪裡屬於“上
10/07 15:32, 8F

10/07 15:32, 3年前 , 9F
面”?
10/07 15:32, 9F

10/08 12:48, 3年前 , 10F
對,你當然可以追究細節跟各種例外處理
10/08 12:48, 10F

10/08 12:48, 3年前 , 11F
但是這跟「無法實作」完全是兩回事
10/08 12:48, 11F

10/08 12:49, 3年前 , 12F
業界多得是根本不知道上線才會發生什麼莫名其妙狀況的實作
10/08 12:49, 12F

10/08 12:50, 3年前 , 13F
,沒有人會跟你說我得要把所有可能性毫無遺漏才能「實作」
10/08 12:50, 13F

10/08 12:50, 3年前 , 14F
這題目的基礎要求已經很明確了,當然可以實作
10/08 12:50, 14F

10/08 12:51, 3年前 , 15F
只是你的實作可能會有缺陷,比如說我們都不知道原題目定義
10/08 12:51, 15F

10/08 12:51, 3年前 , 16F
的完整文字,所以我們並不知道會不會有兩行Rule fixed,會
10/08 12:51, 16F

10/08 12:52, 3年前 , 17F
不會有大小寫不同的rULE FIXED,會不會根本沒有一行是
10/08 12:52, 17F

10/08 12:52, 3年前 , 18F
Rule fixed,會不會在Rule fixed的前中後有\r\n\t
10/08 12:52, 18F

10/08 12:53, 3年前 , 19F
但你還是可以先寫一個滿足已知最單純情況的實作
10/08 12:53, 19F

10/08 12:55, 3年前 , 20F
然後如果你想到以上那些特殊情況,可是題目沒講會不會發生
10/08 12:55, 20F

10/08 12:55, 3年前 , 21F
或該不該處理,那就表示我們可以無視讓它發生錯就錯,或者
10/08 12:55, 21F

10/08 12:56, 3年前 , 22F
用心點為每個情況寫個處理,終究都還是可以實作一個版本啊
10/08 12:56, 22F

10/08 12:57, 3年前 , 23F
這邊的用詞應該是「題意不夠嚴謹」而不是「無法實作」,
10/08 12:57, 23F

10/08 12:57, 3年前 , 24F
「無法實作」這詞我會擺在根本沒講清楚基本要幹嘛或真的做
10/08 12:57, 24F

10/08 12:58, 3年前 , 25F
不到的情況XD
10/08 12:58, 25F

10/08 20:35, 3年前 , 26F
傳說中的客戶進門點了一盤炒飯,酒吧陷入大火
10/08 20:35, 26F

10/08 22:46, 3年前 , 27F
你當然可以寫一些自己都不知道在做什麼的程式去搪塞,但
10/08 22:46, 27F

10/08 22:46, 3年前 , 28F
對我來說那不叫實作
10/08 22:46, 28F
文章代碼(AID): #1VVAodGu (C_and_CPP)
文章代碼(AID): #1VVAodGu (C_and_CPP)