标准c基础知识笔记七

12年前

====》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*)//是否超越了文件末尾