【参赛】自学编程所遇到的困难与体会
本帖最后由 sarnaga 于 2016-9-13 13:44 编辑和成千上万的人一样,我学习编程的动力来自游戏。
游戏很好玩,它们是怎么被制造出来的?
是计算机程序!
于是懵懵懂懂的开始学习编程。
身边没有人懂,也没有老师教,全都是依靠自学。
弯路走得太多,现在回过头来,说一句心灵鸡汤的话:”苦难成了宝贵经历。“
走弯路当然消耗了很多时间,但同时也获得了许多学院派不曾有的心得体会。
1. 起始阶段
听别人说c语言万能,什么都能做,就跟玩游戏选职业一样,我选最厉害的!
一头栽入了C语言的大坑,可是看教材看不懂啊。
为什么有main()?为什么有printf(),我家里没有打印机啊。
什么又叫集成开发环境?为什么要建立解决方案,建立项目?
诸如此类的疑问太多太多,教材上根本没说,或者一笔带过。
自己给自己打气:“没事,练字的不也要先临摹字帖。我就先依瓢画葫芦!“
一边在网络上查询资料,一边强迫自己不要去想太多,就当自己是个复印机。
磕磕碰碰得把教材上的例题输入,运行。
大概两个月吧,某天我在运行程序的时候,有一种醍醐灌顶的感觉,C语言原来是这样的!
这个时候,我可以说,自己C语言入门了。
2.迷茫阶段
C语言是入门了,教材上的各种例题也能自己编写并运行成功。
可是我陷入更深的迷茫了。
以前的那些疑问并没有解决,反而越积越多。
我仍然不知道为什么要有main(),为什么我仍然编写不出printf,scanf这种类似的函数?
辛苦几个月,还是在“黑框框”做一些加减乘除?
或者用循环输出几个“ *
**
***”
这些东西有什么用呢?
不是说C语言万能吗?什么都能做吗?我想编写的游戏呢?
同样,教材上没有任何解答。
最悲哀的是,我连去哪里找答案都不知道。
现在回头过来看,这个时期估计80%的自学者会迷茫到放弃。
3.突破迷障阶段
不知道其他的前辈,先行者是如何突破迷障的。
我个人是在无意中,看了中科大杨力祥老师<c++程序设计>后突破的。
之所以会看这个视频,也是因为找不到解决疑惑的办法,又跑去自学C++,想着也许C++能给我解答?
我既不是中科大的学生,也不认识杨老师,但这里非常感谢他。
他恰好在教学视频中说:
“为什么你们学C语言的时候,打个printf就能在显示器上输出,不用printf行不行?”
“最初的时候,是没有C语言的,肯定也是没有printf,那个时候的程序员怎么输出?"
"操作系统怎么来的?是先有操作系统,还是先有几十行的小程序?”
“早期C++也是先翻译成了C语言,然后再弄成汇编,到机器码执行。”
这些很平常的话,当时对我来说,无异于灵犀一闪!醍醐灌顶!
那些日子在网络上查询疑惑,而获得的各种零散资料,瞬间被整合起来!
当时在书房里兴奋的大吼:“我明白了!我明白了!”
4.进阶学习阶段
经过突破迷障,我不光解决了以前的很多疑惑,最重要的是终于知道去哪里寻找答案。
这里给自学者建议,不要依赖网络查询资料,因为它们是零散的,不成体系的。
如果你和我一样在学习了某种语言后陷入迷茫,觉得自己想做的项目什么都做不出来,那么去学习《计算机系统概论》,《深入理解计算机系统》。
不需要把书本学得无比精通,而是在你的脑海里建立知识体系,知识层次。
清晰的明白,当前正在学习的知识处于哪一个体系层次,它的周围有什么?
如果想做某一个具体项目,比如我想做游戏,需要填补哪些层次?
同样,个人认为这个时候才适合去补充《数据结构》,《操作系统原理》等等基础理论。
这样无论你学习的再多,也不会混淆,更不会出现“学了能做什么”的疑惑。
5.自学者最容易碰到的疑惑举例
大部分讲c语言或者c++语言的书籍,一上来都是直接编写代码,诸如经典“hello,world”程序。
这对初学者,尤其是自学者造成了不小的困难,初学编程的时候,简直一头雾水,拿着教材都不知道从哪里入手。
或者说好不容易把代码输入进去,但在运行过程中,遇到了n个教材上没提及到的问题。
之所以会这样,是因为前面还缺失了相当一部分知识。
这并非书籍的编写者水平不够,而是这些知识和语言本身没有多大联系,如果太花笔墨,那就偏离了重点。
但要在计算机上实际的运行代码,这些前置知识又必不可少。
我就按照自己理解,来说说代码是怎么运行的,编译器及链接器又是什么。
为什么现代的程序编写方式,会是今天这样独特的“工作机制”。
①,代码是怎么运行的
我们用c语言,c++语言,或者python,java等等来编写代码,首先都要编写源文件。
这些源文件,其本质上不过是一堆的文本文件。
比如用windows操作系统上的记事本软件,就能打开这些代码源文件,清楚看见它们的内容。
为什么源文件是文本文件呢?
那是为了方便人类自己,可以直接观看。
而计算机的cpu,仅能识别机器码。
既然如此,为什么文本文件还能变成程序运行呢?
现代的代码运行流程如图:
源代码(文本文件)经过编译器,被翻译成目标代码(obj),再经过链接器被整合成机器码的可执行程序(exe)。
无论什么语言,最后都要变成机器码,计算机的cpu才能识别并执行。
②,编译器的概念
编译器,虽然有“器”字,但不是真正的实物,而是由其他人开发完成的程序。
这里似乎出现了悖论,源代码要通过编译器才能变成可执行程序,编译器也是可执行程序,那么最初的编译器怎么来的?
而且为什么要通过这种“绕远”的方式来处理呢?为什么不“一步到位”呢?
历史上早期的时候,是没有编译器和链接器的,程序员都是直接编写机器码,“一步到位”的让cpu执行。
但是cpu能识别的机器码太过复杂,那个年代的程序员,可以说都是天才,门槛太高。
于是有人就想出办法,让程序的编写发生了改变:
第一步,用约定好的简写记号编写代码,不再直接编写机器码。
第二步,让精通机器码的程序员来手工的进行翻译工作,把简写记号翻译成机器码。
通过这种改变,程序编写有了分工合作的雏形,可以让一批人专门进行翻译工作,并且节省了第一步书写代码的时间。
天才们很快就发现,翻译工作是相当机械枯燥的,因为约定好的简写记号与机器码,总是有特定的对应关系。
为什么不让计算机来做这种机械枯燥的事情呢?这本来就是它的强项。
于是天才们开发出了一款程序,专门来进行“简写记号”——“机器码”的翻译工作,这个程序就是最初的编译器,它是用机器码写的。
编译器的出现,让程序的编写发生了又一次改变,程序员都使用简写记号编程了(即上面的第一步),没有程序员再手工做第二个步骤,都让编译器自动完成吧。
这个时期的流程图:
可以说,编译器是个伟大的发明,表面上看上去“绕远”的方式,却把程序员从纯手工劳动解放了出来。
为了区分直接编写机器码的时代,把这种简写记号的编写方式称为“源代码”,而早期的简写记号发展到后来,就是“汇编语言”。
6. 抓核心本质,抛开表面现象
计算机编程的基本原理与方法,几十年来几乎没有改变,我们一定要抛开表面现象,去抓住核心本质。
比如游戏角色
我们给它修改一下:
和学生管理系统有本质区别么?答案是没有。
类似创造一个角色的数据如下:
struct role
{
unsigned int command-skill;
unsigned int force;
unsigned int intelligence;
}
为什么要用int类型呢?因为我们设定——属性不会出现小数。
同理为什么要用unsigned呢?因为我们设定——属性不会出现负数。
必记住一切设定来源于需求。
再看下某游戏的战斗场面:
不要被花哨的图形给欺骗了,这些都是表面现象,核心本质在于数值计算。
hp是数值,damage还是数值。
类似的代码如下:
int hp = damage - defense;
if (hp <0)
printf("you dead\n");
和我们在“黑框框”里玩的加减乘除有本质区别么?答案是没有。
你完全可以把伤害公式做的很复杂,比如乘上某个系数,再按照某个百分比进行减伤计算。
归根到底,无论图形,音乐,文档还是其他什么东西(表象),计算机只能保存并运行二进制数值(本质)。
谢谢大大分享心得! 呆鸭 发表于 2016-9-12 16:07
谢谢大大分享心得!
不敢称大大,我还在苦逼自学呢。
连拿得出手的作品都没有。 膜拜,加油 学习了。
讲的很好,透过现象看本质。楼主已经在往高层次发展了 写的很棒啊 支持。 {:10_245:}汗颜 应该多向楼主学习 哈哈,醍醐灌顶 {:10_256:} 浅显易懂{:7_123:} 谢谢,受教了 什时候 醍醐也能灌一下我的顶
快点儿让我明白一下哇 原来是这样!
正在学习python呢 用这个打基础怎么样? make 自学的初学者,有时候是真的觉得晕{:10_266:} {:5_95:}继续继续! 这个对我真的是有很大的启发
页:
[1]