C語言的基本輸入與輸出函數

C語言的基本輸入與輸出函數

1.1.1 格式化輸入輸出函數
  Turbo C2.0 標準庫提供了兩個控制檯格式化輸入、 輸出函數printf() 和scanf(), 這兩個函數可以在標準輸入輸出設備上以各種不同的格式讀寫數據。printf()函數用來向標準輸出設備(屏幕)寫數據; scanf() 函數用來從標準輸入設備(鍵盤)上讀數據。

一、printf()函數
  printf()函數是格式化輸出函數, 一般用於向標準輸出設備按規定格式輸出信息。在編寫程序時經常會用到此函數。printf()函數的調用格式爲:printf(“<格式化字符串>”, <參量表>);其中格式化字符串包括兩部分內容: 一部分是正常字符, 這些字符將按原樣輸出,例如printf(“風雨兼程\n”); 另一部分是格式化規定字符, 以”%”開始, 後跟一個或幾個規定字符,用來確定輸出內容格式。參量表是需要輸出的一系列參數, 其個數必須與格式化字符串所說明的輸出參數個數一樣多, 各參數之間用“,”分開, 且順序一一對應, 否則將會出現意想不到的錯誤。
1. 格式化規定符
Turbo C2.0提供的格式化規定符如下:
━━━━━━━━━━━━━━━━━━━━━━━━━━
符號                                     作用
——————————————————————————
%d                                     十進制有符號整數
%u                                     十進制無符號整數
%f                                      浮點數
%s                                      字符串
%c                                      單個字符
%p                                      指針的值
%e                                      指數形式的浮點數
%x, %X                               無符號以十六進制表示的整數
%0                                      無符號以八進制表示的整數
%g                                       自動選擇合適的表示法
━━━━━━━━━━━━━━━━━━━━━━━━━━
說明:
(1). 可以在“%”和字母之間插進數字表示最大場寬。例如: %9.2f 表示輸出場寬爲9的浮點數, 其中小數位爲2, 整數位爲6,小數點佔一位, 不夠9位右對齊。%8s 表示輸出8個字符的字符串, 不夠8個字符右對齊。

(2). 可以控制輸出左對齊或右對齊, 即在“%”和字母之間加入一個”-” 號可說明輸出爲左對齊, 否則爲右對齊。例如: %-7d 表示輸出7位整數左對齊。如果字符串的長度或整型數位數超過說明的場寬, 將按其實際長度輸出。但對浮點數, 若整數部分位數超過了說明的整數位寬度, 將按實際整數位輸出;若小數部分位數超過了說明的小數位寬度, 則按說明的寬度以四捨五入輸出。另外, 若想在輸出值前加一些0, 就應在場寬項前加個0。例如: d 表示在輸出一個小於4位的數值時, 將在前面補0使其總寬度爲4位。如果用浮點數表示字符或整型量的輸出格式, 小數點後的數字代表最大寬度,小數點前的數字代表最小寬度。例如: %6.9s 表示顯示一個長度不小於6且不大於9的字符串。若大於9, 則第9個字符以後的內容將被刪除。
(3). 可以在“%”和字母之間加小寫字母l, 表示輸出的是長型數。例如: %ld 表示輸出long整數%lf 表示輸出double浮點數。
2. 一些特殊規定字符
━━━━━━━━━━━━━━━━━━━━━━━━━━
字符                      作用
——————————————————————————
\n                        換行
\f                         清屏並換頁
\r                         回車
\t                         Tab符
\xhh                     表示一個ASCII碼用16進表示,
                           其中hh是1到2個16進制數
━━━━━━━━━━━━━━━━━━━━━━━━━━

編制下面的程序,以加深對TurboC2.0數據的瞭解

例1 

#include<stdio.h>

#include<string.h> 

intmain() 

{

  char c,s[20], *p;

  inta=1234, *i; 

  floatf=3.141592653589;

  doublex=0.12345678987654321; 

  p="How do you do"; 

  strcpy(s,"Hello, Comrade");

  *i=12;   

  c='\x41';

  printf("a=%d\n", a);    /*結果輸出十進制整數a=1234*/ 

  printf("a=%6d\n", a);   /*結果輸出6位十進制數a= 1234*/ 

  printf("a=%06d\n", a);  /*結果輸出6位十進制數a=001234*/ 

   printf("a=%2d\n", a);   /*a超過2位, 按實際值輸出a=1234*/ 

  printf("*i=%4d\n", *i); /*輸出4位十進制整數*i= 12*/ 

  printf("*i=%-4d\n",*i); /*輸出左對齊4位十進制整數*i=12*/  

  printf("i=%p\n", i);    /*輸出地址i=06E4*/ 

  printf("f=%f\n", f);    /*輸出浮點數f=3.141593*/ 

  printf("f=6.4f\n", f);  /*輸出6位其中小數點後4位的浮點數f=3.1416*/   

  printf("x=%lf\n", x);   /*輸出長浮點數x=0.123457*/ 

  printf("x=%18.16lf\n", x);/*輸出18位其中小數點後16位的長浮點數x=0.1234567898765432*/   

  printf("c=%c\n", c);    /*輸出字符c=A*/

  printf("c=%x\n", c);    /*輸出字符的ASCII碼值c=41*/ 

  printf("s[]=%s\n", s);  /*輸出數組字符串s[]=Hello, Comrade*/ 

  printf("s[]=%6.9s\n", s);/*輸出最多9個字符的字符串s[]=Hello, Co*/ 

  printf("s=%p\n", s);    /*輸出數組字符串首字符地址s=FFBE*/   

  printf("*p=%s\n", p);   /* 輸出指針字符串p=How do you do*/ 

  printf("p=%p\n", p);    /*輸出指針的值p=0194*/ 

  getch(); 

   retunr0; 

}

二、scanf()函數
scanf()函數是格式化輸入函數, 它從標準輸入設備(鍵盤) 讀取輸入的信息。其調用格式爲:scanf(“<格式化字符串>”, <地址表>);格式化字符串包括以下三類不同的字符;
1. 格式化說明符: 格式化說明符與printf()函數中的格式說明符基本相同。
2. 空白字符: 空白字符會使scanf()函數在讀操作中略去輸入中的一個或多個空白字符。
3. 非空白字符: 一個非空白字符會使scanf()函數在讀入時剔除掉與這個非空白字符相同的字符。地址表是需要讀入的所有變量的地址, 而不是變量本身。這與printf()函數完全不同, 要特別注意。各個變量的地址之間同“,”分開。
例1:

int i,j;
scanf(“%d, %d”, &i, &j);

上例中的scanf()函數先讀一個整型數, 然後把接着輸入的逗號剔除掉, 最後讀入另一個整型數。如果“,”這一特定字符沒有找到, scanf()函數就終止。若參數之間的分隔符爲空格, 則參數之間必須輸入一個或多個空格。
說明:
(1). 對於字符串數組或字符串指針變量, 由於數組名和指針變量名本身就是地址, 因此使用scanf()函數時, 不需要在它們前面加上”&”操作符。
例2
main()
{
  char *p, str[20];
  scanf(“%s”, p);
  scanf(“%s”, str);
  printf(“%s\n”, p);
  printf(“%s\n”, str);
}

(2). 可以在格式化字符串中的“%”各格式化規定符之間加入一個整數, 表示任何讀操作中的最大位數。如例2中若規定只能輸入10字符給字符串指針p, 則第一條scanf() 函數語句變爲scanf(“s”, p);程序運行時一旦輸入字符個數大於10, p就不再繼續讀入, 而後面的一個讀入函數即scanf(“%s”, str)就會從第11個字符開始讀入。實際使用scanf()函數時存在一個問題, 下面舉例進行說明:當使用多個scanf()函數連續給多個字符變量輸入時, 例如:
main()
{
  char c1, c2;
  scanf(“%c”, &c1);
  scanf(“%c”, &c2);
  printf(“c1 is %c, c2 is %c”, c2, c2);
}

運行該程序, 輸入一個字符A後回車 (要完成輸入必須回車), 在執行scanf(“%c”, &c1)時, 給變量c1賦值”A”, 但回車符仍然留在緩衝區內, 執行輸入語句scanf(”%c”, &c2)時, 變量c2輸出的是一空行, 如果輸入AB後回車, 那麼輸出結果爲: c1 is A, c2 is B。要解決以上問題, 可以在輸入函數前加入清除函數fflush()。修改以上程序變成:
#include<stdio.h>
main()
{
  char c1, c2;
  scanf(“%c”, &c1);
  fflush(stdin);
  scanf(“%c”, &c2);
  printf(“c1 is %c, c2 is %c”, c1, c2);
}

1.1.2 非格式化輸入輸出函數
非格式化輸入輸出函數可以由上面講述的標準格式化輸入輸出函數代替, 但這些函數編譯後代碼少, 相對佔用內存也小, 從而提高了速度, 同時使用也比較方便。下面分別進行介紹。
一、puts()和gets()函數
1. puts()函數puts()函數用來向標準輸出設備(屏幕)寫字符串並換行, 其調用格式爲:puts(s);其中s爲字符串變量(字符串數組名或字符串指針)。puts()函數的作用與語printf(”%s\n”, s)相同。
例3:
main()
{
  char s[20], *f;
  strcpy(s, “Hello! Turbo C2.0″);
  f=“Thank you”;
  puts(s);
  puts(f);
}

說明:
(1). puts()函數只能輸出字符串, 不能輸出數值或進行格式變換。
(2). 可以將字符串直接寫入puts()函數中。如:puts(“Hello, Turbo C2.0”);

2. gets()函數
gets()函數用來從標準輸入設備(鍵盤)讀取字符串直到回車結束, 但回車符不屬於這個字符串。其調用格式爲:gets(s);其中s爲字符串變量(字符串數組名或字符串指針)。gets(s)函數與scanf(“%s”, &s)相似, 但不完全相同, 使用scanf(“%s”,&s)函數輸入字符串時存在一個問題, 就是如果輸入了空格會認爲輸入字符串結束,空格後的字符將作爲下一個輸入項處理, 但gets() 函數將接收輸入的整個字符串直到回車爲止。
例4
main()
{
  char s[20], *f;
  printf(“What’s your name?\n”);
  gets(s);
  puts(s);
  puts(“How old are you?”);
  gets(f);
  puts(f);
}

說明:(1). puts()函數只能輸出字符串, 不能輸出數值或進行格式變換。(2). 可以將字符串直接寫入puts()函數中。如:puts("Hello, Turbo C2.0");

2. gets()函數

gets()函數用來從標準輸入設備(鍵盤)讀取字符串直到回車結束, 但回車符不屬於這個字符串。其調用格式爲:gets(s);其中s爲字符串變量(字符串數組名或字符串指針)。 gets(s)函數與scanf("%s", &s)相似, 但不完全相同, 使用scanf("%s",&s)函數輸入字符串時存在一個問題, 就是如果輸入了空格會認爲輸入字符串結束,空格後的字符將作爲下一個輸入項處理, 但gets() 函數將接收輸入的整個字符串直到回車爲止

例5

main()

{

         char s[20], *f;

         printf("What's your name?\n");

         gets(s);                      /*等待輸入字符串直到回車結束*/

         puts(s);                      /*將輸入的字符串輸出*/

         puts("How old are you?");

         gets(f);

         puts(f);

 }

 說明:(1). gets(s)函數中的變量s爲一字符串。如果爲單個字符, 編譯連接不會有錯誤, 但運行後會出現"Null pointer asignmemt"的錯誤。

 二、putchar()、getch()、getche()和getchar()函數

1. putchar()函數

 putchar()函數是向標準輸出設備輸出一個字符, 其調用格式爲:putchar(ch);其中ch爲一個字符變量或常量。putchar()函數的作用等同於printf("%c", ch);

 例6:

#include<stdio.h>

main()

    {

         char c:             /*定義字符變量*/

         c='B';              /*給字符變量賦值*/

         putchar(c);         /*輸出該字符*/

         putchar('\x42');    /*輸出字母B*/

         putchar(0x42);      /*直接用ASCII碼值輸出字母B*/

 }

從本例中的連續四個字符輸出函數語句可以分清字符變量的不同賦值方法。

2. getch()、getche()和getchar()函數

(1) getch()和getche()函數  這兩個函數都是從鍵盤上讀入一個字符。其調用格式爲:getch(); getche();兩者的區別是:getch()函數不將讀入的字符回顯在顯示屏幕上, 而getche()函數卻將讀入的字符回顯到顯示屏幕上。

 例7:

#include<stdio.h>

main()

{

         char c, ch;

         c=getch();     /*從鍵盤上讀入一個字符不回顯送給字符變量c*/

         putchar(c);    /*輸出該字符*/

         ch=getche();   /*從鍵盤上帶回顯的讀入一個字符送給字符變量ch*/

         putchar(ch);

}

利用回顯和不回顯的特點, 這兩個函數經常用於交互輸入的過程中完成暫停等功能。

例8:

#include<stdio.h>

main()

{

         char c, s[20];

         printf("Name:");

         gets(s);

         printf("Press any key to confinue...");

         getch(); /*等待輸入任一鍵*/

}

(2) getchar()函數

getchar()函數也是從鍵盤上讀入一個字符, 並帶回顯。它與前面兩個函數的區別在於: getchar()函數等待輸入直到按回車才結束, 回車前的所有輸入字符都會逐個顯示在屏幕上。但只有第一個字符作爲函數的返回值。getchar()函數的調用格式爲:getchar();

例9:

#include<stdio.h>

main()

{

         char c;

         c=getchar();   /*從鍵盤讀入字符直到回車結束*/

         putchar(c);    /*顯示輸入的第一個字符*/

         getch();       /*等待按任一健*/

 }

1.2 文件的輸入輸出函數

鍵盤、顯示器、打印機、磁盤驅動器等邏輯設備, 其輸入輸出都可以通過文件管理的方法來完成。而在編程時使用最多的要算是磁盤文件, 因此本節主要以磁盤文件爲主, 詳細介紹Turbo C2.0提供的文件操作函數, 當然這些對文件的操作函數也適合於非磁盤文件的情況另外, TurboC2.0提供了兩類關於文件的函數。一類稱做標準文件函數也稱緩衝型文件函數, 這是ANSI標準定義的函數; 另一類叫非標準文件函數, 也稱非緩衝型文件函數。這類函數最早公用於UNIX操作系統, 但現在MS-DOS3.0 以上版本的操作系統也可以使用。下面分別進行介紹。

1.2.1 標準文件函數

標準文件函數主要包括文件的打開、關閉、讀和寫等函數。不象BASIC 、FORTRAN語方有順序文件和隨機文件之分,   在打開時就應按不同的方式確定。Turbo C2.0並不區分這兩種文件, 但提供了兩組函數, 即順序讀寫函數和隨機讀寫函數。

一、文件的打開和關閉

任何一個文件在使用之前和使用之後, 必須要進行打開和關閉, 這是因爲操作系統對於同時打開的文件數目是有限制的, DOS操作系統中,可以在DEVICE.SYS中定義允許同時打開的文件數n(用files=n定義)。其中n 爲可同時打開的文件數, 一般n<=20。因此在使用文件前應打開文件, 纔可對其中的信息進行存取。用完之後需要關閉, 否則將會出現一些意想不到的錯誤。Turbo C2.0提供了打開和關閉文件的函數。

1. fopen()函數

fopen函數用於打開文件, 其調用格式爲:FILE *fopen(char *filename, *type);在介紹這個函數之;前, 先了解一下下面的知識。

(1) 流(stream)和文件(file)

流和文件 在Turbo C2.0中是有區別的, TurboC2.0 爲編程者和被訪問的設備之間提供了一層抽象的東西, 稱之爲"流", 而將具體的實際設備叫做文件。流是一個邏輯設備, 具有相同的行爲。因此, 用來進行磁盤文件寫的函數也同樣可以用來進行打印機的寫入。在Turbo C2.0中有兩種性質的流:   文字流(textstream)和二進制(binary stream)。對磁盤來說就是文本文件和二進制文件。本軟件爲了便於讓讀者易理解Turbo C2.0語言而沒有對流和文件作特別區分。

(2) 文件指針FILE

實際上FILE是一個新的數據類型。它是TurboC2.0的基本數據類型的集合,稱之爲結構指針。有關結構的概念將在第四節中詳細介紹, 這裏只要將FILE理解爲一個包括了文件管理有關信息的數據結構, 即在打開文件時必須先定義一個文件指針。

 (3) 以後介紹的函數調用格式將直接寫出形式參數的數據類型和函數返回值的數據類型。例如: 上面打開文件的函數, 返回一個文件指針, 其中形式參數有兩個, 均爲字符型變量(字符串數組或字符串指針)。本軟件不再對函數的調用格式作詳細說明。現在再來看打開文件函數的用法。fopen()函數中第一個形式參數表示文件名, 可以包含路徑和文件名兩部分。如:

    "B:TEST.DAT"

    "C:\\TC\\TEST.DAT"

  如果將路徑寫成"C:\TC\TEST.DAT"是不正確的, 這一點要特別注意。第二個形式參數表示打開文件的類型。關於文件類型的規定參見下表。

                       表 文件操作類型

    ━━━━━━━━━━━━━━━━━━━━━━━━

         字符                含義

    ──────────────────────────────────

         "r"           打開文字文件只讀

          "w"           創建文字文件只寫

          "a"           增補, 如果文件不存在則創建一個

          "r+"          打開一個文字文件讀/寫

          "w+"          創建一個文字文件讀/寫

          "a+"          打開或創建一個文件增補

          "b"           二進制文件(可以和上面每一項合用)

          "t"           文這文件(默認項)

    ━━━━━━━━━━━━━━━━━━━━━━━━

如果要打開一個CCDOS子目錄中, 文件名爲CLIB的二進制文件, 可寫成:fopen("c:\\ccdos\\clib", "rb");

如果成功的打開一個文件,fopen()函數返回文件指針,   否則返回空指針(NULL)。由此可判斷文件打開是否成功。

2. fclose()函數

fclose()函數用來關閉一個由fopen()函數打開的文件 , 其調用格式爲:int fclose(FILE *stream); 該函數返回一個整型數。當文件關閉成功時, 返回0, 否則返回一個非零值。可以根據函數的返回值判斷文件是否關閉成功。

例10:

#iclude<stdio.h>

main()

{

         FILE *fp;                /*定義一個文件指針*/

         int i;

         fp=fopen("CLIB", "rb"); /*打開當前目錄名爲CLIB的文件只讀*/

         if(fp==NULL)             /*判斷文件是否打開成功*/

           puts("File openerror");/*提示打開不成功*/

         i=fclose(fp);            /*關閉打開的文件*/

         if(i==0)                 /*判斷文件是否關閉成功*/

           printf("O,K");        /*提示關閉成功*/

         else

           puts("File close error");/*提示關閉不成功*/

}

二、有關文件操作的函數

1. 文件的順序寫函數

fprintf()、fputs()和fputc()函數函數fprintf()、fputs()和fputc()均爲文件的順序寫操作函數,其調用格式如下:int fprintf(FILE *stream, char *format, <variable-list>);int fputs(char *string, FILE *steam);int fputc(int ch, FILE *steam);

上述三個函數的返回值均爲整型量。fprintf() 函數的返回值爲實際寫入文件中的字罕個數(字節數)。如果寫錯誤, 則返回一個負數, fputs()函數返回0時表明將string指針所指的字符串寫入文件中的操作成功, 返回非0時, 表明寫操作失敗。fputc()函數返回一個向文件所寫字符的值, 此時寫操作成功, 否則返回EOF(文件結束結束其值爲-1, 在stdio.h中定義)表示寫操作錯誤。fprintf( ) 函數中格式化的規定與printf( ) 函數相同,   所不同的只是fprintf()函數是向文件中寫入。而printf()是向屏幕輸出。

下面介紹一個例子, 運行後產後一個test.dat的文件。

例11:

#include<stdio.h>

 main()

{

         char *s="That's goodnews"); /*定義字符串指針並初始化*/

         int i=617;                    /*定義整型變量並初始化*/

         FILE *fp;                     /*定義文件指針*/

         fp=fopne("test.dat", "w");    /*建立一個文字文件只寫*/

         fputs("Your score of TOEFLis", fp);/*向所建文件寫入一串字符*/

         fputc(':', fp);               /*向所建文件寫冒號:*/

         fprintf(fp, "%d\n", i);      /*向所建文件寫一整型數*/

         fprintf(fp, "%s", s);        /*向所建文件寫一字符串*/

         fclose(fp);                   /*關閉文件*/

}

用DOS的TYPE命令顯示TEST.DAT的內容如下所示:屏幕顯示

     Your score of TOEFL is: 617

     That's good news

2. 文件的順序讀操作函數

fscanf()、fgets()和fgetc()函數函數fscanf()、fgets()和fgetc()均爲文件的順序讀操作函數,其調用格式如下:int fscanf(FILE *stream, char *format, <address-list>);char fgets(char *string, int n, FILE *steam);int fgetc(FILE *steam);

fscanf()函數的用法與scanf()函數相似,   只是它是從文件中讀到信息。fscanf()函數的返回值爲EOF(即-1), 表明讀錯誤, 否則讀數據成功。fgets()函數從文件中讀取至多n-1個字符(n用來指定字符數), 並把它們放入string指向的字符串中, 在讀入之後自動向字符串未尾加一個空字符, 讀成功返回string指針,失敗返回一個空指針。fgetc()函數返回文件當前位置的一個字符, 讀錯誤時返回EOF。

下面程序讀取例11產生的test.dat文件, 並將讀出的結果顯示在屏幕上。

 例12

#include<stdio.h>

main()

{

         char *s, m[20];

         int i;

         FILE *fp;

         fp=fopen("test.dat", "r");

          fgets(s, 24, fp);

         printf("%s", s);

         fscanf(fp, "%d", &i);

         printf("%d", i);

         putchar(fgetc(fp));

         fgets(m, 17, fp);

         puts(m);

         fclose(fp);

         getch();

}

運行後屏幕顯示:

   Your score of TOEFL is: 617

   That's good news

如果將上例中fscanf(fp,"%d", &i)改爲fscanf(fp, "%s", m), 再將其後的輸出語句改爲printf("%s",m), 則可得出同樣的結果。由此可見Turbo C2. 0中只要是讀文字文件, 則不論是字符還是數字都將按其ASCII值處理。另外還要說明的一點就是fscanf()函數讀到白符時, 便自動結束, 在使用時要特別注意。

3. 文件的隨機讀寫

有時用戶想直接讀取文件中間某處的信息, 若用文件的順序讀寫必須從文件頭開始直到要求的文件位置再讀, 這顯然不方便。Turbo C2.0提供了一組文件的隨機讀寫函數, 即可以將文件位置指針定位在所要求讀寫的地方直接讀寫。文件的隨機讀寫函數如下:

   int fseek (FILE *stream, long offset, int fromwhere);

   int fread(void *buf, int size, int count, FILE *stream);

   int fwrite(void *buf, int size, int count, FILE *stream);

   long ftell(FILE *stream);

fseek()函數的作用是將文件的位置指針設置到從fromwhere開始的第offset字節的位置上, 其中fromwhere是下列幾個宏定義之一:

    文件位置指針起始計算位置fromwhere

━━━━━━━━━━━━━━━━━━━━━━━━━

    符號常數        數值           含義

───────────────────────────────────

   SEEK_SET          0        從文件開頭

   SEEK_CUR          1        從文件指針的現行位置

   SEEK_END          2        從文件末尾

━━━━━━━━━━━━━━━━━━━━━━━━━

offset是指文件位置指針從指定開始位置(fromwhere指出的位置)跳過的字節數。它是一個長整型量, 以支持大於64K字節的文件。fseek()函數一般用於對二進制文件進行操作。當fseek()函數返回0時表明操作成功, 返回非0表示失敗。

下面程序從二進制文件test_b.dat中讀取第8個字節。

例13:

#include<stdio.h>

main()

{

         FILE *fp;

         if((fp=fopen("test_b.dat", "rb"))==NULL)

           {

              printf("Can't openfile");

              exit(1);

           }

         fseek(fp, 8. 1, SEEK_SET);

         fgetc(fp);

         fclose(fp);

}

fread()函數是從文件中讀count個字段, 每個字段長度爲size個字節, 並把它們存放到buf指針所指的緩衝器中。fwrite()函數是把buf指針所指的緩衝器中, 長度爲size個字節的count個字段寫到stream指向的文件中去。隨着讀和寫字節數的增大, 文件位置指示器也增大, 讀多少個字節, 文件位置指示器相應也跳過多少個字節。讀寫完畢函數返回所讀和所寫的字段個數。ftell()函數返回文件位置指示器的當前值, 這個值是指示器從文件頭開始算起的字節數, 返回的數爲長整型數, 當返回-1時, 表明出現錯誤
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章