Re: [問題] STL for_each 算總和

看板C_and_CPP (C/C++)作者 ( )時間15年前 (2010/08/07 18:20), 編輯推噓8(8019)
留言27則, 4人參與, 最新討論串2/2 (看更多)
→ 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)

08/07 18:57, , 1F
我想原原po應該是不想另外再寫函式或是類別
08/07 18:57, 1F

08/07 19:03, , 2F
那就只能去抓 VS2010 來用 lambda expression。
08/07 19:03, 2F

08/07 19:05, , 3F
不然堅持用 std 的東西的話,最標準最傳統的方法也是要學
08/07 19:05, 3F

08/07 19:07, , 4F
accumulate 已經是 Effective STL 的 Item 31 明確建議的
08/07 19:07, 4F

08/07 19:07, , 5F
用法了。語意跟表達上也會比較清晰。
08/07 19:07, 5F

08/07 19:37, , 6F
我都用 DevC++ 寫 lambda expression XD
08/07 19:37, 6F

08/07 23:28, , 7F
但是就算使用acc, 還是需要另外生一個class來算
08/07 23:28, 7F

08/07 23:28, , 8F
單用 functional裡面的tempalte class, 兜不出來
08/07 23:28, 8F

08/07 23:30, , 9F
同時 WIN32_FIND_DATA是Windows的struct 用來和 找檔案
08/07 23:30, 9F

08/07 23:30, , 10F
的API, FindFirstFile搭配使用, 不能自訂阿
08/07 23:30, 10F

08/07 23:31, , 11F
所以我才說 最後我想得到的作法是 想辦法在WIN32_FIND_DA
08/07 23:31, 11F

08/07 23:32, , 12F
TA中, 注入 int cast operator,然後丟給plus<int>()中
08/07 23:32, 12F

08/07 23:36, , 13F
如果要用plus<int>(), 你用一個wraper包起來就好, 再
08/07 23:36, 13F

08/07 23:37, , 14F
提供operator int 來轉型
08/07 23:37, 14F

08/08 00:04, , 15F
還是搞不懂寫一個程式為啥限制要那麼多= =
08/08 00:04, 15F

08/08 00:09, , 16F
為工作而寫求安全易懂 為了練功而寫就求新求進
08/08 00:09, 16F

08/08 00:10, , 17F
不管怎樣 感謝上面大大回文 我只是想搞清楚 純C++
08/08 00:10, 17F

08/08 00:10, , 18F
目前的限制而已 boost 我可能工作上很難用到 嵌入式阿
08/08 00:10, 18F

08/08 00:21, , 19F
0.0
08/08 00:21, 19F

08/08 01:37, , 20F
用了 accumulate 只要另外生一個 function,不是 class。
08/08 01:37, 20F

08/08 01:38, , 21F
不過要另外寫東西才能動,是肯定的。
08/08 01:38, 21F

08/08 01:39, , 22F
傳進 accumulate 的如果是 function object,它本身不能做
08/08 01:39, 22F

08/08 01:40, , 23F
累加動作。因為標準規定那個引數的物件不能有 side-effect
08/08 01:40, 23F

08/08 01:40, , 24F
。如果要 function object 本身做累加,只能用 for_each。
08/08 01:40, 24F

08/08 02:11, , 25F
原來是標準規定 讀Josuttis那本時我還以為只是不該這麼做
08/08 02:11, 25F

08/08 02:26, , 26F
還是要有規格書在手才好查原因 ( ̄▽ ̄#)﹏﹏
08/08 02:26, 26F

08/08 02:29, , 27F
小弟是個窮大學生 印不起XD 而且還沒玩到那麼深...
08/08 02:29, 27F
文章代碼(AID): #1CNJDzdH (C_and_CPP)
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 2 篇):
文章代碼(AID): #1CNJDzdH (C_and_CPP)