目录
格式化的输入输出
printf
flags
width或prec
hIL修饰符
格式化控制符
scanf
[flag]type
printf和scanf的返回值
13.1.2 文件输入输出
file
fopen的参数
13.1.3 二进制文件
文本 vs 二进制
程序为什么需要文件
二进制读写(与文本文件读写相比较)
为什么nitems?
在文件中定位(fseek,ftell)
可移植性
格式化的输入输出
printf:%[flags][width][.reec][hiL]type
scanf: %[flags]type
printf
flags
printf:%[flags][width][.reec][hiL]type
scanf: %[flags]type
flags
#includeint main() { printf("%9dn",123); printf("%-9dn",123); return 0; }
两种输出结果,都是空位加上数字一共九位,区别是加-号是左对齐,没加是右对齐。加号不代表右对齐,只是加上一个符号。如果加0,空位用0补齐
width或prec
printf("%9.2fn",123.0); 输出为: (四空位)123.00 printf("%*dn",6,123); 输出为: (三空位)123
9.2f表示一共9位,小数点后两位,不足补0。
%*d表示,6用来代替*,让整个字符串占据6位,因此可以用一个参数来代替原来的固定字符
hIL修饰符
单个字节表示输出一个char大小的整数或字符
格式化控制符
#includeint main() { int num; printf("%hhd%nn",(char)12345,&num); printf("%dn",num); return 0; } 输出57,2,原因是12345转16进制,再限制其为单字节 %n的作用是当printf在其之前打印了多少个字符,就把个数传给一个指针
scanf
[flag]type
有关* int main() { int num; //*d,表示跳过一个整数,此时输入 123 456 scanf("%*d %d",&num); printf("%dn",num); return 0; } 得到输出 456
有关[...] //$GPRMC,004319.00,A,3016.98468,N, 12006.39211,E,0.047.,130909.,D*79 这些是GPS产生的数据 scanf("%*[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,]", sTime,sAV,sLati,&sNW,sLong,&sEW,sSpeed,sAngle,sDate); %*[^,]表示跳过到逗号之前所有数据,也就是跳过($GPRMC,)内容
printf和scanf的返回值
这两个函数是有返回值的,且返回值有意义
scanf返回值为读入项目数,printf返回值为输出字符数
在要求严格的程序中,应该判断每次调用scanf或printf的返回值,来了解是否有程序问题
#includeint main() { int num; int i1 = scanf("%i",&num); int i2 = printf("%dn",num); printf("%d:%dn",i1,i2); return 0; } 输入:1234 输出:1234 1:5(1代表读入了一个变量num,输出了1234外加一个n,共5个字符)
13.1.2 文件输入输出
>和<做重定向,可以做文件读写
命令行中输入 > 12.out(12是文件名)
12345
此时什么都没有显示
当打开12.out文件,此时可以读到12345 1:6的结果
命令行中输入 > 12.in
12345
按ctrl+d结束输入,打开文件只有12345
再输入 < 12.in
这表示用12345做输入,此时可以看到1:6
file
FILE* fopen(const char* resitrict path,const char* restrict mode);
int fclose(FILE* stream);
fscanf(FILE*,...)//文件读入
fprintf(FILE*,...)//文件写出
标准代码:
FILE* fp = fopen("filename","r");//r表示read,只读。没打开会返回NULL
if(fp)//判断是不是NULL
{
fscanf(fp,...);
fclose(fp);
}else{
//提示错误
}
>和<做重定向,可以做文件读写
FILE* fopen(const char* resitrict path,const char* restrict mode);
int fclose(FILE* stream);
fscanf(FILE*,...)//文件读入
fprintf(FILE*,...)//文件写出
标准代码: FILE* fp = fopen("filename","r");//r表示read,只读。没打开会返回NULL if(fp)//判断是不是NULL { fscanf(fp,...); fclose(fp); }else{ //提示错误 }
eg:
#includeint main() { FILE *fp = fopen("12.in","r"); if( fp ){ int num; fscanf(fp,"%d",&num); printf("%dn",num); fclose(fp); }else{ printf("无法打开文件!n"); } return 0; }
fopen的参数
- r 只读
- r+ 读写,从文件头开始
- w 只写,不存在则新建,存在则清空
- w+ 读写,不存在则新建,存在则清空
- a 添加,不存在则新建,存在则从文件尾开始
- ..x 新建,若存在则不能打开
13.1.3 二进制文件
- 所有的文件,最终都要转化为二进制之后计算机才能执行
- 但二进制文件需要专门的程序来读写
- 文本文件是最简单的方式可以读写的文件,其输入输出是格式化,可能经过转码
- more、tail(打开文件)
- cat(打开文件)
- vi(编辑文件)
文本 vs 二进制
- 所有的文件,最终都要转化为二进制之后计算机才能执行
- 但二进制文件需要专门的程序来读写
- 文本文件是最简单的方式可以读写的文件,其输入输出是格式化,可能经过转码
- more、tail(打开文件)
- cat(打开文件)
- vi(编辑文件)
文本 vs 二进制
unix喜欢用文本文件来做数据存储和程序配置,而windwos(DOS)喜欢用二进制文件
原因是dos是一些爱好者开发,面向个人电脑的,而且PC刚开始时能力有限,二进制更接近底层。交互式终端的出现使得人们喜欢用文本和计算机交互,unix的shell在最开始提供了一些读写文本的小程序,因此文本和二进制是两种群体产生的不同习惯
文本的优势是方便人类读写,且可以跨平台;缺点是程序的输入输出要经过格式化,算力开销大。
二进制的优点是程序读写快;而缺点是人类读写困难,且不跨平台(如int在不同终端大小不一)
程序为什么需要文件
- 配置信息:unix用文本,windows用注册表(全部存在一个巨大二进制文件里)
- 数据:稍微大点的数据都存放在数据库里
- 媒体:图片、声音等,这种只能是二进制文件。但现在不用将一个媒体通过读写二进制文件来创建,而改用第三方库。
二进制读写(与文本文件读写相比较)
size_t fread(void *restrict ptr,size_t size, size_t nitems, FILE *restrict stream);
size_t fwrite(void *restrict ptr, size_t size.size_t nitems.FILE *restrict stream);
size_t fread(void *restrict ptr,size_t size, size_t nitems, FILE *restrict stream);
size_t fwrite(void *restrict ptr, size_t size.size_t nitems.FILE *restrict stream);
读写的数据都是直接的二进制数据.
- 第一个参数:要读写的内存(指针)
- 第二个参数: 内存大小
- 第三个参数:要有几个这样的内存
- 最后一个参数才是FILE指针,返回值为成功读写的字节数
为什么nitems?
因为二进制文件的读写一般都是通过对一个结构变量的操作来进行的,nitems用来说明要读写几个结构变量,size其实指的也是结构大小
因为二进制文件的读写一般都是通过对一个结构变量的操作来进行的,nitems用来说明要读写几个结构变量,size其实指的也是结构大小
在文件中定位(fseek,ftell)
long ftell(FILE *stream);
int fseek(FILE *stream,long offset,int whence);
SEEK_SET:从头开始
SEEK_CUR:从当前位置开始
SEEK_END:从末尾开始(倒着)
long ftell(FILE *stream);
int fseek(FILE *stream,long offset,int whence);
SEEK_SET:从头开始
SEEK_CUR:从当前位置开始
SEEK_END:从末尾开始(倒着)
可移植性
这样的二进制文件不具有可移植性,如int为32位的机器上写成的数据文件无法直接在int位64位的机器上正确读出
解决方案之一是放弃使用int,而是typedef一个具有明确大小的类型,更好的方式是牺牲速度采用文本
这样的二进制文件不具有可移植性,如int为32位的机器上写成的数据文件无法直接在int位64位的机器上正确读出
解决方案之一是放弃使用int,而是typedef一个具有明确大小的类型,更好的方式是牺牲速度采用文本