The C Programming Language 的确是一本好书, 第一遍读完了.. 第二遍准备认真做遍习题..
把对自己有所感触的进行记录,算是一次归纳总结吧.
导言
1 .整数除法操作将执行舍位,结果中任何小数部分都会被舍弃.
2.printf("%3d %6d\n",fahr,celsius); %3d代表fahr占三个字宽. %6.2f 按照浮点数打印,至少6个字符宽,小数点后有两位小数.
注:printf函数还支持下列格式说明:%O表示八进制数; %d表示十进制整数 %x表示十六进制数; %c表示字符; %s表示字符串; %%表示百分号%本身. %.0f 强制不打印小数点和小数部分,因此小数部分为0.
3. != 优先级高于 = c = getchar()!= EOF 等价于 c = (getchar()!= EOF)
4. getchar()得到的是字符.
第二章 类型、运算符与表达式
5. ANSI c语言中全部的转义字符序列如下:
\a 响铃符 \\ 反斜杠 \b 回退符 \?问号 \f 换页符 \‘ 单引号 \n 换行符 \“双引号 \r 回车符 \ooo 八进制数 \t横向制表符 \xhh 十六进制数 \v 纵向制表符
’\0‘ 表示值为0的字符,也就是空字符(null),常用’\0‘代替0,以强调某些表达式的字符属性,但其数字值为0.
6. 取模运算符%不能应用于float或者double类型.
7. 算术运算符(+ - * /) > ( 关系运算符 > >= < <=) > (相等运算符: == !=) > 赋值运算符 = 、 运算符(&& > ||)
8. 大小转小写 C + ’a‘ - ’A‘ .
9.位运算符 这个单独一篇日志
第三章 控制流
主要讲了各种排序、类型转换、字符串操作函数
10. P53页 对二的补码所能表示的最大正数只能是2(的字长减一次方)-1 .?
第四章 函数与程序结构
11. 输出特定行(匹配问题)注意代码的写法,函数和printf里面用到的是地址.
12. atof函数 习题中掌握.
13. 用栈实现计算器 习题后自己编程扩充功能. 注意缓冲区.
14. 作用域规则
15. 静态变量 各文件定义的静态变量仅仅对本文件可访问. 用法见P71
16. 寄存器变量.
17. 条件包含
第五章 指针和数组
18. *p+=1 等价于 ++*p 和 (*p)++ 后者需要加括号 不加代表ip地址加一.
19. 函数参数 用 &代表引用.
20. char s[] 等价于 char *s.
21. f(&a[2])与 f(a+2)都表示把起始于a[2]的子数组的地址传递给函数f.
22. 地址算术运算符 函数的写法以及各种定义的写法 P86.
23. char amessage[] = "now is the time";/*定义一个数组*/
char *pmessage = "now is the time"; /*定义一个指针*/
数组: a指向一个固定地址,里面的单值可以修改. 指针:p指向字符串常量,如果试图修改字符串内容,结果是没有定义的.
24. 字符串的各种指针操作函数.
25. 指针数组以及指向指针的指针 注意定义方式 掌握函数和课后习题.
26.void swap(char *v[],int i,int j){ char *temp; temp = v[i]; v[i] = v[j]; v[j] = temp;}
v 的所有元素都是字符指针,并且temp也必须是字符指针,因此temp于v 的任意元素可以相互复制.
27.指针数组的声明: char *lineptr[MAXLINES]
表示lineptr是一个具有MAXLINES个元素的一维数组,其中数据的每个元素是一个指向字符类型对象的指针.也就是说,lineptr[i] 是一个字符指针,而 *lineptr[i] 是该指针指向的第i个文本行的首字符.
eg: void writelines(char *lineptr[],int nlines)
{
while(nlines-- >0)
printf("%s\n",*lineptr++); // *lineptr++ 等价于 *(lineptr++)
}
28. 多维数组 三种数组声明: f(int daytab[2][3]){...} f(int daytab[][13]){...} f(int (*daytab)[13]){...} 第二种说明 行数无关紧要 .
(思考)第三种如何代表二维数组,daytab想当一个地址,后面展开13个项代表一行么? 参见 30.
比较 int (*daytab)[13] 和 int *daytab[13]
[ ]的优先级高于*.
前者 声明形式表明参数是一个指针,它指向具有13个整型元素的一维数组. 后者相当于声明了一个数组,该数组有13个元素,其中每个元素都是一个指向整型对象的指针.一般来说,除数组的第一维(下标)可以不指定大小外,其余各维都必须明确指定大小.
29. 指针数组的一个实例 使用static的好处?
char *moth_name(int n)
{
static char *name[] = {
“1月”,略,“12月”
};
return (n < 1 || n > 12)? name[0] : name[n];
}
30. 对比 int a[10][20] 和 int *b[10]
int a[10] 定义了200个int类型长度存储空间.
int *b[10]仅定义分配了10个指针,并未初始化,初始化必须以显示方式进行.比如静态初始化和通过代码初始化.
假定b每一个元素都指向一个具有20个元素的数组,那么编译器就要为它分配200个int类型的长度的存储空间以及10个指针存储空间.
指针数组优点:数组每一行长度可以不同,b的每一个元素不必都指向一个具有20个元素的向量,某些元素可以指向具有2个元素的向量或者不指任何.
31.命令行参数
main(int argc, char *argv[ ])
程序开始执行时将命令行参数传递给程序.argc用于参数计数,argv用于参数向量.是一个指向字符串数组的指针,其中每一字符串对应一个参数.
eg: echo hello, world (3个参数)
定义:argv[0]值是启动该程序的程序名,argc的值至少为1,如果为1,那么说明程序名后面没有命令行参数.
argv[0]、argv[1]、argv[2]分别为 “echo” “hello,” “world” . 第一个可选参数为argv[1],最后一个可选参数为argv[argc-1],argv[argc]值必须为一个空指针.
32. 效仿unix程序grep实现方法来改写模式查找程序. 模式匹配程序待验证.
33. 指向函数的指针 快速排序的实现 程序见p103页
声明 void qsort(void *lineptr[ ] , int left, int right , int ( *comp )( void *, void *) );
实例 if((nlines = readlines(lineptr,maxlines))>=0){
qsort( ( void **) lineptr, 0 ,nlines-1, ( int ( * )( void * ,void *) )(numeric ? numcmp : strcmp)); //注意写法.
writelines(lineptr,nlines);
return 0;}
分析:qsort第四个参数 int(*comp)(void *,void *) 是一个指向函数的指针,该函数具有两个void *类型的参数 返回值为int.
对比 int (*comp)(void *,void *) 和 int *comp(void *,void *).
前者comp是一个指向函数的指针 *comp代表一个函数 注:函数也有内存地址
后者comp是一个函数,该函数返回一个指向int类型的指针.
34.int *f()和 int (*pf)()
*是前缀运算符,优先级低于(). 前者f 是一个函数,返回一个指向int类型的指针. 后者pf是一个指向函数的指针,该函数返回一个int类型对象.
35. 程序dcl基于声明符的语法编写. 掌握此程序.
第六章 结 构
36. . 的优先级比*高.
37. 结构可以嵌套 struct rect{ struct point pt1; struct point pt2;}
38. 优先级问题
eg struct{
int len;
char *str;
} *p;
(++p)->len 先执行p加1,再对len执行操作.
(p++)->len 先对len执行操作,再对p加1;
*p->str ++ 先读取指针str指向的对象值,再str加1.
*p++ ->str 先读取指针str指向对象值,再对p加1;
39. 指向结构的指针.
40. 自引用结构.
41. 表查找 掌握编程.
第七章 输入输出 待补充
第八章 UNIX系统接口 所有的外设都被看做是文件系统中的文件 待补充
总结: 1. 第二遍看书要完成课后习题 多多动手 掌握课本上的函数和程序.
2. 看书时要多动手 多思考
3. 结合算法:C语言实现 那本书 完成好习题.