天天看點

标準C基礎知識筆記七



轉載自本人Open-open部落格:http://www.open-open.com/home/space-43816-do-blog-id-8837.html

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

繼續閱讀