看板 C_and_CPP 關於我們 聯絡資訊
→ akasan:why for_each not accumulate ? 08/07 11:29 → loveme00835:只能用標準庫嗎? 08/07 12:41 → loveme00835:剛剛試過boost::accumulator 似乎沒辦法疊起來用, 不 08/07 12:43 → loveme00835:過這問題可以用transform + accumulate 兜起來, 用 08/07 12:44 → loveme00835:lambda function 來轉整數 08/07 12:45 不知道是不是我誤會了原 po 想幹嘛? 為什麼不能用 std::accumulate? 我沒有 win32 平台的開發環境所以直接寫個小程式測試: #include <numeric> #include <vector> #include <iostream> using namespace std; struct WIN32_FIND_DATA { WIN32_FIND_DATA(unsigned long n) : nFileSizeLow(n) { } unsigned long nFileSizeLow; }; vector<WIN32_FIND_DATA> vcFind; unsigned long fileSizeSum(unsigned long sum, const WIN32_FIND_DATA &data) { return sum + data.nFileSizeLow; } int main() { unsigned long sum = 0UL; vcFind.push_back(WIN32_FIND_DATA(1)); vcFind.push_back(WIN32_FIND_DATA(2)); vcFind.push_back(WIN32_FIND_DATA(3)); sum = accumulate(vcFind.begin(), vcFind.end(), 0UL, fileSizeSum); cout << sum << endl; } 得到 6。 編譯器支援 lambda expression 的場合: #include <numeric> #include <vector> #include <iostream> using namespace std; struct WIN32_FIND_DATA { unsigned long nFileSizeLow; WIN32_FIND_DATA(unsigned long n) : nFileSizeLow(n) { } }; vector<WIN32_FIND_DATA> vcFind; int main() { unsigned long sum = 0UL; vcFind.push_back(WIN32_FIND_DATA(1)); vcFind.push_back(WIN32_FIND_DATA(2)); vcFind.push_back(WIN32_FIND_DATA(3)); sum = accumulate(vcFind.begin(), vcFind.end(), 0UL, [](unsigned long sum, const WIN32_FIND_DATA &data) { return sum + data.nFileSizeLow; } ); cout << sum << endl; } ※ 引述《softwind (software everywhere)》之銘言: [DELETE] : like C的寫法 : unsigned long total=0; : for(vector<WIN32_FIND_DATA>::const_iterator iter=vcFind.begin(); : iter!=vcFind.end(); iter++){ : n+=iter->nFileSizeLow; : } : 然後這邊可以得到該層目錄的 total file size. : 但是 我想要套用 for_each的方式 不過想不出來正確的表示式... : for_each(vcFind.begin(), vcFind.end(), /* 這邊該怎麼填? */ ) 如果你堅持要用 for_each, 你需要一個 function object 來儲存計算結果, 再利用 for_each 的傳回值。 #include <algorithm> #include <vector> #include <iostream> using namespace std; struct WIN32_FIND_DATA { WIN32_FIND_DATA(unsigned long n) : nFileSizeLow(n) { } unsigned long nFileSizeLow; }; vector<WIN32_FIND_DATA> vcFind; class FileSizeSum : public unary_function<const WIN32_FIND_DATA &, void> { public: FileSizeSum() : sum() { } void operator()(const WIN32_FIND_DATA &data) { sum += data.nFileSizeLow; } unsigned long result() { return sum; } private: unsigned long sum; }; int main() { unsigned long sum = 0UL; vcFind.push_back(WIN32_FIND_DATA(1)); vcFind.push_back(WIN32_FIND_DATA(2)); vcFind.push_back(WIN32_FIND_DATA(3)); sum = for_each(vcFind.begin(), vcFind.end(), FileSizeSum()).result(); cout << sum << endl; } 得到 6。 編譯器支援 lambda expression 的場合: #include <algorithm> #include <vector> #include <iostream> using namespace std; struct WIN32_FIND_DATA { WIN32_FIND_DATA(unsigned long n) : nFileSizeLow(n) { } unsigned long nFileSizeLow; }; vector<WIN32_FIND_DATA> vcFind; int main() { unsigned long sum = 0UL; vcFind.push_back(WIN32_FIND_DATA(1)); vcFind.push_back(WIN32_FIND_DATA(2)); vcFind.push_back(WIN32_FIND_DATA(3)); for_each(vcFind.begin(), vcFind.end(), [&](const WIN32_FIND_DATA &data) { sum += data.nFileSizeLow; } ); cout << sum << endl; } : 我想用 bind1st( plus<int>(), totaSize ); : 可是 WIN32_FIND_DATA 沒有辦法cast成 int... 我想這不是你要的東西。 : Ruby的話我會寫 : vcFind.each{ |find| : totalSize+=find.dwFileSizeLow; : } 你想這樣做的話應該是 for_each 版 + lambda expression 會適合你, 但是你的編譯器需要 C++0x 的支援。 至於到底你要取 dwFileSizeLow 還是 nFileSizeLow, 因為前後不一致所以我也無從猜測。 補充說明: GCC 4.5.0 以上的版本支援 lambda expression, 請在編譯的時候下 -std=gnu++0x 或 -std=c++0x。 預設是 -std=gnu++98。 開頭有 gnu 才有 GNU extensions 可以用。 編這邊的 code 倒是沒什麼差異, 但是編一些 tarball 的話 gnu -> std 可能會編不過。 MS 平台我記得要 VS2010 才有吧。 : 但是轉成 C++ template... : sorry~ 我真的是不熟 觀念上一直會卡住... : 麻煩板上高手解答 : 感謝~ -- Ling-hua Tseng (uranus@tinlans.org) Department of Computer Science, National Tsing-Hua University Interesting: C++, Compiler, PL/PD, OS, VM, Large-scale software design Researching: Software pipelining for VLIW architectures Homepage: http://www.tinlans.org -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 118.160.104.163 ※ 編輯: tinlans 來自: 118.160.104.163 (08/07 18:39)
loveme00835:我想原原po應該是不想另外再寫函式或是類別 08/07 18:57
tinlans:那就只能去抓 VS2010 來用 lambda expression。 08/07 19:03
tinlans:不然堅持用 std 的東西的話,最標準最傳統的方法也是要學 08/07 19:05
tinlans:accumulate 已經是 Effective STL 的 Item 31 明確建議的 08/07 19:07
tinlans:用法了。語意跟表達上也會比較清晰。 08/07 19:07
loveme00835:我都用 DevC++ 寫 lambda expression XD 08/07 19:37
softwind:但是就算使用acc, 還是需要另外生一個class來算 08/07 23:28
softwind:單用 functional裡面的tempalte class, 兜不出來 08/07 23:28
softwind:同時 WIN32_FIND_DATA是Windows的struct 用來和 找檔案 08/07 23:30
softwind:的API, FindFirstFile搭配使用, 不能自訂阿 08/07 23:30
softwind:所以我才說 最後我想得到的作法是 想辦法在WIN32_FIND_DA 08/07 23:31
softwind:TA中, 注入 int cast operator,然後丟給plus<int>()中 08/07 23:32
loveme00835:如果要用plus<int>(), 你用一個wraper包起來就好, 再 08/07 23:36
loveme00835:提供operator int 來轉型 08/07 23:37
loveme00835:還是搞不懂寫一個程式為啥限制要那麼多= = 08/08 00:04
softwind:為工作而寫求安全易懂 為了練功而寫就求新求進 08/08 00:09
softwind:不管怎樣 感謝上面大大回文 我只是想搞清楚 純C++ 08/08 00:10
softwind:目前的限制而已 boost 我可能工作上很難用到 嵌入式阿 08/08 00:10
loveme00835:0.0 08/08 00:21
tinlans:用了 accumulate 只要另外生一個 function,不是 class。 08/08 01:37
tinlans:不過要另外寫東西才能動,是肯定的。 08/08 01:38
tinlans:傳進 accumulate 的如果是 function object,它本身不能做 08/08 01:39
tinlans:累加動作。因為標準規定那個引數的物件不能有 side-effect 08/08 01:40
tinlans:。如果要 function object 本身做累加,只能用 for_each。 08/08 01:40
hilorrk:原來是標準規定 讀Josuttis那本時我還以為只是不該這麼做 08/08 02:11
loveme00835:還是要有規格書在手才好查原因 ( ̄▽ ̄#)﹏﹏ 08/08 02:26
hilorrk:小弟是個窮大學生 印不起XD 而且還沒玩到那麼深... 08/08 02:29