此博客作为本人读书记录,写下书本后面的课后习题,也欢迎大家交流
第一章课后问题
1.C是一种自由形式的语言,也就是说并没有规则规定它的外观究竟应该怎样。但本章的例子程序遵循了一定的空白使用规则。你对此有何想法?
C是一种自由形式的语言,也就是说并没有规则规定什么地方可以书写语句,一行中可以出现多少语句,什么地方应该留下空白以及应该出现多少空白等(预处理指令是个例外)。唯一的规则就是相邻的标记之间必须出现一至多个空白字符(或注释),不然它们可能被解释为单个标记,因此,下列语句是等价的。
y=x+1;
y = x + 1;
y = x
+
1;
至于下面这组语句,前三条是等价的,但是第四条语句却是非法的;
int
x;
int x;
int/*comment*/x;
intx;
这种代码书写的极度自由有利有弊。很快你就就将听到一些关于这个话题的肥皂盒哲学。
肥皂盒哲学:有一家日本最大的化妆品公司,收到了用户的投诉.用户抱怨买来的肥皂盒是空的。这家公司为了防止再发生这样的事故,很辛苦地发明了一台X光检查器,能够透视每一个出货的肥皂盒。同样的事故,发生在一家小公司。他们的解决方法是买一台强力的工业电扇,对着肥皂盒猛吹,被吹走的就是空肥皂盒。其实也就是简单原则,keep it simple,stupid.
2.把声明(如函数原型的声明)放在头文件中,并在需要时用#include指令把它们包含与源文件中,这样做法有什么好处?
如果你有一些声明需要用于几个不同的源文件,你可以在头文件中编写这些声明,然后用#include指令把这个文件包含到需要使用这些声明的源文件中,这样,你就只需要这些声明的一份拷贝,用不着在许多不同的地方进行复制,避免了在维护这些代码时出现错误的可能性,也有利于代码的清晰度与复用率。
3.使用#define指令给字面值常量取名有什么好处?
用#define把名字MAX_COLS定义为20,当这个名字以后出现在源文件的任何地方时,它会被替换为定义的值。由于它们被定义为字面值常量,所以这些名字不能出现在于有些普通变量可以出现的地方(比如赋值符的左边)。这些名字一般都大写,用于提醒它们并非普通的变量。#define指令和其他语言中符号常量的作用类似,其出发点也想通,如果以后你觉得20列不够,你可以简单的修改MAX_COLS的定义,这样你就用不着在正哥程序中到处寻找兵修改所有表示列范围的20,你有可能漏掉一个,也可能把并非用于表示列范围的20也修改了。
4.依次打印一个十进制整数、字符串和浮点值,你应该在printf函数中分别使用什么格式代码?试编一例,让这些打印值以空格分隔,并在输出行的末尾添加一个换行符。
十进制整数使用 %d , 字符串使用 %s ,浮点值使用 %f 。
int number = 10;
char c_char[] = "abc";
float f_float = 1.126;
printf("%d %s %f\n", number,c_char,f_float);
5.编写一条scanf语句,它需要读取两个整数,分别保存于quantity和price变量,然后再读取一个字符串,保存在一个名叫department的字符数组中。
int quantity, price;
char department[100];
scanf("%d %d %s", &quantity, &price, &department);
6.C语言并不执行数组下标的有效性检查。你觉得为什么这个明显的安全手段会从语言中省略?
C语言这种不加检查数组下标的行为有好处也有坏处。好处是不需要浪费时间对有些已知是正确的数组下标进行检查。坏处是这样做将使得将无效的下标引用无法被检测出来。
从技术上说,让编译器准确的检查下标值时候有效是做得到的,但这样做将带来极大的额外负担。有些后期的编译器,如Borland C++ 5.0,把下标检查作为一种调试工具,你可以选择是否启用它。
7.本章描述的rearrange程序包含下面的语句
strncpy( output + output_col,
input + columns[col], nchars );
strcpy函数只接受两个参数,所以它实际上所复制的字符数由第2个参数指定。在本程序中,如果用strcpy函数取代strncpy函数会出现什么结果?
在本程序中,用strcpy函数取代strncpy后并没有异常错误,程序运行正常。但是这仍然是一个不安全的操作。
函数原型:extern char *strcpy(char *dest,char *src)
strcpy是从src地址开始,一直到NULL,也就是“\0”结束的字符串赋值到以dest地址开始的空间。strcpy函数并不对src字符串与dest字符串空间进行判断buffer大小,如果dest的空间过小,将会引起buffer overflow(缓冲区溢出)。
函数原型:char * strncpy(char *dest, char *src, size_tn);
strncpy函数是strcpy函数的安全版,第三个参数可指定拷贝范围的大小,并不一定到NULL结束,使用strncpy可以有效避免buffer overflow的出现
8.rearrange程序包含下面的语句
while( gets( input ) != NULL ) {
你认为这段代码可能会出现什么问题?
由于没有对输入的字符串进行规定,输入的字符串很可能超过input的大小,从而导致overflow。
第一章课后练习
1.“Hello world!”程序常常是C编程新手所编写的第1个程序。它在标准输出中打印Hello world!,并在后面添加一个换行符。当你希望摸索出如何在自己的系统中运行C编译器时,这个小程序往往是一个很好的测试例。
非常简单
#include <stdio.h>
void main()
{
printf("Hello Word!\n");
return ;
}
2.编写一个程序,从标准输入读取几行输入。每行输入都要打印到标准输出上,前面要加上行号。在编写这个程序时要试图让程序能够处理的输入行的长度没有限制。
简单理解题意,输入行的长度没有限制,应该指一个while循环无限循环输入字符串,代码如下。
#include "stdafx.h"
void main()
{
char ar[1000];
int i = 0;
while(gets(ar)!=NULL)
{
printf("第%d行:%s\n",i,ar);
i++;
}
return ;
}