當前位置: 華文星空 > 知識

開始慢慢抄程式碼敲對自己編程提高有用嗎?

2020-04-15知識

沒用。和太平洋小島上那些戴著木頭做的耳機型祭祀用品嘰裏咕嚕想把神靈的大鐵鳥喊下來一樣滑稽。

學習編程照著別人的程式碼敲進去有效率嗎?

真想學的話,建議你買個便宜機械表拆了,或者買點電子元件自己焊個收音機,徹底搞明白它們是怎麽工作的。

不會編程、沒有思路,多半是因為你壓根不會活用知識,理解不了機械/電子產品的工作原理,不知道自己學過的物理數學化學知識是怎麽套用於電磁爐微波爐電視機裏面的。

缺了這個理解,所以你看什麽都是咒語的堆砌。所以你抄/背這玩意兒不會有半點用:

擰你面前的圓盤子!右邊!快!90°!
保持!保持!
圓盤子擰回來!180°!
腳!右腳!從現在的位置向左挪10厘米,踩!快!快!
圓盤子下面有個鑰匙,逆時針擰。擰到擰不動。
右邊,中間,看見那個向前的把手了嗎?拉起來!
下車,跟著警察叔叔走。

因為程式是執行過程的 抽象 。它離具體動作太近,離思想太遠。所以跟著上面那些咒語你只會跳大神,絕對不可能學會開車。

離具體執行過程遠點,真正理解了它,上面一大堆就精簡為如下幾句話:

圓盤子是方向盤。
旋轉方向盤就可以讓車輛向對應方向轉彎。
有人過馬路,要踩剎車避讓。剎車是油門左邊緊挨著那個。
如果撞到人了,停車,熄火,拉手剎,等警察帶走。

程式其實隔的更遠。它可能是這樣:

select_port(197);
out(90);
select_port(198);
out(1);
select_port(199);
out(5);

轉譯過來是:

197號埠接了個電機控制板,這是它的第一個控制寄存器。它控制的電機和方向盤相連。
對它輸出90,它就旋轉90圈,一圈對應方向盤轉動1°。
這兩句對應「擰你面前的圓盤子」。

198號埠接著電機控制板的第二個寄存器。
對它輸出1,意思是動作要在1秒內完成。
這兩句對應「快!快!」。

199號埠接電機控制板的第三個寄存器。
對它輸出5,意思是動作執行後鎖死電機,保持5秒,避免方向盤回轉。
這兩句對應「保持!保持!」。

現在,告訴我,你抄這堆鬼畫符,能抄到什麽?

select_port(197);
out(90);
select_port(198);
out(1);
select_port(199);
out(5);

背下來?

下次我把電機接網線上,ip 192.168.1.7,你怎麽辦?

控制字?沒了。現在我把這個丟給下位機,你發個報文,內容是「turn 75, left, fastest」就好。車輛會左轉到和現有路線成75°夾角的方向,以最快速度。具體執行細節在下位機上。

你看,隨便你背多少,是不是全沒用了?

想有用,你必須理解這個電動小車究竟是怎麽一回事;加速你應該控制哪個電機;倒車、轉彎、裝卸,剎車,以此類推。

理解了這個東西,然後你再編程,發電訊號過去,觸發這些動作。這才是正確過程。

換句話說,編碼是具體執行細節,是因地制宜的東西——是跟著環境、需求甚至個人習慣不停變動的東西。

背這個,就好像太平洋島嶼的土人考證「呼喚大鐵鳥需要摳幾下鼻子」一樣,完全是扯淡。

想理解它,你恰恰必須站的足夠高、離的足夠遠,直到你可以用人類語言去描述它的機制為止。

然後,程式是另一套機制,它把模糊的人類語言轉譯成具體細致的執行動作——把手指從鼻孔拿出來,取紙巾擦擦,換一檔,松離開,起步!

你背這個,暈不暈?迂不迂?

你沒摳鼻子,起步也必須先摳下鼻子,紙巾擦擦?不然不能掛擋?

高速上,你朋友問到你家怎麽走,你也伸手指掏鼻孔,摸張紙巾擦擦,從後排伸手給人家掛個二檔?

金牌教練都這麽教的?你照做了居然會挨打?

打的好。

你猜正規公司為何忌諱從網上拷貝程式碼?

哪怕你照著一行行抄進自己的工程,都比拷貝黏貼齊譜。起碼該公司的考核可以保證你看得懂程式碼;然後,你就能在一行行的輸入過程中,發現其中某幾句不符合你所在公司的軟件環境。

而一旦換了環境,原本0 warning 0 error 0 bug的程式碼,或許連基本功能都會牛頭不對馬嘴。

國外統計顯示,近年來各公司軟件質素明顯下降。因為從StackOverflow等網站拷貝程式碼的現象越來越多。

類似的,演算法看不懂,一行行抄程式碼是行不通的。你得真正理解演算法的思路,理解每行程式碼究竟幹了什麽、究竟和整個記憶體環境、整個電腦有著哪些互動——術語叫side effect。

前者其實是初中知識——本科階段的演算法也就這點水平,考你語文能力(閱讀理解)和基本的邏輯知識。

後者其實是X語言編程的基礎知識——你是不是真的在學X程式語言時,自己敲過程式碼?是不是真的做過每章習題?如果做過,你自然就明白了程式語句的作用和能力;等學到演算法與數據結構時,你會覺得那本書的內容,大部份你自己都想到了。

中學知識死記硬背、滿是夾生飯,所以理解不了鐘表收音機等各種器物的工作原理;程式語言滿是夾生飯,死記硬背for/while/i+++++i,連個普通的日程管理/行事曆/排課程式都不會寫——現在突然讓你學演算法,你不懵逼才怪。

那麽,究竟是因為什麽,讓你學不會編程呢?要如何針對性的訓練?

要回答「為什麽學不會編程」,首先你必須先學會編程。那些「考前突擊混過數據結構考試」的憨批是教不會你的,因為他自己都不會。

光會還不行,你還得學的比較好,起碼得是個職業程式設計師——碼農趁早別發言。教人一碗水你起碼得有一桶水。半瓶子咣當的怎麽敢來?

學編程,無非兩個難點:

一是 思路

思路是最難的。你必須極為了解各種事物背後的原理,了解到能用數學語言表達出來的程度。

二是「 如何把思路塞進程式語言語法的套子 」。

註意,你得先有思路,然後像調遣手下的戰士一樣,安排程式語言提供的指令們各就各位,把你的思路分片包幹、執行下去。

編程語法這類東西太淺,看一遍書就應該完全能理解的。全都小學知識。

當然,理解了不等於就能執行。因為格式太死板,一點不能錯——很多人學不會編程,就是學偏到死記硬背規則/格式上了。比如什麽short是幾個字節、每個字節幾個位;或者if後面應該是圓括弧還是中括弧;或者print裏面有哪些符號、參數代換規則是什麽之類。

這些東西自然是必須熟練掌握的。但根本 不需要死記硬背 大概理解是什麽意思 ,多敲程式,就好像玩遊戲一樣,不知不覺一切細枝末節就都牢牢記住了。

記住它的意義,大概在於證明你的確上機敲過不少程式;另外就是鍵盤輸入效率更高、更容易一次敲對,不需要頻頻翻資料對照格式,不會遇到語法錯誤茫然失措。但它並不影響你設計程式。

重復一遍: 設計程式的思路,並不受語法格式影響 。無非就是你先理清思路、然後想辦法把這個思路塞進語法的套子裏罷了。

換句話說,第二點其實並不難。但需要大量的練習。

編程最難的地方還是思路,沒有思路,就好像突然讓你去打仗;結果你看著一排排大頭兵,連自己要做什麽都不知道,怎麽給它們安排任務?

那麽, 思路是怎麽來的

從看得見摸得著的開始。

你有個遠方結識朋友來找你玩,但你不在家,得幾個小時後才能回去。所以你需要透過文字資訊給他指個路,讓他到你家門前的咖啡廳等著。

請問,你該如何編寫這條資訊?你需要他理解哪些東西,才能確保他找到正確地方?

1、首先你得知道你家在哪。或者說, 確定一個目標

連目標都沒有,思路可能存在嗎

——你寫個程式!
什麽程式?
——我怎麽知道!快寫!
那我寫個hello world?
——別寫那種逗小孩玩的!寫個牛逼點的!
寫什麽?
——我怎麽知道!

嗯,你說這程式該怎麽寫。

因此,你必須給自己一個明確的目標。

2、你是怎麽找到你家的?

哎呀我說不清,反正閉著眼睛就走到了……
嗯……那我回去了。反正我閉著眼睛走不到你家。
別!我想想辦法……

有了。第一步,先找個公交月台,坐車到……對了你得先告訴我站名……哎呀太復雜了。你看月台上的說明,隨便找個公交車,先到火車站!
到了火車站怎麽辦?
坐101路車,到XX中路XX學院站下車。
然後?
到街對面,沿剛才101路車前進方向走50米,進XX胡同。
繼續?
進胡同一直往前走,走到一個丁字路口,左轉,20米就到了。

沒錯。這就是思路。這就是演算法。

3、有思路了,現在就可以寫成程式。

3.1、找公交月台

3.2、找一輛目的地是火車站的公交車

3.3、上車,去火車站

3.4、聽語音播報,if(站名==火車站) then 下車 else 在車廂裏呆著 endif

3.5、火車站下車後,找到101路車月台,上車

3.6、

while ( true ) { input ( "輸入公交站名" , & station ); //不是C標準函數。我故意的。自己想法封裝去。基礎知識而已。 if ( station == "XX中路XX學院站" ) { //c裏面沒法直接用==比較字串。自己想辦法解決。 break ; } } // 下車,然後按指示走到地方

4、現在,輪到你給你同學指路了。

別抄我上面的。沒用。我家又不是你家——何況還是我隨口杜撰的案例。

但是,領會了思路,這事還有那麽難嗎?

你看,就這麽點東西。

類似的,數據結構與演算法講的是什麽?

一些比較難的、一般人一下子想不出解法的問題的解決思路——有了思路,你自己寫出程式碼。

不僅如此,它還要告訴你,這些思路好不好、為什麽、如何評判——冒泡法時間復雜度⊙(N^2),空間復雜度⊙(1),快排時間復雜度⊙(N X logN),等等。

學了這些進階知識,今後你調兵遣將就必須有章法——你不光要能寫出程式,還要能說出其復雜度、甚至證明你的演算法已經是這個問題的最佳解法。起碼復雜度不能高一個級別,業界通用實作O(N)你弄成O(N^2),樂子可就大了。丟本科生的人!

所以,你 學不會編程的根本原因 在哪呢?

第一,你 是不是真的指揮過你的士兵

如果你連它們是火槍兵還是藤牌軍、或者是步坦協同的近代軍隊、空地協同的現代化精銳部隊都不知道,你能正確指揮它們嗎?

沒錯。if/else/while/for/ class,這些就是你的兵。

它們是你 未來幾十年生涯裏的唯一依靠 ,是你最為忠心耿耿的近衛隊。

你一定得經常和它們玩,盡可能的挖掘它們的極限,直到能夠如臂使指。

如果你只是為了混過考試死記硬背過一點東西、連差遣它們幫你提醒一下女朋友生日的嘗試都沒有……

該幹嘛幹嘛去吧。你根本就不該學這一行。

真想入這行,從現在開始,操練你的兵。從女朋友生日提醒、到寫給女朋友玩的萌萌噠的沙雕小遊戲,你都要親歷親為,一行行的自己想出來——你必須和你的親兵吃住都在一起,熟悉它們每個人,它們才會為你效死力。

這是最樸實,但也是程式設計師 最重要 的技能。是你的 立身之本

第二,在一的基礎上,你是否真正看懂了別人的調兵思路。

比如,給你一組數碼,讓你排序。

不要看書,你會怎麽排?寫個程式驗證下你的想法是否可行。

註意,一定要先想出思路、並把程式寫出來,確保結果正確。

然後,看書,看看別人的演算法是什麽思路。是他的思路好,還是你的思路好?為什麽?

你能不能學會評估一個演算法的好壞?

現在,你是否發現,所謂演算法,其實就是簡單的物理原理(冒泡)、數學知識(輾轉相除法)?

沒錯,過去你學過的物理、數學、化學知識,它們背後的原理,也全都是你忠心耿耿的得力下屬。

那些編程水平很高的程式設計師是怎麽訓練出來的?

它們,就是你的思路。

如你所見,這兩個重點,全都沒有抄程式碼的位置——背程式碼更是愚不可及。還是那句話,我家又不是你家。你背它有什麽意義?

尤其是第二個重點,它完全是在考你過往知識的掌握程度,和電腦本身反而沒太大關系——你中學的物理化學數理邏輯學的踏實不踏實?現在,開花結果的時候到了。

這就是我建議你「買個便宜鐘表拆開揣摩揣摩原理」或者「買點散件焊個收音機」的原因——先學著把數學物理知識套用於現實,然後才能把它套用於電腦虛擬的數碼世界(以前叫「建模」)。這就是演算法的來源。

至於第一個問題,它很好解決。馬上動手就行。

比如說,我們知道Windows有計劃任務;但現在我們不要用它。

任務:

1、寫一個程式,讓它開機啟動(網上有如何設定一個程式開機啟動的教程)

2、查詢你使用的語言的相關教程,看看怎麽取當前時間

3、判斷當前時間是不是你女朋友生日

4、如果是,播放一首歌曲(網上有教程)

5、如果不是,結束程式

除了標註網上有教程的,其它請自己解決。你有這個能力。

解決之後,如果意猶未盡,繼續:

1、女朋友生日那天,不要只提醒一次;而是只要電腦開著,就每隔5分鐘提示一次。

2、找找檔讀寫的範例程式;把程式改為「最多提示十次」,哪怕關機重新開機也不會重復提示。

3、繼續修改為「每年女朋友生日提示十次,然後當年不再提醒;下一年女朋友生日繼續提示十次,以此類推」。

4、考慮女朋友生日是農歷的情況;把生日設定/是否農歷做成可配置項(還記得那個檔讀寫範例嗎?),或許你的室友也想拿它來討好自己女朋友。試試看,能不能推銷出去一份。

5、考慮女朋友生日是農歷閏月,一年出現兩次的情況

6、想辦法測試你的程式是否能表現得如同你所希望的那樣

這些你都能辦到。你絕對有思路。只是你沒有逼過自己而已。

如果連這點嘗試都沒有,你當然看什麽都是天書。

還是那句話:編程從思路到實施,中間隔的比現實中其它的一切都遠,遠到不可避免的要遺失大量資訊。

因此不要去記「圓盤子旋轉多少度」,你必須反過來,自己主動:我要去哪裏?路線已知,我該怎麽指揮一輛車?指揮它的原理是什麽?我該如何用這些基礎設施體現我的意圖?

你,永遠是行為的發起者。你必須站在指揮者的角度看問題。你的兵只是在機械的執行你的一條條指令而已,它們並不知道你的戰略意圖。

因此,不要抄別人的程式碼。甚至,只要書本質素合格,看都不要看它的常式。像一個大頭兵一樣被指揮的團團轉,這怎麽可能教會你編程?

領會思路,然後自己動手指揮,這才能學到東西。

一旦你透過這種更為科學的手段解決了「編程無法入門」問題,你就會知道為什麽我說那些鼓動你抄程式碼的家夥是「Cargo Cults」了——你不會指揮你的兵,所以你跟著電視裏打仗的鏡頭,對著話筒大吼?這樣能學會打仗?

換句話說,【X語言編程】這門課教你「步兵操典」,你本應該透過它學會調兵遣將。結果你不學,當咒語背,混過考試拉倒。

然後,【數據結構與演算法】教你戰役指揮法則,教你在旅團級作戰會議上討論作戰方案——結果你基礎不牢,完全無法理解,不得不吃力的死記硬背別人給下屬打的電話?你能從中學到什麽?

如果你還知道透過模仿這些調兵遣將的口令、把X語言編程這門課補上( 逆向可比按部就班學習難得多,充其量像很多人那樣,四年學了個大一水平、還敢自鳴得意 );這雖然遲了點、而且方法也不對頭, 透過逆向猜測去補課 畢竟事倍尚能功半 ;結果你居然是想繼續用死記硬背來混過戰役指揮考試?你覺得混過考試就是終極目的?

那麽,等後來的作業系統原理、編譯原理這些戰略級別的、必需演算法與數據結構為基礎的課程,你又如何混過考核呢?

將來畢業了,讓你上陣真刀真槍幹時,你能行嗎?

國內電腦系畢業生,起碼90%以上可都幹不了這行;好不容易湊合進去的,其中又有90%會在30歲/35歲遭遇職業危機——幹了好多年,因為當年夾生飯太多一點長進沒有,誰肯白養你?