我的C语言学习历程

灼眼的超哥 2011-12-04 03:19:23
加精

开始学习C语言

你玩过电脑游戏吗?
你喜欢电脑游戏吗?
电脑游戏是你生活中的一部分吗?
小时候,游戏是一台黑白电视机——现实在手柄的这头,梦境在手柄的那头.
有的游戏改变过人的一生……
长大后,游戏是一枚小小的铜币——现实在摇杆的这头,梦境在摇杆的那头。
现在啊,游戏是一台电脑——现实在鼠标这头,梦境在鼠标那头……
当计算机技术给游戏提供了强有力的支持后,一个陌生而又似曾相识的新奇世界展示在人们面前。
这里有逝去的童年梦想,有心头压抑已久的情感;有疯狂、神秘、也有脑力和技巧的挑战;有轻松获得实实在在的知识,也有用“虚拟”成就一个别样的人生。这不是一个神奇的世界吗?下面,我们就用编游戏来学习C语言吧!
总是从HELLO WORLD开始。
学习编程的第一个程序,一般就是打印一个亲切的词语——“Hello,World!”
……
(后面的内容省略)


透露一下,上面所写的,其实是转载自我的学习机里的“趣味导学”开始部分的内容,我接触C语言也是从这里开始的。
高二时,我有了一部学习机:诺亚舟NP1500,它搭载的系统是嵌入式linux系统,除了学习功能外,还自带了“编程天地”功能,看名字大家应该就能知道,这个是用来编程的。


打开“编程天地”,主菜单里面有个Noah-IDE,之前还不知道IDE是什么,有空百度了一下,原来IDE指的是集成开发环境;

这个Noah-IDE很强大,虽然没有电脑端的那样多的功能,比如:语法高亮、自动缩进、代码格式化。
但是,基本功能还是具备的:可以新建C/C++工程、为工程添加源码文件、支持编辑撤销/重做、跳转到指定行、编译工程时自动生成makefile文件并make之,更想不到的是,还自带了gcc、g++编译器,busybox也有。

闲话不多说,入正题。

之前看“趣味导学”里的示例源码,第一个是HelloWorld!程序,我就照着写了,测试了一下,可以显示Hello World!,之后,上面说要加个getch()函数,按任意键后退出程序,我就改了一下源码,加上头文件:conio.h,printf()后加上getch(),编译之,结果可想而知,无法通过编译,现在我是知道原因的,这个示例源码是适合windows系统的,而学习机是linux系统,与windows系统不同,有些头文件没有。“趣味导学”里面还有两个源码:在屏幕中移动的笑脸,推箱子游戏;两个都试过,由于编译不通过就放弃了。

“编程天地”里还有C语言教程,入门篇、初级篇、中级篇、高级篇,我都看过,折腾很久才会用printf()函数,什么for、while、switch – case在那时都还不会用…


某天,没事就研究学习机,打开“虚拟终端”,我会的命令并不多,用ls命令查看了bin文件夹里的文件,随便选了一个,选到了gzip,加上“—help”参数,看了帮助,英文的,还不理解,上网查了一下,gzip是个压缩软件,能将文件压缩成gz格式的压缩文件,了解了这个后,又发现了tar和bzip2,经过测试,学习机里有这些软件,并且可用。但是,我发现敲命令行太麻烦,如果有个软件能简化操作就好了,于是就有了用C语言编写压缩管理程序的想法,从这个时候开始,“压缩管理”便成为我的第一个正式的C语言项目,也是我学C语言的目的,为什么要学C语言?学C语言干什么?这两个问题也就有了答案。


当时只会基本的函数: 用printf函数显示字符菜单, scanf函数接受按键输入,if语句判断输入内容,system函数调用命令进行操作,打印的字符界面还是黑白的;

由于是上高中,每个月只有放月假才能回去碰电脑,其余时间在学校,C语言代码大部分是用学习机在课余时间写的,两手握着学习机,疯狂的点击屏幕….
有时偶尔去网吧,用电脑敲代码,当然,是代码比较多、需要复制粘贴才去网吧的。

之前在学习机的论坛上见到某位高人的帖子,他的程序能在终端打印彩色字符,在QQ上问了相关人士(学C的),无果,只好去百度,关键词是:“linux 彩色 字符“,终于找到了答案:http://apps.hi.baidu.com/share/detail/24241711
不久,就将它应用了到我的程序,实现了彩色字符界面(如图所示)。



这时的“压缩管理“,功能很少,只支持指定位置里的文件的压缩及解压,想解压/压缩文件,就必须把文件放到指定的文件夹下,然后运行程序,进行操作。按键输入还是有毛病,不能一次性输入多个字符,否则,会跳过菜单显示,例如:主菜单有abcdef六个选项,每个选项都有子菜单,如果我输入ab,那么就会跳过a选项的子菜单的显示,直接执行子菜单中的b选项操作。为了解决这个问题,我用了这么个办法:scanf(“%s”,&str);,if语句判断,只判断str[0]的值,每次输入完后,清空str里的全部内容,编译时有warning。

“压缩管理“完成后,想在论坛上发布,与其他机油分享成果,但又不想让他们轻易获得这个程序(毕竟是个人的劳动成果,有点舍不得),于是就想到了一个办法:添加试用期,正版激活。试用期为7天;
如何获取时间?
毫无疑问,我去了CSDN论坛发帖,问了这个问题,帖子:http://topic.csdn.net/u/20101016/09/13d6c4c1-8099-4fad-bc3f-7d80dc898117.html。

如何知道程序安装时间?
我想, 程序第一次运行时创建一个文件,记录安装时间,以后运行就读取这个文件,要实现这个,需要用到C语言的文件操作类的函数,重新复习了一遍学习机里自带的教程,又在网上搜索了一番,我用了fprintf函数写入数据至文件,fscanf函数读取文件内容。

这时,我有了这么一个想法:
printf和fprintf都是输出数据,用法基本一样,前者是将内容输出至屏幕,后者是输出至文件,fprintf前面的f是指file吗?我想应该是的,那么,是不是有个输出至字符串变量的函数?字符串的名字是string, string+printf = sprint, 会有sprintf函数吗?百度了一下,真的有,而且用法和printf、fprintf的基本一样,这时,我便学会用sprintf函数改变字符串变量的内容了,对以后的字符串处理的帮助很大。

安装时间的保存和读取的功能已经基本实现,那如何知道还剩几天呢?
如何判断是否超过了试用期?
没法,为了这个问题,有空就拿个草稿纸,用笔在上面画程序运行流程图,先干什么,后干什么,判断什么,画着画着,还是觉得直接敲代码好一些;
判断时间,我用了一堆if语句,先判断年份,后判断月份,天,小时,分钟,秒;考虑到1月、3月、5月、7月、8月、10月、12月有31天,4月、6月、9月、11月有30天,而2月在平年有28天,闰年有29天,为了准确度,只好全部判断了。
如果让我现在来做,就不会用这个方法来判断了,具体用什么方法,你懂的!!!

试用期的天数的计算倒是勉强完成了,可是程序的正版激活如何实现?
像电脑上的软件那样用CD-Key激活?
CD-Key如何生成?
为了防止多个人共用一个CD-Key,如何实现一个学习机上只能用专有的CD-Key激活程序?
我是这样想的:
先实现独一无二的产品ID的生成,之后,通过算法算出对应的CD-Key,想激活程序的机油,可将产品ID以回帖方式发给我,我再给他CD-Key,这样就能增加帖子的回复数和人气,但是,这个功能由于本人当时技术水平有限,终究还是没实现,关于这个问题,在论坛上提过:
http://topic.csdn.net/u/20101010/13/51fb341e-05c8-46f3-919c-6b17d3955d80.html
http://topic.csdn.net/u/20101210/09/1b49f8b8-213d-4c40-8b1d-c6e3015d3ea7.html



使用7-zip作为主要利用的程序


“压缩管理”的第二个版本,也就是0.84版(之前的版本是测试版本),加入了很多新功能。那时,由于本人发现了一个强大的压缩软件:7-zip,就把它作为“压缩管理“调用的主要程序,改用命令行版的7-zip,支持解压的格式更多,压缩文件的可自定义参数也较多,包括了系统自带的tar、gzip、bzip2这三个压缩程序的功能;

为了更好的利用7-zip,我还特意研究了7-zip的命令行用法,花费了一些时间,终于实现了”压缩管理“的压缩参数设置功能,具体如图所示:

图中所示的是7z格式的压缩参数,更新后,又添加了几个选项:


Zip格式的压缩参数:


单词大小、词典大小、压缩等级、压缩算法等参数均可自定义;7z和zip这两种格式的压缩参数最多,输入对应字母即可切换参数,源码中用的if语句也非常多,反正是根据自己的逻辑思维写的,怎么想的就用什么样的代码描述。
这些自定义的参数都保存在文件内,参数保存和读取的功能费了比较大的功夫才完成的,实现这个功能,我是这样想的:
首先,需要读取每一行字符串,这个,我在文件操作类的函数中找到了fgets函数,它能读取一行内容,要让它读取每一行内容,我就用了while循环,每读一行就进行处理;那么,如何搜索已读取的字符串是否包含指定的字符串?我用strstr函数,这个strstr函数是通过提问得到的:http://topic.csdn.net/u/20101111/09/927dccb8-0797-4e51-af0e-60dabe14f771.html

用strstr函数查找是否有对应选项,有的话,保存该选项后面的内容,例如:
有一行内容是这样的:“switch = off“,程序搜索时,就用strstr函数搜索该行是否有“switch =“,有的话,判断后面的内容是否正确,考虑到字符串首尾会有空格,在网上找了个去除字符串首尾空格的代码,这个代码是仿照trim函数写的,又考虑到字符要不分大小写的对比,例如switch和SWITCH等同,找到了strcasecmp函数。

调用7-zip进行压缩和解压文件主要是通过system函数实现的,命令行的内容,是通过sprintf函数处理生成的,先声明一个char型的字符串变量command用于存储命令行内容,每个参数都有各自的变量,当这个参数有效时就赋值给相应变量,无效则清空相应变量里的内容,最终用形如sprintf(command,”7z %s %s %s%s %s %s %s”a,b,c,d,e,f,g)的代码生成命令行,用system(command)运行命令行。

当用7-zip解压和压缩文件时,在终端上显示的字符是英文的,于是就有了把它汉化的想法,于是,去看7-zip的源代码,源代码是C++语言编写的,有些地方和C相似,还是能看明白一部分,找到需要汉化的字符,改成中文,黑白太单调,改用了彩色字符,重新编译,这个编译,是在学习机下完成的,先./configure,后make,这是在学习机论坛上得知的linux系统下编译源码的方法,受益匪浅啊。
汉化后的效果:

这个版本的“压缩管理“还是不能添加任意位置的文件压缩成压缩包,但是,却可以解压任意位置的压缩文件;
研究了学习机自带的”资源管理“的关联功能, 所有格式的文件关联信息都保存在resourcemanager.app文件中,为了更好的修改文件内容,我又用C语言编写了一个”关联管理“的程序,可以添加/编辑/删除关联数据,具体见下图,在此不做过多的说明。


为了更好的查看“压缩管理“与支持的压缩文件格式的关联状态,我就把”关联管理“集成到了“压缩管理“中,具体可以看图:

主菜单中直接显示已关联的格式数量,新增的关联管理功能菜单中可以显示具体状态,红色背景的表示为已关联,黄色字体表示未关联。


由于压缩7z和zip格式可以设置压缩密码,为了避免忘记密码,加了密码查询功能,可以查询之前设置的密码;在操作完成时,程序会播放提示音,音频播放的功能,我调用了madplay程序播放mp3格式的音频。



学习机的总内存为64MB,平常的可用内存为5MB左右, 有时调用7zip压缩文件和解压文件时会提示内存不够,为了腾出足够的内存空间供当前程序使用,需要一个SWAP分区来保存暂时没有用的程序的数据,于是就加了SWAP开关功能,SWAP这个东东也是在学习机论坛上得知的。

建立文件关联后,就可以在学习机里的“资源管理”里打开压缩文件,打开方式是调用“压缩管理”,并将文件的绝对路径作为参数传给它,int main(int argc,char *argv[])中的argc和argv就起到作用了,通过判断argc的值得出是否有参数传入,有参数传入就会保存在argv里。
有参数时,会进入文件操作菜单,这个菜单中的“位置”和“名称”内容是变化的,内容过长、过短都会影响字符界面,于是,写了个字符串处理函数,指定字符的长度,低于这个长度则用空格填补,大于这个长度则截取内容,并将末尾3个字符改为”.”。
初始形态是这样的:

可是,7-zip对压缩文件的操作不止这些,花费了一些时间完善该功能的代码,最终实现了如下图所示的效果:

传入的参数是文件的绝对路径, 如何将文件名和位置从绝对路径中分离出来?当时采用的方法是计算绝对路径中的“/”的个数,以最后一个”/”为字符串截断点,把字符串分成两个。



解压压缩文件时,可以进行设置,解压后自动关闭终端,返回“资源管理”;
压缩文件的释放目录可以自定义:当前目录、工作目录、自定义目录。
查看文件列表是使用了“l”参数查看压缩包内的文件,用了输出重定向,把7z打印在屏幕的文件列表重定向至文件。



压缩文件还可以再次进行压缩,考虑到tar格式的存在,就添加了这个功能, 将tar格式的文件压缩成gzip 、bzip2、zip、7z格式,可以看上图,源文件是terminfo.tar,7z和zip都是使用lzma算法压缩。

解压和压缩文件时,少不了文件路径的选择,直接输入字符很麻烦,就这样,我又新增了路径选择功能,字符界面的:

但是,选择的只是“本地磁盘”和“存储卡”中固定的文件目录。
存储卡的空间信息显示有误,后来知道是块大小的问题,我复制的源代码中,块大小直接用4,我改成了用stat结构体中的变量 st_blksize后,才正常计算了总空间大小。

曾经还用过Ncurses库里的函数实现程序启动动画,但是在学习机里不支持彩色字符显示,因为这个,就抛弃了Ncurses。


也记不起上面的图片究竟是不是同一个版本的“压缩管理”的截图,程序的更新比较频繁。

刚开始写C代码时,听说warning可以忽略,只重视error,偶然的机会,在网上发现了gcc编译器的一个参数,-Wall开启所有警告信息,于是乎,用了这个参数,结果,发现我的程序原来有这么多warning…
由于本人喜欢追求完美,想把所有warning消灭,花费了大量时间,百度了N次,最终还是消灭warning了,从此以后,写的代码编译时,都习惯性的给gcc编译器加个-Wall参数,看看程序有什么warning和error。
稍微提醒一下,大部分截图中能看到catchscreen /mnt/xxxxx之类的字符,这个其实是我使用的截图命令,显示界面后,立刻终止程序运行,并使用catchscreen命令截图。

有的人或许能从截图中发现一些细节:
在某些截图中的字符菜单的右下角多出了“[X]返回”、“[返回键]退出”的字符,其实,前期版本的“压缩管理”的操作,需要靠输入字符、然后按回车才能确定操作的,而在我多次努力更新后,这种麻烦的操作已经被我抛弃,改用了直接按相应键进行操作,实现这个功能,主要是用了getch()函数;windows系统下有个getch()函数,可以无回显、无需回车即可接受按键输入的键值,在linux系统下虽然没有,但可以模拟实现getch()函数的功能,我百度了一番,关键词是“linux getch 模拟实现”,网上给的这个函数的源代码,并不完美,不支持方向键,因为会把方向键分解成多个键值,没办法,当时没打算改进它,勉强的先用了。


到了“压缩管理”的0.86版,添加了程序启动画面:

用的是QQ安装目录里的部分图像素材,外加自己PS编辑。


有人可能会问,启动画面的显示是如何实现的?
显示图像,我调用了mgaview程序,这个程序在学习机论坛上有机油发过,我也正好找到了它,可是呢,mgaview显示的图片只是临时的,如果屏幕有变动,这图片也就消失了,为了寻找解决方法,我就开始研究了mgaview的源码,刚开始研究的并不深,只是把部分代码改了一下,它的main函数我改成int view_image(char *filepath,int sec),传入图片文件的路径和显示时长即可显示,想把它编译成一个库,动态库和静态库的编译就是在这个时候开始学会的,我选择了静态库,而静态库其实是多个o文件经过打包而成的,用可用ar命令打包o文件成静态库。
这个mgaview程序,是我的程序实现图形化的一个重要的存在,如果没有它,现在可能还是敲字符版的程序,在后面会提到它的。


0.86版的“压缩管理”,功能已经比较完整,能添加的功能也尽量添加了,例如:IPK的安装、IPK安装包信息的读取、IPK安装包的制作、IPK安装信息的读取等等,IPK是学习机的安装包文件的一中格式,属于压缩文件,既然是压缩文件,我的“压缩管理”怎么能放过呢?
从初始版本到0.86版,累计写了3000+行的代码,用行数表示还是不准确,0.83版(貌似是这个版本)的代码量将近1000行,0.84版时代码重新开始写,直到0.86版,一直在新增、修改代码,0.85版的总源代码的大小是126KB,到了0.86版,光是新增的7z和zip的压缩参数配置功能的源代码就占了50KB左右,其它源代码也经过修改和新增,由于现在只有0.87版的源码,之前的源码都找不到,0.86版之前的代码量也就不知道是多少了。
...全文
33163 34 收藏 388
写回复
388 条回复
亚飞正传 2013年07月31日
赞!mark!!!最近准备学习C语言,楼主不错!
回复 点赞
初学者96号 2013年07月19日
厉害 值得学习
回复 点赞
天天向上嗨 2013年07月16日
实在天人也。。。
回复 点赞
fantasticu 2013年04月25日
兴趣是学习程序的基础。
回复 点赞
Polobom 2013年04月22日
马克一下,楼主是我的学习榜样!!
回复 点赞
pengmyctext 2013年03月16日
楼主真是。。。厉害没说的
回复 点赞
果冻虾仁 2013年02月04日
敢问楼主今年上大学了吗?咋这么牛b的高中生
回复 点赞
「已注销」 2013年01月03日
mark一下,楼主真乃神人也 ,我路过
回复 点赞
tangyang332 2012年07月07日
LZ,你那学习机太强大了吧
回复 点赞
Dreamer_LX灵 2012年07月06日
LZ强大!
回复 点赞
duanrencai 2012年04月27日
虽然我还看不懂,但是我在认真的看,努力的学习,以楼主为榜样
回复 点赞
wsying12 2012年04月03日
牛人...膜拜
回复 点赞
linbounconstraint 2012年04月03日
犀利。。。。。。。。。。。。。。
回复 点赞
weima007 2012年04月01日
终于明白差距是如何产生的啦!
回复 点赞
Runner6587 2012年03月30日
佩服,我都快大二了,而且学得计算机业弄不出来着东西啊!
回复 点赞
墨灵 2012年03月30日
LZ厉害!我现在也在看C语言,可什么都看不懂!
回复 点赞
xiaodao1992 2012年03月28日
嘿嘿!精彩的自学!
回复 点赞
hu7397 2012年03月21日
404??是啥意思?
回复 点赞
wumingxiaotaotao 2012年03月12日
借鉴一下楼主经验,膜拜
回复 点赞
zpaopao12315 2012年03月11日
帅的一塌糊涂啊,我要想你学习,啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊!!!
回复 点赞
发动态
发帖子
非技术区
创建于2007-09-28

4415

社区成员

5.8w+

社区内容

C/C++ 非技术区
社区公告
暂无公告