如果读起来感觉很吃力,那我推荐你读一读书,书上的例子比较多,看着能轻松一点,老鸟看起来应该不是很难,作为复习一下,应该还不错,5min可以看完。
C语言进阶
五、 库函数
1、 返回整数的getchar函数
尽量使用系统头文件
1、返回整数的getchar函数
char c;
while((c=getchar())!=EOF)
putchar(c);
这个存在三种可能:
1)某些合法的输入字符在被”截断“后使得c的取值与EOF相同,程序将在文件复制的中途终止。
2)c取不到EOF这个值,程序将陷入死循环。
3) 因为巧合可以工作。
2、更新顺序文件
访问文件时,不能同时进行读写操作,如果想要同时进行,必须插入fseek函数调用。
类似:
read
seek
write
seek
第二次的seek改变文件状态,使得下一次文件可以正常读写。
3、缓冲输出与内存分配
setbuf(stdout,buf);可以将输出暂存起来,然后大块写入
使用时,为了避免错误,可以用两种方法:
1)将缓冲区成为静态数组,例如 static char buf[BUFSIZE];setbuf(stdout,buf);
2)动态分配缓冲区,例如:setbuf(stdout,malloc(BUFSIZE));
4、 使用errno检测错误
正确使用errno的方式
/*调用库函数*/
if(返回的错误值)
检查 errno;
5、 库函数signal
signal(signal type,handler function);
捕获异步事件的一种方式,信号非常复杂,而且具有一些从本质上而言不可移植的特性,我们要让signal处理函数尽可能简单。
例如: 打印一条错误消息,然后直接exit退出程序。
六、 预处理器
预处理器的重要性可以由两个主要的原因说明:
1)预处理器可以实现只需要改动一处数值,便可将用到该值的地方的所以地方都修改,将这个数定义为显式常量。
2)没有函数调用带来的系统开销
1、 不能忽视宏定义中的空格
1、不能忽视宏定义中的空格
例如:
#define f (x) ((x)-1)
f(x) 代表 ((x)-1) 错误
f 代表 (x) ((x)-1) 正确
#define f(x) ((x)-1)
这样才能实现 f(x) 代表 ((x)-1)
2、 宏并不是函数
宏定义中最好把每个参数都用括号括起来,来避免错误。
例如
#define abs(x) x>0?x:-x
abs(a)+1 会得到 a>0 ? a : -a+1
但我们的本意不是这样。
如果宏实现比较复杂,那么尽量使用函数来实现。
宏的展开可能会产生庞大的展开式。
3、 宏并不是语句
这里的例子有点晦涩,不知如何表达,只是记住宏并不能直接当作语句去使用,并且要注意分号即可。
4、 宏并不是类型定义
#define FOOTYPE struct foo
FOOTYPE a;
FOOTYPE b,c;
这样我们只需要修改一行代码就可以改变abc的类型,但是我们并不推荐如此使用,最好还是使用类型定义
typedef struct foo FOOTYPE;