第一章: C语言概述
- 背景:
- 人机交互单调
- 用汇编写unix
- 16k内存
- 目的:
- 替代汇编写unix,解决调试修改难和无法移植的问题
- 特点:
- 操作硬件,与unix系统集成
- 语言小巧,编译器易于实现
- 标准库功能强大
- 类型和运算符丰富,表达力强
- 很早形成标准,按统一规格开发的不同机型和OS版本的编译器,使C具备良好的可移植性
第二章: C语言基本概念
-
编译过程
- 预处理preprocessor:处理#开头的指令
- 编译compiler:将源代码翻译成目标代码
- 链接linker:将多个目标代码组装成一个可执行文件
-
整数除法:C语言舍掉小数部分
- 向下取整:5 / 10 = 0
- 向上取整:(5 + 9) / 10 = 1。利用(操作数1 + 操作数2 - 1) / 操作数2 来实现向上取整,是一种编程技巧。
-
初始化(initialize)
- 编译器不会对所有变量自动赋初值。定义时赋初值,是一个好习惯。
- 使用没有初始化(uninitialized)的变量是严重错误,程序可能崩溃。
-
在任何需要数值的地方都可使用同类型的表达式
-
预处理指令无分号,要求独立成行;其他语句有分号,可写到一行
-
注释
- 早期编译器会删除注释,a
/**/b = 1变成ab=1,相当于给ab赋值; - 现代编译器根据C标准用一个空格替换注释,a
/**/b = 1变成ab=1,就会报错。
- 早期编译器会删除注释,a
-
多项式求值:3x^5+2x^4-5x^3-x^2+7x^1-6
- 常规方法: 3 * x * x * x * x * x + 2 * x * x * x * x - 5 * x * x * x - x * x + 7 * x - 6,执行14次乘法运算;
- Homer方法: ((((3 * x + 2) * x - 5 ) * x -1) * x + 7) * x - 6,执行5次乘法运算,效率大幅提升;
第三章:格式化输入/输出
- 转换说明 conversion specification
- 也叫占位符,%开头,指示将位模式数值转换成何种形式的字符串
- %5.3d显示40的时候,是
| 040| \"将显示双引号%%显示%- %i允许scanf以八进制(0开头)、十进制、十六进制(0x 0X开头)输入整数
- scanf:
工作流程
- 到格式串里拿占位符,到输入流里提取子串
- 提取第一个非空白字符放入子串,直到不能组成相应的数字为止;
- 匹配:int float string匹配规则不同
- 匹配成功:(1)将子串转成值,保存到目标单元。(2)取下一个子串。
- 匹配失败:结束并返回匹配成功的变量个数
- 格式串里的其他字符
- 空白字符:如
scanf("%d %d", &i, &j);由于scanf读取第二个数字输入时跳过空白字符,在格式串中出现一个或多个空白字符对scanf无影响,在键盘输入的时候可以输入0个空格,也可以输入任意多个空格。 - 其他字符:如
scanf("%d,%d", &i, &j);在两个%d之间设置输入分隔符逗号。从输入流里,读取第一个数后,碰到空格或者其他字符后结束读取,并将这个字符放回缓冲区原处,作为读取第二个数时的第一个字符。读第二个数字的时候,从输入流里拿出“放回原处”的字符,这个字符要和分隔符,比较,若两者不同,则scanf退出,若两者相同,则将此分隔符丢弃(不要读入第二个数字的字串里),继续向下读。
- 空白字符:如
注意事项
- 变量前漏掉&,程序可能崩溃
- 专业程序员一般不用scanf读数据,采用字符格式读数据,再转换成数值形式
举例:
scanf("%d%f", &i, &f);输入2-3.1e3
- scanf拿出%d:到输入流跳过前2个空格,拿到
2,继续读-,判断2-不是整数,子串确定为2,转成数值写到&i。然后记录-的位置,返回值+1; - scanf拿出%f:从
-开始,float能用-开头,放入子串;接着,3.1e3经过同样判断并放入子串,读到空格判断不能作为float的一部分而停止,将字串-3.1e3转成数值并写到&f。然后再记录空格的位置,返回值+1; - scanf格式串处理结束,不再继续从输入流拿子串,将写入成功的变量个数返回,scanf结束。
问与答
- 转换说明%i和%d有什么区别?
- 答:在scanf中,%d——十进制,%i——可处理十进制、八进制(0开头)、十六进制(0x 0X开头)三种输入。
- 如何显示
%?
- 答:
%%
\t到底跳多远?
- 答:由操作系统决定,或4个空格,或8个空格,和C无关。
- 如果要求读入一个数,而用户录入了非数值的输入,scanf如何处理?
- 答:比如
scanf("%d",&i);(1)如果输入23foo,scanf扫描到f后停止,将子串"23"转换成数值保存到&i处;(2)如果输入foo23,scanf扫描到f后停止,子串为空,无法给&i赋值。
- scanf如何把字符“放回原处”并在以后再次读取?
- 答:键盘输入流在缓冲区里,scanf读到一个不符合当前占位符的输入时,将该字符放回缓冲区;scanf处理下一个占位符时,从这个“放回原处”的字符处开始读取。
- 用户在两个数之间输入了逗号,scanf如何处理?
- 答:比如
scanf("%d%d", &i, &j);输入1,2, 将1读到&i,将逗号“放回原处”,读第二个数的时候,从逗号开始读,发现整数不能以逗号开头,读入错误scanf结束。
- 以下格式串是否等价?
scanf("%d-%d, &i, &j);只适应两种输入方式:scanf("%d -%d, &i, &j);`可适应四种输入方式: