K&R学习笔记 第一章

最近上班了,利用上下班的班车时间,我在路上几乎看完了经典名著《C程序设计语言》。看完后的感觉就是:C语言不过如此!短短不到300页内容,就涵盖了C语言的方方面面,(有的内容我也是第一次才注意到)甚至穿插着讲了栈、二叉树、折半查找、快速排序、哈希表等数据结构与算法的内容。代码编写非常精炼,很适合有一定基础的人提高自己的代码水平。值得注意的是,这本书并没有在后面列参考文献或者值得推荐的读物之类的,这种情况在西方学术界是十分罕见的。据我所知,陶哲轩的《实分析》也没有列参考文献,全书内容的选择、每个定理的证明甚至课后题都是作者自己编的,汗颜啊!这本书原创性之高,可见一般。


首先先说第一章。一般的书,第一章只是讲是讲如何写“hello,world”程序。附带介绍一些printf,include之类是做什么的;而这本书的第一章,却给出C语言程序的概貌:利用一些简单的文字处理的例子,涉及了选择、循环控制,数组,甚至子函数等内容。所以一般人都不会把它当一本入门级教材,但是这样也有好处,就是尽早的写出一些稍微复杂一点的程序,而不是示例程序。


书中的练习题也很有意思,其中1.2说,如果在printf中加入了转义字符“\c”会有什么后果?我开始怎么也想不起来“\c”是什么意思,后来才知道是作者给读者开了一个小小的玩笑:\c根本就不是转义字符!而从后面的参考手册可以看出,如果“\”后面的字符不构成转义字符,那么行为是未定义的。


而且书中非常强调程序复用性的。里面的一些例子,比如读取一行字符并返回字符数的函数,在示例程序和习题中反复出现。

唯一令我稍有不满的地方在于K&R里面的大括号风格,而且对于可以省略大括号的地方,几乎全都省略了;据说这样做是因为以前的显示器太小了,一屏幕放不下几行程序所以才写成那样的,不过对于我还是不叫喜欢微软的风格,看起来更加清晰明了,只不过不是特别紧凑而已。

书中还有一些小问题需要注意,这本书成书较早,是不覆盖C99标准的,所以注释只有一种形式,就是/*注释*/。因此课后题1-23的参考答案对于//以后的该行内容还是会正常输出的,需要注意。

习题也是稍微有一些难度的,如果有时间,绝对指得一做:
练习1-13编写一个程序,打印输入中单词长度的直方图。水平方向的直方图比较容易绘制,垂直方向的直方图则要困难些。

我开始也想不明白怎么话直方图,后来看到了答案我才释然了:

#include 

#define MAXHIST 15
#define MAXWORD 11
#define IN		1
#define OUT		0

/*输入:一系列的单词; 输出:单词长度的直方图:长度为1的有几个,长度为2的有几个……长度为10的有几个,并且通过“*”来绘制水平的直方图*/
int main(void)
{
	int c, i, nc, state;
	int len;				//对应水平直方图的*号的个数
	int maxvalue;			//所有符合范围的单词长度的最大值		
	int ovflow;				//超长单词的个数
	int wl[MAXWORD];		//统计从长度为:1~10的单词

	state = OUT;			//是否在一个单词里
	nc = 0;					//一个单词的长度计数
	ovflow = 0;				//单词长度超过限制的单词的个数

	for(i = 0; i < MAXWORD;++i)
		wl[i] = 0;

	while((c = getchar()) != EOF)
	{
		if(c == ' ' || c == '\n' || c == '\t')//如果遇见分隔符
		{
			state = OUT;//不在单词里
			if(nc > 0)//如果此时有单词
			{
				if(nc < MAXWORD)//该单词长度小于预设值:MAXWORD
				{
					++wl[nc];//增加对应的bar
				}
				else
				{
					++ovflow;//ovflow自增,记录了超长的单词个数
				}
				nc = 0;//单词长度归零
			}
		}
		else if(state == OUT)//开始一个新单词的长度计数
		{
			state = IN;
			nc = 1;
		}
		else//增加计数
		{
			++nc;
		}
	}
	maxvalue = 0;
	//统计长度出现频率最高的单词:这个单词的直方图将会有15颗星,其他按比例递减
	for(i = 1; i < MAXWORD;++i)
	{
		if(wl[i] > maxvalue)
		{
			maxvalue = wl[i];
		}
	}

	for(i = 1; i < MAXWORD;++i)
	{
		printf("%5d - %5d : ",i,wl[i]);
		if(wl[i] > 0)//如果有长度为i的单词
		{
			if((len = wl[i] * MAXHIST / maxvalue) <= 0)//如果不足一颗星,则补齐一颗星
			{
				len = 1;
			}
		}
		else//如果长度为i的单词压根没有出现
		{
			len = 0;
		}

		while(len > 0)
		{
			putchar('*');
			--len;
		}
		putchar('\n');
	}
	if(ovflow > 0)//如果有超长的单词,打印超长单词的个数
		printf("there are %d words >= %d\n",ovflow,MAXWORD);

	return 0;
}

虽然答案书不是K&R两位大神写的,但是也值得一看。(话说自学什么的如果没有标准答案是一件多么痛苦的事啊)

你可能感兴趣的:(K&R,学习笔记)