📜 [專欄新文章] Tornado Cash 實例解析
✍️ Johnson
📥 歡迎投稿: https://medium.com/taipei-ethereum-meetup #徵技術分享文 #使用心得 #教學文 #medium
Tornado Cash 是一個使用 zk-SNARKs 建立的 Dapp,它實現了匿名的代幣交易,這篇文章就用一些程式碼片段,來分享它是怎麼運作的。
本文為 Tornado Cash 研究系列的 Part 3,本系列以 tornado-core 為教材,學習開發 ZKP 的應用,另兩篇為:
Part 1:Merkle Tree in JavaScript
Part 2:ZKP 與智能合約的開發入門
Special thanks to C.C. Liang for review and enlightenment.
我們知道在以太坊上的交易紀錄都是公開的,你可以在 etherscan 上看到某個地址的所有歷史交易紀錄,當然地址是合約的話也是一樣。
也許創建一個新的錢包和地址就好了?假設一個情境是 Alice 想要匿名傳送 1 ETH 給 Bob,Alice 原本的錢包是 A,但她不想讓 A 地址傳給 Bob 的交易紀錄被看到,所以 Alice 創建另一個錢包 B,顯然 B 錢包是空的,Alice 必須把 A 錢包的 1 ETH 傳到 B 錢包,再用 B 錢包的地址傳給 Bob。
但問題就在於,只要追蹤 B 錢包的地址,就能看到 B 的歷史交易紀錄中 A 錢包曾經打幣給 B 錢包,於是到頭來交易還是被追蹤到了。
Tornado Cash 的解決方案,簡單來說,它是一份合約,當你要匿名傳送代幣時,就把一定數量的幣丟進合約裡 (Deposit),此時你會拿到一個 note,長得像這樣:
tornado-eth-0.1-5-0x3863c2e16abc85d72b64d78c68fca5936db2501832e26345226efdfb2bc45804977f167d86b711bb6b4095ddaa646ec93f0a93ac4884a66c1d881f4fc985
note 就是一串字串,擁有這字串的人,就能提領 (Withdraw) 剛剛傳入合約的代幣。握有 note 就代表擁有提款的權利,所以 note 一旦被別人知道,別人就可以把錢給提走。
其中,後面那段亂碼,本篇文章就以「秘密」來稱呼,這個秘密是由 secret 與 nullifier 組成,而這兩個都是在鏈下隨機產生的亂數。
因此 Tornado 的合約基本上會有兩個函式:
Deposit
Withdraw
有興趣的人可以先到 Dapp 上先玩一次看看,使用 Goerli 測試網,這裡可以領 Goerli 的代幣:https://goerli-faucet.slock.it/
Deposit
我們就從 Deposit 開始說起,簡單來說, Deposit 是將資料儲存到合約的 Merkle Tree 上。
剛剛提到的秘密,它是在鏈下產生,由 secret 跟 nullifier 組成,合在一起之後也稱作 preimage,因為我們要對這個 preimage 進行 hash,就會成為 commitment。
合約中 Deposit 如下:
deposit 除了傳送代幣到合約之外,需填入一個參數 _commitment。
我們對 preimage 使用 Pedersen 作為 hash function 加密後產生 commitment,以偽代碼表示如下:
const preimage = secret + nullifier;const commitment = pedersenHash(preimage);
這個 commitment 會成為 Merkle Tree 的葉子,所以合約中的 _insert(commitment) 來自 MerkleTreeWithHistory.sol 的合約,將我們的資料插入 Merkle Tree,然後回傳一個 index 給你,告訴你這個 commitment 在 Merkle Tree 上的位置,最後一起發布成公開的 Deposit 事件。
我們知道 MerkleTree 是將一大筆資料兩兩做雜湊後產生一個唯一值 root,這個 root 就是合約上所儲存的歷史資料。
root 的特性就是只要底下的資料一有更動,就會重新產生新的 root。
所以只要一有用戶 deposit ,就會插入新的葉子到 Merkle Tree 上,於是就會產生新的 root,所以在合約中有一個陣列是用來儲存所有的 root 的 roots:
bytes32[ROOT_HISTORY_SIZE] public roots;
roots 是用來紀錄每個 deposit 的歷史,每一次 deposit 都會創造新的 root,而所有 root 都會被儲存進 roots 裡,於是當你要提領的時候,就要證明你的 commitment 所算出的 root 曾經出現在 roots 裡,代表曾經有 deposit 的動作,因此才可以進行提領。
Withdraw
在 Deposit 之前 Tornado Cash 就會在鏈下產生秘密後交給使用者,擁有這個秘密的人等於擁有提款的權利。
提領的時候,秘密會在鏈下計算後產生 proof,proof 是 withdraw 需要的參數,所以只要確保這個 proof 能夠被驗證,那麼代幣的接收地址 (recipient) 就可以隨便我們填,只要不填上當初拿來 deposit 用的地址,基本上就做到匿名交易的效果了。
也就是說,產生這個 proof 並提交給合約,能夠證明此人知道秘密,但卻不告訴合約秘密本身是什麼。
function withdraw(bytes calldata _proof, bytes32 _root, bytes32 _nullifierHash, address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund) external payable nonReentrant;
我們可以清楚看到 withdraw 函式裡沒有接收有關秘密的任何資訊作為參數,也就是秘密不會與合約有所接觸,也不會暴露在 etherscan 上。
回顧 ZKP 所帶來的效果:
鏈下計算
隱藏秘密
在 Tornado Cash 的例子中,我們用秘密來產生證明,完成的鏈下計算包括:
將秘密 hash 成 commitment
算出 Merkle Tree 的 root。
以下是簡化後的 withdraw.circom:
template Withdraw(levels) { signal input root; signal input nullifierHash;
signal private input nullifier; signal private input secret; signal private input pathElements[levels]; signal private input pathIndices[levels];
component hasher = CommitmentHasher(); // Pedersen hasher.nullifier <== nullifier; hasher.secret <== secret; hasher.nullifierHash === nullifierHash;
component tree = MerkleTreeChecker(levels); // MiMC tree.leaf <== hasher.commitment; tree.root <== root; for (var i = 0; i < levels; i++) { tree.pathElements[i] <== pathElements[i]; tree.pathIndices[i] <== pathIndices[i]; }}
component main = Withdraw(20);
從上述代碼就可以看出這份 circuit 的 private 變數有:
secret
nullifier
pathElements
pathIndices
而 public 變數有:
root
nullifierHash
如同我們一開始說過的,秘密就是指 secret 與 nullifier。這裡進行的鏈下計算就是對 secret 與 nullifier 雜湊成 commitment。而使用的 hash function 叫做 Pedersen。
在進行 Merkle Tree 的計算之前,我們還檢查了 nullifier 雜湊後的 nullifierHash 跟 public 變數 nullifierHash 是不是一樣的。
hasher.nullifierHash === nullifierHash;
接下來,開始計算 Merkle Proof,用意是確認經過雜湊後的 commitment 有沒有出現在 Merkle Tree 上,所以我們的 private input 還有 pathElements 與 pathIndices(詳情參考 Part 1 Merkle Tree in JavaScript),讓它跑一趟 Merkle Proof 的計算,最後就能夠算出一個 root,再確認計算後的 root 與我們的 public 變數 root 是否一樣。
tree.root <== root;
於是我們就能產生一個 ZKP 的證明 — 證明 private 變數:secret, nullifier, pathElements, pathIndices 可以計算出 public 變數:root 與 nullifierHash。
把這個證明提交給合約,合約透過 Verifier 驗證 proof 是否正確,以及必須事先確認:
public 變數 root 有在合約的 roots 裡面。
public 變數 nullifierHash 在合約中是第一次出現。
以下附上完整的 withdraw 原始碼:
必須注意 ZKP 是向合約證明使用者填入的 secret 和 nullifier 可以計算出某個 root,但無法保證這個 root 曾經在合約的 roots 歷史上。
所以合約的 withdraw 中,除了 verifyProof 之外,還要事先檢查 ZKP 算出來的 root 是不是真的在歷史上發生過,所以需要 isKnownRoot 的檢查:
function isKnownRoot(bytes32 _root) public view returns(bool)
必須先檢查 isKnownRoot 後才能進行 verifyProof。
經過 verifyProof 驗證成功後,合約就開始進行提款的動作,也就會將代幣傳到 recipient 的地址,最後拋出 Withdrawal 的事件。
nullifier 與 nullifierHash
為什麼我們的秘密不是只有 secret 還要額外加一個 nullifier?
簡單來說,這是為了防止已經提領過的 note 又再提領一次,也就是所謂的 double spend。
require(!nullifierHashes[_nullifierHash], "The note has been already spent");
可以看到 withdraw 需要填入參數 nullifierHash,跟 isKnownRoot 一樣的狀況,我們需要對電路的 public 變數先經過一層檢查之後,才能帶入到 verifyProof 裡面。
nullifierHash 可以理解為這個 note 的 id,但它不會連結到 deposit,因此可以用來紀錄這個 note 是否已經被提領過。
所以當 verifyProof 驗證成功之後,我們要紀錄 nullifierHash 已完成提領:
nullifierHashes[_nullifierHash] = true;
有關為什麼需要事先檢查 public 變數後,才能帶入 verifyProof ,可以參考 Part 2:ZKP 與智能合約的開發入門 提到的 publicSignals 的部分。
附上 Tornado Cash 的架構圖:
簡化版的 tornado-core
tornado-core 的程式碼很簡潔漂亮,所以我模仿該專案自己實作一遍:
simple-tornado:https://github.com/chnejohnson/simple-tornado
這份專案只完成了 tornado-core 的核心部分,不一樣的是我的開發環境使用 hardhat 與 ethers 寫成,而 circom 與 snarkjs 使用官方當前的版本,合約用 0.7.0,測試使用 Typescript 。
比起兩年前的 tornado-core ,simple-tornado 使用的技術更新,可能更適合初學者理解這份專案,但是它有 bug…我在 issues 的地方有紀錄說明。
在開發的過程中,我的順序是先從最小單位的 MiMC hash function 開始玩,發現必須 javascript 算一次 hash、solidity 算一次、circom 再算一次,確保這三個語言對同一個值算出同樣的 hash 之後,才能放心去做更複雜的 Merkle Tree。
總結
我們可以看到 Tornado Cash 簡單的兩個函式:Deposit 與 Withdraw,透過將代幣送入合約後再提領到另一個地址的流程,應用 ZKP 達成匿名的交易。
除了斷開 Deposit 與 Withdraw 的地址關聯性之外,Tornado Cash 還有做了一層「藏樹於林」的隱私防護,這部份的解釋就請參考 ZKP 讀書會 Tornado Cash。
網路上很多關於 ZKP 的文章或專案都是在 2019 年後出產的,經過許多人對這項技術的嘗試,讓我們對 ZKP 有了更清晰的理解,如今兩年後,開發工具也變得更加成熟,期待未來在 web 隱私議題上能看到更多 ZKP 大放異彩的應用。
原始碼
tornado-core
simple-tornado
參考資料
ZKP 讀書會 Tornado Cash
Tornado Privacy Solution Cryptographic Review
Tornado Cash 實例解析 was originally published in Taipei Ethereum Meetup on Medium, where people are continuing the conversation by highlighting and responding to this story.
👏 歡迎轉載分享鼓掌
同時也有109部Youtube影片,追蹤數超過4萬的網紅吳老師教學部落格,也在其Youtube影片中提到,東吳EXCEL函數與VBA課程分享(5) 完整影音: http://www.youtube.com/playlist?list=PLsE34duTsJQyGGSdDIt63QgGr9F11j1Fj 上課內容: 01_貸款計算範例說明 02_如何開啟範例與表單設計 03_如何啟動表單 04_如何當...
「字串 存 入 陣列」的推薦目錄:
- 關於字串 存 入 陣列 在 Taipei Ethereum Meetup Facebook 的最佳貼文
- 關於字串 存 入 陣列 在 紀老師程式教學網 Facebook 的精選貼文
- 關於字串 存 入 陣列 在 紀老師程式教學網 Facebook 的最佳解答
- 關於字串 存 入 陣列 在 吳老師教學部落格 Youtube 的最讚貼文
- 關於字串 存 入 陣列 在 吳老師教學部落格 Youtube 的精選貼文
- 關於字串 存 入 陣列 在 吳老師教學部落格 Youtube 的精選貼文
- 關於字串 存 入 陣列 在 [問題]將字串存入一元陣列?? - 看板C_and_CPP - 批踢踢實業坊 的評價
- 關於字串 存 入 陣列 在 字串存入陣列在PTT/Dcard完整相關資訊 - 萌寵公園 的評價
- 關於字串 存 入 陣列 在 字串存入陣列在PTT/Dcard完整相關資訊 - 萌寵公園 的評價
- 關於字串 存 入 陣列 在 【C 語言入門】19.6 - 存取陣列元素的原理 - YouTube 的評價
字串 存 入 陣列 在 紀老師程式教學網 Facebook 的精選貼文
[熱門文章] 程式設計、重構、與其它任何東西的終極問答
"The Ultimate Question of Programming, Refactoring, and Everything"
網頁版: http://goo.gl/6jIcIp
PDF 版: https://yadi.sk/i/pBZqebxsr5Wyg
#Craftmanships #SoftwareEngineering #CPP #Refactoring #ProgrammingSkills
好的!遲交比不交好,今天的推薦文來了(笑)~
今天介紹這篇,是過去一個禮拜在國外鄉民聚集地 Reddit 程式設計版瘋傳的文章。標題很臭屁「The Ultimate Question of Programming, Refactoring, and Everything」(沒錯!我就在意它最後一個字 "Everything"。咬我啊! XD)。因為轉載的人實在太多,讓我不禁努力地把它看完了。
其實這篇文章講的是 C/C++ 程式寫作者應該注意、或建議遵守的 42 個小訣竅。既不「Ultimate(終極)」,也不是涵蓋「Everthing」。不過裡面還是有不少中肯的建議,所以我還是將它介紹給大家。
為了讓英文苦手的朋友也能稍微感受一下這篇文章在講什麼,所以我不負責任地快速翻譯了每個標題一下。如果對哪個主題有興趣的,就麻煩大家直接對照標題號碼去看原文解說。原文有些標題用「戲謔」或「隱晦」寫法,我若直接翻譯,大家可能不知道原作者想表達什麼。所以我會將某些標題,用比較易懂的中文重新表達。一切以「標題編號(1~42)」為準。
接下來就請享用我這個不負責任的翻譯了。有會錯原文意思的,還請各位留言在下方、然後鞭小力一點 XD。我會馬上修正的:
1. 不要去做編譯器會做的事情
如:用迴圈能存取 a[0] ~ a[9],就不要用「拷貝貼上」a[0], a[1], a[2]..., a[9] 來存取裡面的內容值。
2. 大於 0 不代表它等於 1
若文件告訴你某函數執行成功會傳回「大於0」的值、但目前這個大於0的值是「1」。請你寫程式的時候不要自作聰明地偵測「傳回值 == 1」當成成功,請乖乖遵照規格書用「傳回值 > 0」等於成功。因為將來的版本有可能還會傳回 2, 3...等其他值。
3. 當你拷貝貼上一段程式碼,記得檢查它的副本兩遍
有時候你拷貝貼上一段程式碼,會忘了去修改裡面一些不同的小數字,導致花了大把時間去檢查錯誤到底出現在哪裡。
4. 小心使用「? :」運算子。並記得多加括號
「? :」是 C/C++ 內常用的運算子。若您寫了一段這樣的原始碼「a - b?0:1」,您可能以為它是這樣運作的「a - (b?0:1)」,事實上,它是這樣運作的「(a-b)?0:1」。結論是,多加括號保平安。
5. 多用市面上有的工具來分析您的原始碼
市面上有些工具,如:原始碼靜態分析工具、原始碼排列工具...可以幫您在把原始碼送入編譯器前,就抓到錯誤。不過作者也提到,別以為倚賴這些工具,錯誤就不會發生。真正要減少錯誤還是得靠多讀規格書,增加程式寫作經驗才辦得到。
6. 確認您所有的指標,都已經轉型成整數型態
作者擔心,某些使用 64 bits 當成指標變數寬度的系統,到 32 bits 的機器內重新編譯時,會產生高位元組被截斷的慘劇。某些編譯器提供「uintptr_t」這個專門給指標變數使用的型態,會隨著編譯器所在的環境,自動調整指標寬度。
7. 別在迴圈內呼叫「alloca()」這個函數
萬一迴圈失控,alloca() 函數會霸佔大量記憶體無法釋放。建議事先在迴圈外霸佔一大塊足夠的記憶體,然後在迴圈內慢慢蠶食之。
8. 在「解構函數(Destructor)」內使用「例外處理(Exception)」是很危險的!
作者認為,在負責釋放記憶體、收尾等工作的解構函數,還去霸佔新記憶體作事情是不好的。若真的發生例外(Exception),直接「吃掉(Supress)」不要讓它出現在使用者面前可能還比較好。
9. 若你要比對字串結尾,請用 '\0' 代表
有些程式設計師因為 '\0' 其實就是數字 0,而在比對字串結尾時,直接使用 0 來比對字串結尾。作者認為這個習慣不好。
10. 請勿濫用 # ifdef
# ifdef 很好用,但很容易讓原始碼雜亂難讀。作者不會建議大家不要用,但他反對連可以用 if ~ else 解決的場合,都濫用 # ifdef。
11. 別把一堆運算子全都擠在同一列
多分成幾列,Debugger 可以比較容易指出發生錯誤的是在哪個環節。
12. 當你「拷貝貼上」程式碼時,特別注意「最後一列效應」
作者還是不太建議濫用拷貝貼上,他認為需要重複使用一段程式碼,不如好好考慮寫成稍有彈性的函數,然後重複叫用。此外,他建議大家去看「最後一列效應」這篇文章(連結在本文),並了解最後一列效應在拷貝貼上程式碼內,所扮演的角色。
13. 程式碼若很長,盡量多折幾列,然後排成像表格般一樣整齊(Table-style)
14. 好編譯器 + 好的寫碼習慣是不夠的
內文舉了個後括號「)」括錯位置,但編譯器抓不出來的例子。
15. 若有一堆意義相關的常數,請用 enum 括住它們
16. 「看我能把程式碼寫得這麼屌!」的炫耀寫碼心態不可取
寫程式碼要以「穩」「易讀」為主,不是把一些剛學不久,覺得很酷,但三個月後會忘個精光的技術用進程式碼內。
17. 想用程式碼把一塊資料清乾淨,最好把清除程式碼獨立拉出來成一個專屬函數
18. 你在一個語言行得通的方法,在另一個語言不一定行得通
19. 盡量用技巧避免在同一個類別內,建構函數彼此呼叫的情況
20. 讀檔時,只檢查有沒有讀到檔尾(EOF)似乎是不夠的
21. 正確檢查 EOF 的方法
22. 有比使用 # pragma warning(...) 來印錯誤訊息更好的方法,勿濫用
23. 如果你想取得字串長度,用函數自動幫你算,別用手算然後硬填數字上去
24. 請多使用 "override" 與 "final",它們會是你的好朋友
25. 別再把 "this" 指標跟 "nullptr"(空指標)拿來作比較
26. 小心使用 VARIANT_BOOL 這個陰險狡猾的東西
27. BSTR(Binary STRing)這個用於微軟 COM/Automation 技術中的資料型態,請小心使用
28. 能用函數把一段程式碼包起來重複用,就別用巨集包它(使用巨集函數的缺點多於優點)
29. 在迴圈或迭代程式碼間,使用 ++i,來取代 i++(i++ 編譯後的執行效能稍微差那麼一點)
30. wprintf() 函數的使用陷阱:Win32 印寬字元字串要用 %S(大寫),Win64 要用 %s(小寫)。
31. 陣列在 C/C++ 傳給函數時,並非是「傳值呼叫」(Call by Value)
32. 要把檔案內的文字直接印在螢幕上時,請不要直接使用 printf() (怕檔案內夾雜 % 開頭的字,這些字對 printf 是有特殊意義的)
33. 想對一個指標取值(亦即:*p),記得檢查它是否為 NULL。否則你對 NULL 取值會導致系統出錯的
34. 別以為 int 的上限 21億+ 很多,在 64 bits 系統中,這個數字很容易爆掉
35. 若您把 enum 常數與 switch~case 連用,增加新元素進 enum 時也別忘了加新 case 進 switch
36. 如果有怎麼抓都抓不出來的 bugs,記得往「記憶體」的方向去思考(32bits vs. 64bits 之類的問題)
37. 在 do~while() 內用 continue 指令要小心,有可能會跳過你放在底部的「更新條件」,導致無窮迴圈
38. 對於指標,請用 nullptr 代替 NULL,這是新的 C++ 規格書希望您遵循的
39. 試著別把一列式子搞得太複雜,這樣比較不會有「咦?為何這段寫錯的程式碼居然可以運作」的問題出現
40. 開始使用「原始碼靜態分析工具」吧!
41. 別為了要使用某函式庫的一個函式,而引進整個函式庫。如果只用了一個函式,建議自己寫比較容易維護。
42. 別再用 empty 這個曖昧的字眼當函數名稱了。用 erase(), clear() 都比 empty() 好。
如果您覺得小弟翻譯了這麼多,沒有功勞也有苦勞,那就麻煩按個讚犒賞小弟一下吧!當然歡迎轉發給您 Facebook 的朋友共同討論。最後提醒一句,上述 42 點別把它們全都當聖旨,親身體會驗證才是最重要的喔!
祝福大家假期愉快!
字串 存 入 陣列 在 紀老師程式教學網 Facebook 的最佳解答
[WebTech #82] JavaScript 大補帖!一篇搞定 JavaScript!
這篇大概是今天唯一會分享的一篇了...別誤會!我沒有偷懶!關於 JavaScript,我一樣收集了大約 80 幾篇國內外文章打算分享的!但是昨天晚上,不小心找到我現在要分享的這篇,一頁就刊出 89 篇影音教學!而且主題包括「JavaScript 入門」、「JavaScript 物件」、「AJAX」、「DOM」、「jQuery」。把我要分享的主題全包括了!而且還追加「用 JavaScript 做 App」、「JavaScript 設計模式」等幾個額外的主題。
我倒抽一口涼氣,心想:「這篇貼出去我還混什麼啊?」於是我的心情就在「照原定計畫刊出 80 幾篇、以彰顯小弟的努力跟多賺幾個讚」,還是「貼出這一篇、頂著可能被別人罵偷懶、但對大家有幫助」之間搖擺不定。最後...我決定還是以讀者能夠理解為最優先!虛榮心什麼的去吃 X 吧... XD。
原文是台灣的一位網友,依照 w3schools.com (我前幾天分享 CSS 時也有引用他們的文章)的大綱,以台灣方面電腦用語(如:Object=物件,而非「對象」。Memory=記憶體,而非「內存」)錄製而成的影音教學。考量到本粉絲頁還是以台灣網友佔多數,中國、香港、新加坡、馬來西亞的網友,如果您們不習慣台灣這邊的用語就抱歉了!我會提供英文原文給您們參考的!
接下來,就讓我隆重介紹今天唯一一篇、也最補的一篇:JavaScript 教學大補帖!連結與大綱如下,想學會的朋友一定要耐心看完喔:
台灣網友影音版:
http://ithelp.ithome.com.tw/question/10098361
w3schools.com 英文原文(無影片):
http://www.w3schools.com/js/
JavaScript 教學 1:簡介
JavaScript 教學 2:環境
JavaScript 教學 3:變數
JavaScript 教學 4:運算子
JavaScript 教學 5:邏輯
JavaScript 教學 6:If...Else
JavaScript 教學 7:Switch
JavaScript 教學 8:彈出式對話框
JavaScript 教學 9:函數
JavaScript 教學 10:for 迴圈
JavaScript 教學 11:while 迴圈
JavaScript 教學 12:for each 迴圈
JavaScript 教學 13:break/continue
JavaScript 教學 14:事件
JavaScript 教學 15:Exception
JavaScript 教學 16:自定義錯誤
JavaScript 教學 17:特殊字元
JavaScript 教學 18:物件
JavaScript 教學 19:字串
JavaScript 教學 20:日期
JavaScript 教學 21:陣列
JavaScript 教學 22:布林
JavaScript 教學 23:數學
JavaScript 教學 24:正規式
JavaScript 教學 25:Browser 物件
JavaScript 教學 26:Cookie
JavaScript 教學 27:setInterval
JavaScript 教學 28~30:AJAX
JavaScript 教學 31~33:DOM
JavaScript 教學 34~42:jQuery
JavaScript 教學 43:JSON
JavaScript 教學 44~55:App 實作
JavaScript 教學 56﹣85:JS 三十參
JavaScript 教學 86:JSFiddle
JavaScript 教學 87~89:設計模式
字串 存 入 陣列 在 吳老師教學部落格 Youtube 的最讚貼文
東吳EXCEL函數與VBA課程分享(5)
完整影音:
http://www.youtube.com/playlist?list=PLsE34duTsJQyGGSdDIt63QgGr9F11j1Fj
上課內容:
01_貸款計算範例說明
02_如何開啟範例與表單設計
03_如何啟動表單
04_如何當EXCEL執行自動開啟表單
05_按鈕事件處理(計算每月償還金額)
06_按鈕事件處理(計算將資料寫到EXCEL中儲存)
07_運用自動提示與清除資料
08_建立ACCESS資料庫
09_新增資料到資料庫
10_逐行了解如何新增資料與除錯技巧
11_更改連線字串與批次將EXCEL資料搬到資料庫中
13_如何避免錯誤與保險費範例說明
14_保險費計算範例介面設計說明
15_保險費計算開始計算程式
16_保險費計算資料庫連線說明
17_保險費計算資料庫程式說明
18_批次新增資料庫程式說明
12_如何避免程式發生錯誤
補充資料:
EXCEL函數與VBA設計
http://goo.gl/LEjSW
EXCEL函數與VBA雲端班
http://goo.gl/zz71P
EXCEL函數與VBA進階班
http://goo.gl/rq9EK
上課可分為實體老師教學與數位雲端學習,有三階段課程:
1.Excel2003或2010進階與函數應用
2.Excel函數與VBA雲端班
3.Excel VBA程式設計
1.有系統的學習函數的使用。
2.Excel內建的VBA正是為了解決這種繁複、瑣碎的操作而生。
3.以循序漸進的方式,透過詳細的說明和實用的範例。
4.進而解說EXC-EL與資料庫的結合。
5.將結合GOOGLE雲端試算表。
課程大綱
堂數 類別 內容
第一堂 文字和資料函數
第二堂 邏輯函數
第三堂 尋找與參照函數
第四堂 VBA編輯器 控制項名稱、變數名稱的命名規則
變數的宣告、變數資料類型
第五堂 操作資料庫1 將VBA活用在資料庫中
記錄、資料的搜尋、篩選
第六堂 操作資料庫2 將VBA活用在資料庫中
記錄、資料的搜尋
第七堂 以VBA來與外部資料庫合作 文字檔案的讀寫、利用QueryTable
使用ADO控制外部資料、操作XML資料
第八堂 實例:模擬考系統 函數佈局、出題
評分、程式改良、系統包裝
第九堂 實例:郵遞區號 除錯環境一、除錯環境二
陣列變數
第十堂 實例:個股進出表 讀取資料、計算頁數
找出起始列、程式組合
EXCEL VBA辦公自動化--自強基金會2012(第1次上課)
http://terry55wu.blogspot.tw/2012/07/excel-vba-20121.html
EXCEL VBA辦公自動化二班--自強基金會2012(第1次上課)
http://terry55wu.blogspot.tw/2012/08/excel-vba-20121.html
EXCEL VBA辦公自動化--自強基金會2012(第6次上課)
http://terry55wu.blogspot.tw/2012/08/excel-vba-20126.html
EXCEL VBA辦公自動化二班--自強基金會2012(第8次上課)
http://terry55wu.blogspot.tw/2012/10/excel-vba-20128.html
EXCEL VBA辦公自動化--自強基金會2012(第9次上課)
http://terry55wu.blogspot.tw/2012/09/excel-vba-20129.html
EXCEL VBA辦公自動化二班--自強基金會2012(第10次上課)
http://terry55wu.blogspot.tw/2012/10/excel-vba-201210.html
EXCEL VBA辦公自動化--自強基金會2012(第11次上課)
http://terry55wu.blogspot.tw/2012/09/excel-vba-201211.html
EXCEL VBA辦公自動化二班--自強基金會2012(第11次上課)
http://terry55wu.blogspot.tw/2012/10/excel-vba201211.html
EXCEL VBA辦公自動化--自強基金會2012(第12次上課)
http://terry55wu.blogspot.tw/2012/10/excel-vba-201212.html
EXCEL VBA辦公自動化2012(第13次上課)-破解股市資料
http://terry55wu.blogspot.tw/2012/10/excel-vba201213.html
EXCEL VBA辦公自動化二班--自強基金會2012(第13次上課)
http://terry55wu.blogspot.tw/2012/11/excel-vba-201213.html
EXCEL VBA辦公自動化--2012(第14次上課)
http://terry55wu.blogspot.tw/2012/10/excel-vba-201214-ending.html
EXCEL VBA辦公自動化二班--自強基金會2012(第14次上課Ending)
http://terry55wu.blogspot.tw/2012/11/excel-vba-201214ending.html
EXCEL,VBA,函數,吳清輝老師,程式設計,線上教學excel vba教學,excel 2010 vba,excel 2007 vba,excel vba教學網站,excel vba tutorial,excel vba電子書,excel vba範例,excel vba教學電子書,excel vba array,excel vba example
字串 存 入 陣列 在 吳老師教學部落格 Youtube 的精選貼文
東吳EXCEL函數與VBA課程分享(5)
完整影音:
http://www.youtube.com/playlist?list=PLsE34duTsJQyGGSdDIt63QgGr9F11j1Fj
上課內容:
01_貸款計算範例說明
02_如何開啟範例與表單設計
03_如何啟動表單
04_如何當EXCEL執行自動開啟表單
05_按鈕事件處理(計算每月償還金額)
06_按鈕事件處理(計算將資料寫到EXCEL中儲存)
07_運用自動提示與清除資料
08_建立ACCESS資料庫
09_新增資料到資料庫
10_逐行了解如何新增資料與除錯技巧
11_更改連線字串與批次將EXCEL資料搬到資料庫中
13_如何避免錯誤與保險費範例說明
14_保險費計算範例介面設計說明
15_保險費計算開始計算程式
16_保險費計算資料庫連線說明
17_保險費計算資料庫程式說明
18_批次新增資料庫程式說明
12_如何避免程式發生錯誤
補充資料:
EXCEL函數與VBA設計
http://goo.gl/LEjSW
EXCEL函數與VBA雲端班
http://goo.gl/zz71P
EXCEL函數與VBA進階班
http://goo.gl/rq9EK
上課可分為實體老師教學與數位雲端學習,有三階段課程:
1.Excel2003或2010進階與函數應用
2.Excel函數與VBA雲端班
3.Excel VBA程式設計
1.有系統的學習函數的使用。
2.Excel內建的VBA正是為了解決這種繁複、瑣碎的操作而生。
3.以循序漸進的方式,透過詳細的說明和實用的範例。
4.進而解說EXC-EL與資料庫的結合。
5.將結合GOOGLE雲端試算表。
課程大綱
堂數 類別 內容
第一堂 文字和資料函數
第二堂 邏輯函數
第三堂 尋找與參照函數
第四堂 VBA編輯器 控制項名稱、變數名稱的命名規則
變數的宣告、變數資料類型
第五堂 操作資料庫1 將VBA活用在資料庫中
記錄、資料的搜尋、篩選
第六堂 操作資料庫2 將VBA活用在資料庫中
記錄、資料的搜尋
第七堂 以VBA來與外部資料庫合作 文字檔案的讀寫、利用QueryTable
使用ADO控制外部資料、操作XML資料
第八堂 實例:模擬考系統 函數佈局、出題
評分、程式改良、系統包裝
第九堂 實例:郵遞區號 除錯環境一、除錯環境二
陣列變數
第十堂 實例:個股進出表 讀取資料、計算頁數
找出起始列、程式組合
EXCEL VBA辦公自動化--自強基金會2012(第1次上課)
http://terry55wu.blogspot.tw/2012/07/excel-vba-20121.html
EXCEL VBA辦公自動化二班--自強基金會2012(第1次上課)
http://terry55wu.blogspot.tw/2012/08/excel-vba-20121.html
EXCEL VBA辦公自動化--自強基金會2012(第6次上課)
http://terry55wu.blogspot.tw/2012/08/excel-vba-20126.html
EXCEL VBA辦公自動化二班--自強基金會2012(第8次上課)
http://terry55wu.blogspot.tw/2012/10/excel-vba-20128.html
EXCEL VBA辦公自動化--自強基金會2012(第9次上課)
http://terry55wu.blogspot.tw/2012/09/excel-vba-20129.html
EXCEL VBA辦公自動化二班--自強基金會2012(第10次上課)
http://terry55wu.blogspot.tw/2012/10/excel-vba-201210.html
EXCEL VBA辦公自動化--自強基金會2012(第11次上課)
http://terry55wu.blogspot.tw/2012/09/excel-vba-201211.html
EXCEL VBA辦公自動化二班--自強基金會2012(第11次上課)
http://terry55wu.blogspot.tw/2012/10/excel-vba201211.html
EXCEL VBA辦公自動化--自強基金會2012(第12次上課)
http://terry55wu.blogspot.tw/2012/10/excel-vba-201212.html
EXCEL VBA辦公自動化2012(第13次上課)-破解股市資料
http://terry55wu.blogspot.tw/2012/10/excel-vba201213.html
EXCEL VBA辦公自動化二班--自強基金會2012(第13次上課)
http://terry55wu.blogspot.tw/2012/11/excel-vba-201213.html
EXCEL VBA辦公自動化--2012(第14次上課)
http://terry55wu.blogspot.tw/2012/10/excel-vba-201214-ending.html
EXCEL VBA辦公自動化二班--自強基金會2012(第14次上課Ending)
http://terry55wu.blogspot.tw/2012/11/excel-vba-201214ending.html
EXCEL,VBA,函數,吳清輝老師,程式設計,線上教學excel vba教學,excel 2010 vba,excel 2007 vba,excel vba教學網站,excel vba tutorial,excel vba電子書,excel vba範例,excel vba教學電子書,excel vba array,excel vba example
字串 存 入 陣列 在 吳老師教學部落格 Youtube 的精選貼文
Excel VBA辦公室自動化程式開發(公訓處)2-1
如何學會EXCEL函數與VBA提高工作效率提前下班
完整教學影音
http://www.youtube.com/playlist?list=PLsE34duTsJQz2veMbVTQ7__bCKuBKQlIp
完整影音:
http://groups.google.com/group/excelvba2012?hl=zh-TW
如何把EXCEL"函數"變為 "VBA"?
今天課程延續大樂透函數版轉成VBA版,這裡會遇到幾個要注意事項:
1.如何利用陣列存放 6個使用者選號與 7個亂數產生的號碼。
2.如何增加副程式,再利用call呼叫。
3.除錯技巧說明,如何逐行與新增監看式。
之後再教了兩個範例,一個是銷貨單,把EXCEL當成資料庫來存放資料,
與郵遞區號碼轉換程式撰寫,可以快速的分析資料並輸出成所要資料結果。
很快的就完成VBA的建立,如此效率大增,隨心所欲的建立標準流程。
01_講師簡介與課程大綱
02_問卷結果與縮短網址與下載檔案
03_範例01:進階功課表說明
04_範例01:進階功課表解題
05_開發環境設定與巨集安全性
06_如何錄製巨集並修改
07_如何在巨集中加入註解與增加按鈕
08_實例2:大型試算表說明
09_實例2:大型試算表解說(公式)
10_實例2:大型試算表解說(九九乘法表)
11_實例2:大型試算表解說(函數)
12_實例2:大型試算表解說(巨集)
13_實例2:大型試算表解說(VBA列迴圈)
14_實例2:大型試算表解說(VBA欄迴圈)
15_實例2:大型試算表解說(VBA字串)
16_實例2:大型試算表解說(VBA非字串)
17_實例3:文字遊戲說明
18_實例3:文字遊戲說明串接
19_實例3:文字遊戲說明串接(合併字串VBA)
補充資料:
EXCEL函數與VBA進階班總整理:
http://terry55wu.blogspot.com/p/excelvba.html
目前 EXCEL函數與VBA完整影音論壇:
1.EXCEL函數與VBA設計
http://groups.google.com/group/labor_excel_vba?hl=zh-TW
2.EXCEL函數與VBA進階51
http://groups.google.com/group/excelvba51?hl=zh-TW
3.EXCEL函數與VBA雲端班
http://groups.google.com/group/excelvbacloud?hl=zh-TW
4.EXCEL VBA辦公自動化班
http://groups.google.com/group/excelvba_cloud?hl=zh-TW
5.EXCEL函數與VBA設計(自強基金會2012)
http://groups.google.com/group/excelvba2012?hl=zh-TW
由於吳老師超過十年以上的教學經驗,對EXCEL與VBA十分純熟,
並將多年的教學過程錄製分享給學生課後學習,讓想學習者也想一同學習,
但礙於加入者實在太眾多,無法讓所有人加入,除非您是:
1.吳老師目前上這門課的學生。
2.吳老師的數位影音申請的學生,也就是申請完整教學影音DVD者。網址:http://goo.gl/xME01
最近湜憶電腦也開設EXCEL函數與VBA設計課程,若有興趣可以詢問看看。
EXCEL,VBA,函數,自強基金會,吳清輝老師,程式設計,線上教學,e化創新,雲端計算,吳老師提供,APP教學
字串 存 入 陣列 在 字串存入陣列在PTT/Dcard完整相關資訊 - 萌寵公園 的推薦與評價
因此當把一個字串存入一個 ...String.ToCharArray 方法(System) | Microsoft Docs將這個執行個體中的字元複製到Unicode 字元陣列中。 Copies the characters in this ... ... <看更多>
字串 存 入 陣列 在 字串存入陣列在PTT/Dcard完整相關資訊 - 萌寵公園 的推薦與評價
因此當把一個字串存入一個 ...String.ToCharArray 方法(System) | Microsoft Docs將這個執行個體中的字元複製到Unicode 字元陣列中。 Copies the characters in this ... ... <看更多>
字串 存 入 陣列 在 [問題]將字串存入一元陣列?? - 看板C_and_CPP - 批踢踢實業坊 的推薦與評價
開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
Dev-C++
額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
問題(Question):
我想將txt檔資料讀出想要部分擷取下來存入一元陣列
餵入的資料(Input):
預期的正確結果(Expected Output):
m[18]想要存放a1,a2,b1出來的字串總共進入while六次,一次三的字串
錯誤結果(Wrong Output):
每次print出來的值都是想要的,可是存入陣列後出來的結果就會無法顯示
我想應該是指標存的是位置重複做的結果會覆蓋原來的值
程式碼(Code):(請善用置底文網頁, 記得排版)
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int main()
{
FILE *fp;
fp = fopen("C:\\Users\\99092040\\Desktop\\WI202 log\\SEQ-XXXXXXXX--20110127-230143_PASS.txt","r");
char a[50];
char m[18];
char b[50];
char c[4];
char d[6];
char *p1;
char *p2;
char *s1;
char *a1;
char *b1;
char *a2;
int i=0,j=0;
while(fgets(a,50,fp)!=NULL)
{
p1=strstr(a,"ANT0");
p2=strstr(a,"ANT1");
//printf("%s\n",a);
if(p1!=NULL || p2!=NULL)
{
//printf("%s\n",a);
s1=strtok(a,"\t");
//printf("%s\n",s1);
s1=strtok(NULL,"\t");
s1=strtok(NULL,"\t");
//printf("%s\n",&s1);
a1=s1;
//memcpy(a1, s1, sizeof(s1));
printf("%s\n",a1);
m[j]=*a1;
//strncpy(m[j],a1,sizeof(a1));
//printf("%s\n",m[0]);
j=j+1;
//a1=strcat(a1,"_");
s1=strtok(NULL,"\t");
a2=s1;
//printf("%s",a2);
m[j]=*a2;
//strcpy(m[j],a2);
j=j+1;
s1=strtok(NULL,"\t");
s1=strtok(NULL,"\t");
s1=strtok(NULL,"\t");
s1=strtok(NULL,"\t");
s1=strtok(NULL,"\t");
b1=s1;
//strcpy(m[j],b1);
//printf("%s",b1);
m[j]=*b1;
j=j+1;
//i=i+1;
//printf("%s\n",m[0]);
//printf("%s %s\t",a1,a2);
}
//printf("%s\n",m[j]);
}
printf("%s",(m[2]));
fclose(fp);
system("pause");
return 0;
}
補充說明(Supplement):
被mark的地方是我要驗證出來的結果, printf("%s",(m[0]))理論上只想要一個字串,可是卻會跑出六個字串??
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.134.146.217
... <看更多>