标准c基础知识笔记七
====》IO
INPUT与OUTPUT
常规下用scanf/printf即可;从输入/输出缓冲区读
#include <stdio.h>
int main()
{
printf("立马显示出来");
fflush(stdout);//刷新显示
printf("hello");
sleep(10);//在windows里面编译不能通过
printf("world");
return 0;
}
scanf 字符串===》数据
printf 内存里的数据====》字符序列
什么时候会立马输出到屏幕上
1、有输入请求的时候,会立马输出到屏幕
2、输出有换行符的时候,也会马上输出到屏幕上
3、程序结束的时候也会马上输出到屏幕上
4、输出缓冲区满的时候
#include <stdio.h>
//sscanf,sprintf
int main()
{
char buf[100];
sprintf(buf,"hello,i'm %s ,today is %d-%d-%d\n",
"wow",2012,05,16);
//把信息放到buffer数组中
puts(buf);
int age;
char name[20];
double salary;
const char * str="21 sxl 2000" ;
sscanf(str,"%d%s%lf",&age,&name,&salary);
printf("我是%s,今年%d,月薪%g\n",name,age,salary);
return 0;
}
1、从键盘输入5各日期,用一个日期数组保存,写一个通用排序函数,能够根据传入的排序规则对日期进行排序,再写一个函数用来输出排序
后的日期。要求写3个排序规则:一个按年从大到小,一个按月从小到大,一个按整个日期从早到晚。
2、写一个过滤函数,根据传入的过滤规则对一组整数进行过滤,输出所有符合规则的数据并返回符合规则的数据的个数。
3、写一个函数,用来返回一个文件名字符串,格式为imageXXX.jpg,其中XXX是从000开始的三位整数。每次返回一个文件名,每一次跟上一次
不一样,到999之后回到000。
内存分配
代码区
——————————————————————————
静态全局数据区
——————————————————————————
堆区(自由,一般自己收回)
——————————————————————————
栈区-----一般局部变量;受作用范围限制
malloc 与 free成对出现
理解指针:
指向数组的指针
指向函数的指针
指向结构变量的指针
指向堆空间的指针
堆空间----用3个函数之一来分配空间malloc/calloc/realloc
栈空间
指针只能保存地址
memset(地址,数值,字节数)
sscanf--->sscanf(字符串
---->fscanf(文件,===》文件用FILE*指针来表示
sprintf--->sprintf(字符数组
--->fprintf(文件,
-------------------------------------------
操作系统级别一般用一个int fd来表示文件;
C语言用file*指针来表示文件
c++用对象来表示文件
———————————————————————————————————————————
在C语言中file*指针有3个可用:stdout标准输出文件,stderr标准错误文件,stdin标准输入文件
其中stderr是没有缓冲的;而stdout与stdin是有缓冲的
而标准输入和输出是可以重定向的
fflush(stdout);//刷新标准输出文件
#include <stdio.h>
int main()
{
int n;
double d;
char str[100];
fsprintf(stdout,"请输入姓名、年龄和体重:");
fscanf(stdin,"%s%d%lf",str,&n,&d);
fprintf(stdout,"%s:%d岁,%g公斤\n",str,n,d);
return 0;
}
打开文件用fopen,关闭用fclose
FILE *fopen(const char *path,const char *mode);
FILE *Fdopen(int fildes,const char *mode);
FILE *freopen(const char *path,const char *mode,FILE*stream);
FILE*代表一个文件
打开方式
r从文件开始读取
r+读和写,从文件开始
w清0从头开始写
w+如果不存在创建新的,否则将清空,定位在文件开始
a追加
a+
有时间一定去man一下看看
man stdio.h
stdlib.h
string.h
time.h
math.h
如何实现FILE*呢?
FOPEN
类型 * 地址
vi fio.c
#include <stdio.h>
int main()
{
FILE* fi=fopen("in","r");//会返回一个FILE*,代表的是一个文件
//检查打开文件是否成功?
if(fi==NULL)
{
printf("打开文件in失败\n");
return 1;
}
char name[20];
int age;
double weight;
fscanf(fi,"%s",name);
fscanf(fi,"%d%lf",&age,&weight);
fclose(fi);
printf("姓名:%s,年龄:%d,体重:%g\n",name,age,weight);
FILE* fo=fopen("out","w");
if(fo=NULL){
printf("打开文件out失败\n");
return 2;
}
fprintf(fo,"向文件写内容\n");
fprintf(fo,"姓名:%s,年龄:%d,体重:%g\n",name,age,weight);
fclose(fo);
return 0;
}
//一定要记得关闭,因为写的文件可能在缓冲区中并没有写到文件里面,否则有可能丢失
格式串,在输出的时候还有些格式控制:
1、整数:%与%之间可以指定宽度,用什么来填充;
2、%%之间:如果是小数还可以指定宽度.小数位数f
3、可以指定靠左还是靠右,-表示靠左;默认靠右
4、%宽度.字符数s
以上规则:对于键盘,屏幕以及文件都适用
#include <stdio.h>
int main()
{
char * s="helloworld"
printf("%d,%10d,%-10d,%010d,%+d\n",123,123,123,123,123);
printf("%f,%10f,%-10f,%6.2f\n",1.2,1.2,1.2,1.2);//%f固定6位小数
printf("%s,%10s,%-10s,%6.3s\n",s,s,s,s);
int w=10;
for(w=10;w<15;w++)
{
printf("%c,%*c\n",'a',w,'a');
}
//在这里宽带使用*,可变宽度
printf("input an integer:");
int x,y;
scanf("%3d%5d",&x,&y);
printf("x=%d,y=%d\n",x,y);
//输入1234567890,输出为x=123 y=45678
//输入12 3,输出x=12 y=3
//输入12345 输出x=123 y=45
scanf("%*d%d",&x);//在scanf中这个*表示抛弃;而在上面printf中表示参数
printf("x=%d\n",x);
char str[100],st[100];
scanf("%[a-z]%[^a-z]",str,st);//读取在方括号内的字符,比如读取小写字符
//[^]表示不是这个范围的
printf("str=%s,st=%s\n",str,st);
return 0;
}
//其他的输出格式:
可以通过man printf来看
从文件读和从键盘读
scanf/printf fopen==>FILE* fclose
puts/gets fgets/fputs
gets会抛弃换行符
puts在写时会加上换行符
自动换行
fgets从文件读取一行,不会抛弃换行符,把它作为字符串的一部分
fputs向文件写的时候不会加换行符
一般情况下puts/fgets;fputs/gets交叉使用。
#include <stdio.h>
int main()
{
char buf[1000];
printf("请输入一行文字:\n");
//gets(buf);
//scanf("%[^\n]%*c",buf);
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]='\0';//去掉末尾换行符
puts(buf);
printf("%s",buf);
fputs(buf,stdout);//fputs本身并不换行
return 0;
}
//配置文件,用户信息文件/etc/passwd 一般都是一行一行的。
读写一个字符
getchar/putchar
等价scanf("%c" / printf("%c")
fgetc/fputs
getc/putc
fgetc一定是一个函数;getc有可能是个函数也可能是个宏
返回值为int而非char
不管什么字符都读取
#include <stdio.h>
int main()
{
int i;
int d;
for(i=0;i<3;i++)
{
// printf("请输入一个整数:");
// scanf("%d",&d);
// scanf("%*[^\n]");scanf("%*c");
// printf("您输入的是%d\n",d);
// getchar();
d=getchar();
if(d==EOF){
printf("读取终止\n");
break;
}
printf("%c(%d)\n",d,d);
}
return 0;
}
#include <stdio.h>
//int fgetc(FILE*)/int fputc(int,FILE*)
int main(int argc,char* argv[])
{
//a.out filename copyfile
if (argc!=3){
printf("%s filename copyfile\n",*argv);
return 0;
}
FILE * fi=fopen(argv[1],"r");
if(fi==NULL){
printf("无法打开文件%s"\n,argv[1]);
return 1;
}
FILE* fo=fopen(argv[2],"w");
if(fo==NULL){
printf("无法打开文件%s\n",argv[2]);
return 2;
}
char c;
while((c=fgetc(fi))!=EOF){//EOF在编译前会替换成-1
putchar(c);
fputc(c,fo);
}
fclose(fi);
fclose(fo);
return 0;
}
vi position.c
#include <stdio.h>
int main()
{
FILE* fp=fopen("file","r+");
if(fp==NULL)
{
printf("无法打开文件file\n");
return 1;
}
int c;
while((c=fgetc(fp))!=EOF){
fputc(c,fp);
}
fclose(fp);
return 0;
}
vi file
abcdefghijklmnopqrstuvwxyz
如何定位文件当前的读写呢?fseek函数,设置当前读写位置
feek(哪个文件,位置参数,从哪里算起的偏移量)
可以从当前位置或者某个特定的位置开始的偏移量seek_set,seek_cur,seek_end
ftell取当前位置
rewind把当前位置设置为文件的最开头
什么时候使用呢?比如1、音频或视频的播放器;2、数据库
我们读取file文件,把第10个和第20个字符交换位置
1、打开文件
2、读取出第10个字符
3、读取出第20个字符
4、
#include <stdio.h>
int main()
{
FILE* fp=fopen("file","r+");
if(fp==NULL){
printf("无法打开文件file\n");
return 1;
}
fseek(fp,9,SEEK_SET);
char c10,c20;
c10=getc(fp);
fseek(fp,9,SEEK_CUR);//getc读取完毕后,其位置加1,所以是9
c20=getc(fp);
fseek(fp,-11,SEEK_CUR);//用负数,是代表向前
putc(c20,fp);
fseek(fp,-8,SEEK_END);//为什么是-8,需要考虑换行符
putc(c10,fp);
fclose(fp);
return 0;
}
在内存和文件进行大量的读写时,则用fread/fwrite;从文件到内存叫读;将内存的东西放到文件里面叫写。
size_t fread(void *ptr,size_t size,size_t nmemb,FILE* stream);
size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE* stream);
对于内存中的数据,主要关注地址而非类型
vi fwrite.c
#include <stdio.h>
//fread(内存地址,每条记录的字节数,记录的个数,哪个文件)
//fwrite
typedef struct person{
char name[20];
char gender;
int age;
double salary;
}person;
int main()
{
person a[5]={{"abc",'F',18,3500},{"def",'M',20,4500},{"ghi",'F',20,3000},{"jkl",'F',23,2000},{"mno",'M',22,8000}};
FILE* fp=fopen("person.dat","wb",);//b在这里的意思是不做任何转换
if(fp==NULL){
printf("打开person.dat文件失败\n");
return 1;
}
int b[10]={11,22,33,44,55,66,77,88,1010};
short s=12345;
fwrite(a,sizeof(person),5,fp);
fwrite(b,sizeof(int),10,fp);
fwrite(&s,sizeof(short),1,fp);
fclose(fp);
return 0;
}
以上是将相关信息写到了person.dat文件中去了。
我们通过fread将信息从person.dat中读到内存中去
vi fread.c
#include <stdio.h>
typedef struct person{
char name[20];
char gender;
int age;
double salary;
}person;
int main()
{
person a[5]={};
int b[10]={};
short s=0;
FILE* fp=fopen("person.dat","rb");
if (fp==NULL){
printf("打开person.dat文件失败\n");
return 1;
}
fread(a,sizeof(person),5,fp);
fread(b,sizeof(int),10,fp);
fread(&s,sizeof(short),1,fp);
fclose(fp);
int i;
for (i=0;i<5;i++){
printf("%s:%s,%d,^g\n",a[i].name,a[i].gender='M'?"man":"women",a[i].age,a[i].salary);
}
for (i=0;i<10;i++){
printf("%d ",b[i]);
}
printf("\n");
printf("%hd\n",s);
return 0;
}
//ungetc向文件里面退出一个字符;下一次就读这个字符
举例:读取172.18.9.6或者ftp.xxx.xxx.xxx
vi ungetc.c
#include <stdio.h>
int main()
{
printf("请输入一些内容\n");
char str[1000];
double data;
register int c;
for(;;){
c=getchar();
if(c==EOF) break;
if(isspace(c)) continue;//isblank是不是空白
ungetc(c,stdin);
if(c>='0'&&c<='9'){
scanf("%lf",&data);
printf("data=%lf\n",data);
}
else{
scanf("%s",str);
printf("str=%s\n",str);
}
}
return 0;
}
//fgetc(),fgets(),fread(),fwrite()
//feof(FILE*)//是否超越了文件末尾