>>>>>>>>>>>>>>>>>>>>>>>>>>>>
基本结构、输出函数、编译、进制转换
变量、常量
1、程序源文件命名方法
*.c,不可执行,需要gcc翻译为机器指令
2、编写一个程序的过程:
1 edit:vi xxx.c2 complile: gcc -c xxx.c ==> xxx.o3 link: gcc xxx.o ==> a.out
源文件语法为国际标准(ANSI,ISO),可移植
若无错误,则生成可执行程序,机器指令,不可移植
(不同系统,格式不相同,linux:ELF,windows:PE,...COFF,即使在windows下不同版本的驱动不可通用)
linux下安装软件,需要重新编译
3、C的特点
灵活,无需死记硬背,理解比较重要,像打太极,多思考,解决新的无法预料到的问题
4、小程序新鲜一下
1)建个目录
2)hello.c
3)讲解:c程序可以简单到什么程度 main(){},编译,没有消息就是好消息,试下执行./hello.c,执行a.out
4)删除a.out,讲解分开编译 gcc -c hello.c ==> hello.o gcc -o hello hello.o
5)规范写法
1 #include2 int main ()3 { 4 printf ( "hello world\n" );5 return 0; 6 }
6)浏览标准头文件 /usr/include
7)需要重新编译,而不是执行原来的那个可执行程序
8)总结:'#'开头的行为预处理行
#include 用来插入文件,可以插入系统的,也可以插入自己的文件
必须有 int main () 和 {} void main 非标准 (有且只有一个)
潜规则不声明返回类型 则默认int
一个分号为结尾的一个语句,可以一个语句多行或多行为一个语句
\n的意义 \t \r \b \\
return 0的意义 呼应int
注释 //或/* */ 编译时会跳过,注释内字符编码任意,代码字符编码必须为英文
注释的重要性
9)小练习:输出自己的个人信息
10)续行符 '\'
11)演示#include插入自己的文件 新建xxx,输入printf("");
'<>'用来插入系统头文件,插入自己的文件需用'""'
不能插入自己,只能插入别的文件,否则死循环
12)如何调试,先调试第一个错误,不要试图一下将所有的错误改好,后面的错误有可能是前面的错误导致的
5、基本类型
int char float double / long double (有些编译器不支持)
计算机中的数字二进制表示方法,00000000 每位上为权重
负数怎么表示呢? 用权重最大的位拿出来当符号位 0-非负 1-负
原码 -1 ==> 10000001
补码 对于正数来说与原码相同,对于负数来说,补码就是用其绝对值的原码按位取反再加1
一个负数如何算它等于多少?按位取反加1
一个字节表示的数的大小范围 -128~127,-128如何表示10000000,为什么如此表示?因为负数用补码表示,所以按位取反加1后正好是-128
unsigned 符号 有些东西注定为非负,举例:比如搬砖、工作天数
unsigned一个字节表示的数的大小范围为0-255
char型在计算机中的表示方法 一个图案在计算机中只存在一份,每个图案有一个编号,这个编号就是ascll码
'a'-'z' 97-122 'A'-'Z' 65-96 '0'-'9' 49-57 '\r' 13 '\n' 10 '\t' 9 null('\0') 0 ' ' 32
所以字符也可以当成整数来用,如何来计算字符所对应的整数呢?记住基础的字符的值,其他的都可以进行计算
char 0-127 用7位数就可以表示,gb2312字符集-汉字用两个字节扩展
unsigned char 范围0~255
int型在计算机中为一个字长,16位机器中为16位,32位机器中为32位(主流)
表示范围2的负31次方~2的31次方减一 (数字很大,过度到short,如果没人应答,提示主动应答)
short int,用不了int那么大的数则可以用short int,范围2的负15次方~2的15次方减一,unsigned short int 范围0~2的31次方减一
SD卡用一个整数位表示容量,所以最大容量为2G,扩展SD卡则可以更大
long long int非标准类型,8个字节,范围2的负63次方~2的63次方减一
float/double在计算机中的表示方法,float 4字节,32位 double 8字节,64位
float范围 正负3.4乘以10的38次方,double范围 正负1.7乘以10的308次方
符号位 | 阶码 | 尾数 | |
float | 1位 | 8位 | 23位 |
double | 1位 | 11位 | 52位 |
尾数即小数部分,尾数位数越多能表示的精度越高,但是最多也只能精确到2的63位,故小数为近似值
运算符sizeof可以计算每个类型在系统中的字节数
超出类型所能表示的范围,成为溢出,有可能为两个方向的溢出
整数的溢出,导致回绕 小数的溢出,导致无穷,inf(英菲尼迪)
总结:笼统的整数位int,笼统的小数为double
3.5f float类型
5L long int 类型
6.7L long double类型
c语言中没有真假类型,用数值表示真假 非0为真,0('\0',NULL)为假
用真假表示树值 真总为1,假总为0
6、类型提升
char、short ==> int
float ==> double
整数、小数的混合运算,整数会转换为小数
(int和double就像傻逼,不要和一个傻逼争论,它会把你拉到跟他一样层次,然后利用丰富的经验打败你)
7、小程序
printf个数化输出
格式占位符:
%i/%d | int |
%hd | short |
%ld | unsigned int |
%u | int |
%f/%lf | double |
%c | char |
%s | "string" |
%p | address |
%x | 十六进制 |
%o | 八进制 |
%g | float/double去尾零 |
printf的一般形式为printf("格式控制字符串",输出列表),格式控制字符串形式为:[标志][输出最小宽度][.精度][长度]类型。
其中方括号[]中的项为可选项。 各项的意义介绍如下:
1)类型:类型字符用以表示输出数据的类型,其格式符和意义如下表所示:
d 以十进制形式输出带符号整数(正数不输出符号)
o 以八进制形式输出无符号整数(不输出前缀 0)
x,X 以十六进制形式输出无符号整数(不输出前缀 Ox)
u 以十进制形式输出无符号整数
f 以小数形式输出单、双精度实数
e,E 以指数形式输出单、双精度实数
g,G 以%f 或%e 中较短的输出宽度输出单、双精度实数
c 输出单个字符
s 输出字符串
2)标志:标志字符为-、+、#、空格四种,其意义下表所示:
- 结果左对齐,右边填空格
+ 输出符号(正号或负号)
空格 输出值为正时冠以空格,为负时冠以负号
# 对 c,s,d,u类无影响;对 o 类,在输出时加前缀 o;对 x 类,在输出时加前缀 0x;对 e,g,f 类当结果有小数时才给出小数点
3)输出最小宽度:用十进制整数来表示输出的最少位数。 若实际位数多于定义的宽度,则按实际位数输出,若实际位数少于定义的宽度则补以空格或 0。
4)精度:精度格式符以“.”开头,后跟十进制整数。本项的意义是:如果输出数字,则表示小数的位数;如果输出的是字符,则表示输出字符的个数;若实际位数大于所定义的精度数,则截去超过的部分。
5)长度:长度格式符为 h,l 两种,h 表示按短整型量输出,l 表示按长整型量输出。
8、进制转换
倒除法,除到商为0为止
328转换为6进制 ==> 1304
商 余
328/6 54 4
54/6 9 0
9/6 1 3
1/6 0 1
16进制 0-9a-f 表示0-16
作业:练习vi的使用,进制的转换,要求16进制和二进制必须熟练
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
9、标识符的规则
1)不能为关键字
2)由不能以数字打头的字母数字下划线组成
3)尽量做到见名知意
c语言、linu、unix中严格区分大小写
vi的初始化文件 ~/.exrc
查看set命令,进入命令模式然后输入:set all
10、变量的初始化和赋值
垃圾数据:创建的数据,没有初始化,其值不可预知,这样的数据叫做垃圾数据
定义变量时并且指定变量的值,叫做变量的初始化
变量赋值后,会保持后面的值
变量一旦定义,类型在其整个生命周期中不变
区分初始化操作和赋值操作
11、强制类型转换
1 int n;2 n = ( int ) 1.5e30;
sizeof 运算符,不做计算,子分析类型
12、常量
增加可读性,若多次用到,只需在定义出修改即可,便于维护
3.14159; // 字面量
const double PI = 3.14; // 常量
// PI称为常量,const和double位置无关
另一种常量:#define PI 3.14
常量必须初始化,因为常量不允许赋值,称为垃圾数据
13、运算符
算术运算符:
+、-、*、/、%
逻辑运算符:
>、<、!、==、!=、>=、<=、&&、||(短路举例) a>0&&b>0,a>0||b>0
位运算符:
^(异或)、&、|、~、>>、<<
&运算:1 & 1 = 1 1 & 0 = 0 1 & x = x 可以将某位置0,可以检测某位是0还是1
0 & 1 = 0 0 & 0 = 0 0 & x = 0
|运算:1 | 1 = 1 1 | 0 = 1 1 | x = 1 可以将某位置1,可以检测某位是0还是1
0 | 1 = 1 0 | 0 = 0 0 | x = x
^运算:1 ^ 1 = 0 1 ^ 0 = 1 1 ^ x = ~x 可以实现反转,可以自己跟自己异或使自己变成0
0 ^ 1 = 1 0 ^ 0 = 0 0 ^ x = x
异或面试题:
int a = x, b = y;
a = a ^ b;
b = a ^ b;
a = a ^ b;
<<、>> 左移右边空位补0,右移左边空位补符号位
左移k位相当于乘以2的k次方,右移k位详单与除以2的k次方
作用:左移可以取一个32位数的某一个字节
右移可以用多个字节的数按位或运算拼出一个32位数
地址运算符:&、*
条件运算符:a?b:c //三目运算符
a<0?-a:a
,运算符:连接多个表达式称为一个语句
+=、-=、/=...
自增自减运算符:++、--
b = a++ + a++; //是整个语句结束后再++,还是先计算第一个++,之后再运算+
//连续多个++、--没有统一规定,依赖于编译器的实现方式,所以写程序要避免在一行语句中多次改变一个变量的值,否则,其结果无法预料
左值的概念:能放到=左边的值,一般为变量或者运算结果
小数的值在计算机中是近似表示的,所以直接比较两个小数会有误差
比较的方法可以用绝对值小于精确值来确定是否相等,例:fabs ( a - b ) < 1e-5;
运算符的优先级,没必要死记硬背
[ 带符号位扩展 ]
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
流程控制、枚举
14、输入
scanf ( "格式占位符", 地址表 );
格式占位符后面不能加\n,scanf格式占位符中的空白字符表示跳过空白字符,直到遇到非空白字符为止,读取一个字符时,格式占位符前一般都要有个空白字符,用来跳过跳过那些空白字符
输入时可以通过空白字符隔开对应的格式占位符,例如:空格、tab、回车
格式占位符,如果放入了其他非空白字符,要求输入时原样输入
检测scanf是否成功,其返回值带回成功输入的个数
scanf ( "%*3s", str ); //这里的*表示跳过,数字表示跳过的个数
标准C中,scanf不会直接从键盘读数据,键盘输入值放入键盘缓冲区(可以修改),用户敲入回车后,会将输入内容放到输入缓冲区,scanf会从输入缓冲区中取对应格式占位符的数据,如果不匹配,会根据格式占位符跳出或继续读下一个
丢弃多输入的数据:scanf ( "%*[^\n] ); scanf ( "%*c" ); //清除输入缓冲区
^D用来结束一次输入
15、流程控制
默认顺序执行
if/else
switch/case 在块语句内不要定义变量,case后面必须是字面量,不能是变量,而且只能是字符或整数,或者能自动转成整数的字面量
while
do/while 就像营销,第一次不要钱
for 将循环体、条件、步进整合到一起,逻辑比较整齐
goto 智能在同一个函数中跳转,只能从内层跳到外层。尽量不使用
输入一个一到九的整数,根据这个数打印出乘法表
16、枚举类型
1 enum bool 2 {3 true = 1, //枚举常量,可以看做为字面量4 false = 0 //可以指定枚举常量的值,如果没有指定,则从0开始,其后的每一个都是前一个加15 };
typedef的用法
作业:
1、从键盘输入一个整数,输出它的二进制形式 (根据符号位判断比较简单)
2、从键盘输入一个有效日期,输出这个日期是这一年的第几天
3、从键盘输入10个整数,输出最大和最小的数
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
数组
17、数组
标准C和标准C++要求数组下标为常量,有些编译器进行了扩展,但不是标准规定的,可能换个地方就不支持了
一组相同类型的数据连续摆放,每个数组称为元素element,
下标从0开始,依次排序。
定义时,方括号中是元素的个数,是一个非负整数的字面量
使用时,方括号中是下标,从0到元素下表个数减一
遍历数组
数组的初始化
int num[4] = { 1, 2, 3, 4 }; //用大括号初始化,花括号中的数据不能多,可以少,少的全部用数值0填充
数组可以初始化,不可以赋值,可以给数组中的每一个元素赋值
[]运算符,将数组名和下标进行运算。数组名是第一个元素的地址,也称为是整个数组的地址,下标是偏移量
演示数组元素的地址,对比数组地址加运算后的结果,理解地址加减运算的意义,地址运算的数只是一个偏移量
编译器做的转换a[i] ==> *(a+i) ==> *(i+a),那么从[]运算符的原理从而得出i[a]也可以表示第i个元素(这特么也可以啊~)
数组越界
越界访问可以看出,编译器不保证变量按照定义的顺序分配空间
越界赋值可以看出,轻则破坏别的变量的数据,重则导致程序崩溃(段错误)
如何理解数组名,例如:int a[10]; 那么a和&a的值是相等的,这怎么理解呢,首先a可以看做是数组a第一个元素的地址,但a不是个变量,它也代表整个联合数据,
故对数组名取地址,即&a表示对整个数组(联合数据)取地址,所以a和&a的值相等
18、字符串
以'\0'结束的一窜字符,比较字符数组与字符串
字符串字面量存在只读区,由操作系统管理
c语言允许用一个字符串字面量直接初始化一个字符数组,例:char str[] = "hello world";
字符串字面量没有名字,可以直接当成字符数组来用,
例:printf ( "%c", "abcdefg"[2] );
printf ( "%c", "abcdefg" + 3 );
strcpy/strcat/strlen/strchr/strrchr/strstr/strcmp/strncmp
19、二维数组
int x[5]; // x的类型是 int [5];
把所有的多位数组都看成一维数组
20、结构体
1 typedef的使用,typedef可以给类型起别名,甚至可以给数组起别名 2 typedef char A[20]; A str="abcdef"; //A代表char [20] 3 4 结构体中每个组成部分称为这个结构的成员member 5 typedef stuct person { 6 char name [20]; 7 enum gender g; 8 int age; 9 double income;10 } person;11 person a;12 person c = { age:19, g:FEMEAL, ...}; //指定初始化成员名字,语法比较新,老编译器可能不支持,c++也不支持13 person d = c; //用c初始化d14 a = c; //同类的两个结构体可以赋值
结构的对齐与补齐:
边界对齐:一个变量所占的字节(起始)位置一般是这个变量本身所占字节数大小的倍数,这样可以加快访问速度
例:char 1
short 2
int 4
double 8 有的编译器会严格执行标准,大多数编译器超过4会按照4的倍数执行边界对齐
边界补齐:如果定义的是一个结构数组,为了保持数组内的每一个结构元素内部结构一致,所以在每个元素结束后要进行补齐,补齐的规则
是,变量结束地址位置是这个元素中最大元素所占字节的倍数,超过4个字节按4字节计算
为什么要进行对齐、补齐?有些系统一次访问内存的大小为一个字长(一般为32位),如果没有对齐与补齐,变量放置会紊乱,这样系统一次访问内存取出的可能是半个变量,
这样有些系统会直接报总线错误,而即使是优化过的系统,也会因此而使访问内存的速度慢下来
每个成员都从自身长度的倍数摆放,整个结构的长度是最长的成员的长度的倍数,否则进行对齐与补齐,但各个系统的对齐与补齐策略不一定一样,都有自己的对齐补齐方式。
位段:
1 struct mode 2 { 3 unsigned char ur : 1; 4 unsigned char uw : 1; 5 unsigned char ux : 1; 6 unsigned char gr : 1; 7 unsigned char gw : 1; 8 unsigned char gx : 1; 9 unsigned char or : 1;10 unsigned char ow : 1;11 unsigned char ox : 1;12 };
如上定义的结构,每个成员变量只占一位。
每个位段成员只能定义为unsigned int或unsigned char
1 联合体(共用体):2 typedef union IP {3 char i4[4];4 int net4;5 } IP;6 7 IP me;8 me.net = 0x12345678;
12 34 56 78 大端存储
78 56 34 12 小端存储
作业:
1、从键盘输入10个整数存入数组,将其顺序倒过来存于数组,然后输出
2、从键盘输入10个小数,将其从小到大排序后输出
3、从键盘输入10种商品的信息:名称、价格、库存量,分别按照价格从高到低的顺序和按照库存量从小到大的顺序输出商品信息
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
函数
21、函数
具有一定功能的语句集合就是函数,c是一种函数语言。
函数头:返回值类型、函数名、参数表
函数体
函数声明:可以有多次声明
函数定义:必须唯一,只能有一份,单一定义原则
函数调用:从哪调用,回到哪去
函数形参实参
自己写的头文件的使用,多个文件连成一个程序,
做一个比较正规的工程
多文件工程的好处
stdio.h stdlib.h time.h math.h string.h ctype.h
讲解函数是如何工作的,从哪调用回到哪去,画图
函数传参是值传递,c中所有的传递都是值传递
感受值传递经典程序,交换两个数的值
c中形参参数表为空,表示参数的类型和个数不定,无论传什么都不会报错,
如果要明确表示不要参数要写上void
数组作为函数参数来传递的问题
数组作为形参时,需要再加一个形参,用来说明数组的长度
数组不能作为返回值,意义会变成数组第一个元素的地址
形参一定是由实参初始化的,它在调用的时候创建,在返回的时候释放
递推(递归):由大推小
{ 5 ; 当x<=0;
f ( x )
} 2f(x-1)+3; 当x>0;
if控制的内容如果以return结束,else可以省略
22、变量范围
在一定范围内定义的变量称为局部变量,在全局范围定义的变量称为全局变量
声明全局变量:extern char w;
static修饰的全局变量和函数
静态局部变量,第一次到达声明语句时分配空间,以后不再分配空间,所以只有第一次声明时才能初始化,其所占内存空间只有到程序结束后才释放,相比之下比全局变量安全
对于静态局部变量和全局变量,如果没有初始化,系统会自动初始化为数值0
register 请求将变量放到寄存器中,不一定被批准
volatile
23、变长参数 variable arguments
可变长参数在传递时,会进行类型自动提升
char,short ==> int
float ==> double
va_list ap; // ap是一个用来保存变长参数表地址的变量
va_start ( ap, cnt ); // va_start将可变长参数表保存在ap中,cnt是个边界,表示从cnt后都是可变长参数
va_arg ( ap, type ); // va_arg可以将可变长参数表里的参数一个一个取出来
va_end ( ap ); // va_end释放ap变量
作业:
1、写一个函数,输入一个日期,计算这个日期是这一年的第几天
2、写一个函数,输入一个日期,计算这个日期是星期几
3、写一个函数,将一个整数转成一个字符串存到字符数组中
4、写一个函数,对一个数组从小到大排序
5、上次作业第三题,用函数实现
6、汉诺塔 (把n个盘子转换为n-1个盘子的问题[函数])
小练习:
斐波那契数列
24、宏 macro
#ifdef/#ifndef // 宏不能重名,检测重复定义可以用
#undef // 去除宏定义
头文件卫兵
__FILE__
__LINE__
__DATE__
__TIME__
__STDC__ // 不一定有,表示为c程序
1 宏函数(带参的宏)2 #define SWAP(T, x, y ) { T t=x;x=y;y=t; } 3 #define MAX(x,y) x>y?x:y4 #define PI 3.14159265 #define AREA(r) PI*r*r
1 宏函数的问题: 2 1)int a = 5, b = 5; 3 printf ( "%d\n", AREA(a+b) ); 4 5 2)int c = 50, d = 60; 6 printf ( "%d\n", MAX(a,b)+MAX(c,d); 7 8 解决方法: 9 1)#define AREA(r) PI*(r)*(r)10 // 带参的宏要在后面为参数加上括号11 12 2)#define MAX(x,y) (x>y?x:y)13 // 将后面的全部用括号括起来14 15 宏有天然缺陷,有些问题无法避免16 MAX(++a,++b);
1 2 宏函数优点是速度快,没有不存在调用,缺点是,没有类型检查并且容易引起错误 3 4 宏中'#'的作用 5 #define STR(x) puts(#x) //把参数编程对应的字符串 6 STR(hello); // 会直接输出hello 7 8 宏中'##'的作用 9 void welcomstu { printf ( "welcome student\n" ); }10 void welcomtea { printf ( "welcome teacher\n" ); }11 #define wel(who) welcome##who()12 13 wel(stu); // '##'起连接作用
1 2 日期的一系列宏函数3 #define ISLEAP(y) ((y)%4==0&&(y)%100||(y)%400==0)4 #define ISSMALL(m) ((m)==4||(m)==6||(m)==9||(m)==11)5 #define NORMAL(m) (ISSMALL(m)?30:31))6 #define DAYS(y,m) ((m)==2?28+ISLEAP(y):NORMAL(m)7 #define IN(x,head,bottom) ((x)>=(head)&&(x)<=(bottom))8 #define ISVALID(y,m,d) ((y)>1600&&IN((m),1,12)&&IN((d),1,DAY((y),(m))))
作业:
1、写一个宏函数,给一个数组排序,可以由参数控制升序还是降序
2、写一个宏函数,HIBYTE用来取得short类型的高位字节,再用一个宏函数LOWBYTE取得short的低字节
写一个宏函数,HIWORD用来取得一个int的高位两个字节,LOWWORD取一个int的低位的两个字节
3、写一个C程序,运行时将自己的代码打印到屏幕上
25、指针
用来保存地址的变量P叫做指针,也可以说变量P指向某个地址
定义的时候'*'不是运算符,而表示类型
演示若指针类型不对的结果
野指针 指向未知
空指针 指向空
悬空指针 指向一个释放了的变量的地址
用指针访问数组
1 数组作为参数传递时,数组名其实是一个指针 2 char a[100] = { 'a', 'b', 'c' }; 3 const char * p = NULL; // 所指目标为一个常量 4 p = a; // 允许 5 *p = 'w'; // 不允许 6 char * const p; // p本身是一个常量 7 const char * const p; 8 9 char * str;10 scanf ( "%s", str ); // 看运气11 strcpy ( str, "hello" ); // 看运气
指针数组 (处理字符串、排序)
命令行参数
小练习 使用命令行参数
二级指针 实现strtol
void *
对于没有类型的指针,不能直接用*直接取变量,因为不知道什么类型,不确定长度
数组指针
1 int a[5] = { 11, 22, 33, 44, 55 };2 int (* p) [5]; // 数组指针3 p = &x;4 printf ( "%d\n", (*P)[1] );
二位数组等同于指向数组的指针,而不是二级指针
函数指针
函数的大小不能由其类型来确定,所以函数不能做数学运算
函数指针的应用
操作一个数组的各种方法
排序规则
1 int (*x(void (*p) ()) ( char ); // x是一个函数,它的返回值为int (*) ( char ), 参数 void (*) ()2 // 分析方法:x右边是个括号,则x是一个函数,该函数的参数是一个是一个函数指针,然后往左看,返回值为一个指针,该指针指向一个函数,其返回值为int,参数为char
C中,传递结构变量时,一般传递地址,这样可以避免结构复制,提高效率节省空间
structptr.c
指针访问堆区heap
malloc、calloc、realloc、free
内存泄漏 memeory leak
wc-> men | women
作业:
1、写一个函数,用来检查一个字符串是否为数字字符串
2、写一个函数,用来检查一个字符串是否为实数字符串
3、写一个函数,用来把一个字符串用指定的字符作为分隔符分割成若干个子串输出
*4、写一个函数,用来返回字符串中重复出现的最长子串的长度及其开始位置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
I/O
26、I/O
缓冲
刷新缓冲的条件:1、有输入的时候
2、程序结束的时候
3、缓冲区满的时候
4、有换行的时候
5、fflush(stdout)
sscanf/sprintf
27、文件I/O
fscanf/fprintf
C语言已经定义好了三个文件指针stdout/stdin/stderr
fscanf ( stdin, "%d", &n ); ==> scanf ( "%d", &n );
28、格式化输入输出
%[宽度].[精度]d/c/f
%[占位].[长度]s
29、非格式化输入输出
gets/puts (gets会将读到的内容去掉换行,puts会将输出的内容加上换行)
fgets/fputs
getchar/putchar (getchar读到一个字符,返回一个int,读完或者错误返回EOF)
fgetc/fputc <==> getc/putc (getc/putc可能是个宏)
在进行文件操作时,内核会记录当前读写位置
fseek 设置文件读取位置
读写一块内容
fread/fwrite
ungetc 用来向流中退回一个字符
getline 非标C函数,为扩展函数
feof(FILE*) 检测是否超越文件末尾
作业:
1、从键盘输入5个日期,用一个日期数组保存,写一个通用的排序函数,能够根据传入的排序规则对日期进行排序,另写函数用于输出排序后的日期。
排序规则三个:1)按照年从大到小,2)按月从小到大,3)按整个日期从早到晚
2、写一个过滤函数,根据传入的过滤规则对一组整数进行筛选,输出所有符合规则的数据,并返回符合规则的数据的个数
3、写一个函数,用来返回一个文件名字符串,格式为imgXXX.jpg,其中XXX是从000开始的三位整数,到999之后返回000
4、写一个文件复制程序,要求用fread/fwrite
5、写一个文件加解密程序,自己设计加密规则。
6、写一个程序,用来统计一个文件中字母、数字和其他字符各有多少个
7、写一个显示文件内容的程序,要求带行号,每20行暂停,敲回车继续。