12/23 計程實習課

33
Speaker: Wen-Ching Lo Date: 2009/12/23

description

12/23 計程實習課. Speaker: Wen-Ching Lo Date: 2009/12/23. Outline. 檔案的輸入與輸出 Structure. 檔案的輸入與輸出. C 軟體提供了許多檔案的輸入與輸出函數,這些函數可分成兩大類。 有緩衝區的輸入與輸出 (Buffered I/O) 無緩衝區的輸入與輸出 (Unbuffered file I/O) 有緩衝區的輸入與輸出,是當它在讀取檔案資料或將資料寫入檔案時,一定都先經過一個緩衝區。 沒有緩衝區的輸入與輸出,表示輸入與輸出的動作,是直接在磁碟內執行讀取資料和寫入資料的動作。 - PowerPoint PPT Presentation

Transcript of 12/23 計程實習課

Page 1: 12/23 計程實習課

Speaker: Wen-Ching LoDate: 2009/12/23

Page 2: 12/23 計程實習課

檔案的輸入與輸出 Structure

Page 3: 12/23 計程實習課

C 軟體提供了許多檔案的輸入與輸出函數,這些函數可分成兩大類。 有緩衝區的輸入與輸出 (Buffered I/O) 無緩衝區的輸入與輸出 (Unbuffered file I/O)

有緩衝區的輸入與輸出,是當它在讀取檔案資料或將資料寫入檔案時,一定都先經過一個緩衝區。

沒有緩衝區的輸入與輸出,表示輸入與輸出的動作,是直接在磁碟內執行讀取資料和寫入資料的動作。

由於有緩衝區的輸入與輸出函數是包含在 stdio.h檔案內,所以程式前面,必須要包含下列指令。

# include <stdio.h >

Page 4: 12/23 計程實習課

函數名稱 功 能 說 明fopen( ) 開啟一個檔案fclose( ) 關閉一個檔案putc( ) 輸出一個字元到檔案getc( ) 從某一個檔案讀取一個字元fprintf( ) 輸出資料至某檔案fscanf( ) 從某檔案讀取資料feof( ) 測試是否到了檔案結束位置ferror( ) 測試檔案操作是否正常fseek( ) 設定準備讀取檔案資料的位置rewind( ) 將準備讀取檔案資料置,設定在檔案起始位置

remove( ) 檔案的刪除

Page 5: 12/23 計程實習課

fopen( ) 函數主要是用於開啟檔案。檔案在磁碟裡,使用前是需先經過開啟動作的。使用格式如下:

FILE *fopen(char *filename, char *mode); filename :檔案指標,指的是欲開啟的檔案名稱。 mode :檔案使用模式,指的是檔案被開啟之後,它的使用

方式。 “ r” :開啟一個文字檔 (text) ,供程式讀取。 “ w” :開啟一個文字檔,供程式將資料寫入此檔案內。如果磁

碟內不包含這個檔案,則系統會自行建立這個檔案。如果磁碟內包含這個檔案,則此檔案內容會被蓋過而消失。

“ a” :開啟一個文字檔,供程式將資料寫入此檔案的末端。如果此檔案不存在,則系統會自行建立此檔案。

Page 6: 12/23 計程實習課

“rb” :開啟一個二元檔( binary ),供程式讀取。 “ wb” :開啟一個二元檔,供程式資料寫入此檔案內。如果磁

碟內不包含這個檔案,則系統會自行建立這個檔案。如果磁碟內包含這個檔案,則此檔案內容會被蓋過而消失。

“ ab” :開啟一個二元檔,供程式將資料寫入此檔案末端,如果此檔案不存在,則系統會自行建立此檔案。

前述的 fopen( ) 函數的使用格式是以指標方式設計,而經常也會直接以字串方式設計此函數:

FILE *fopen(“filename”, “mode”);

Page 7: 12/23 計程實習課

fclose( ) 為關閉檔案的函數。 C 語言中關閉檔案主要有兩個目的: 促使檔案在關閉前會將檔案緩衝區資料寫入磁碟檔案

內,否則檔案緩衝區資料會遺失。 一個 C 語言程式,在同一時間可開啟的檔案數量有限,

一般是 20 個,如果你的程式很大,要開啟超過 20 個檔案時,你必須將暫時不用的檔案關閉。

fclose( ) 執行失敗,它的傳回值是非零值,如果fclose() 執行成功,它的傳回值是零。 使用格式:int fclose(FILE *fname);

Page 8: 12/23 計程實習課

putc( ) 函數的主要功能是將一個字元,寫入某檔案內,它的使用格式如下:

int putc(int ch , FILE * fp); ch 代表所欲輸出的字元。 fp 檔案指標。

此函數如果執行成功,它的傳回值是 ch 字元值。如果執行失敗,它的傳回值是 EOF 。

Page 9: 12/23 計程實習課

getc( ) 函數的主要目的是從某一個檔案中,讀取一個字元,它的使用格式如下:

int getc ( FILE *fp );

當執行 getc( ) 函數成功時,傳回值是所讀取的字元,如果所讀取的是檔案結束字元,則此值是 EOF 。而在 stdio.h 內, EOF 值是 -1 。

Page 10: 12/23 計程實習課

#include <stdio.h>int main(){ FILE *fp; int count = 0; fp = fopen("13_1.c","r"); if(fp == NULL) { printf("\n******open file error*****"); exit(1); } while ( getc(fp) != EOF ) count++; printf("The number of character for 13_1.c is %d\n", count); fclose(fp); return 0;}

Page 11: 12/23 計程實習課

C/C++ 語言中的 main 函數,經常帶有參數 argc , argv ,如下: int main( int argc, char *argv[])

argc 是指命令行輸入參數的個數。 argv 是儲存了所有的命令行參數。

Page 12: 12/23 計程實習課

#include <stdio.h>int main( int argc, char *argv[]){ FILE *fp1, *fp2; char chr; if(argc != 3) { printf("\ninput data error"); exit(1); } fp1 = fopen( argv[1], "r"); fp2 = fopen( argv[2], "w"); while ( (chr = getc(fp1) ) != EOF ) fputc (chr, fp2 ) ; fclose(fp1); fclose(fp2); return 0;}

Page 13: 12/23 計程實習課

fprintf( ) 主要目的是供你將資料,以格式化方式寫入某檔案內 fprintf(fp, “ 資料變數型態” , 資料變數名稱 ); 此函數格式和 printf( ) 使用格式相同 . 兩者唯一的差別是, printf( ) 會將資料列印在

螢幕上,而 fprintf( ) 會將資料列印在某個檔案內。

Example:fprintf(fp,"%d\n",var);fprintf(fp,"\2: The average is %6.2f",average);

Page 14: 12/23 計程實習課

fscanf( ) 主要的目的是讓我們從某個檔案讀取資料 fscanf( fp , "……." , ………); fscanf( ) 函數和 scanf( ) 函數兩者之間最大

的差別在, scanf( ) 函數主要用於從鍵盤輸入讀取資料, fscanf( ) 函數則是從 fp 檔案指標所指的檔案讀取資料。

Example:fscanf(fp,"%d",&var)

Page 15: 12/23 計程實習課

feof( ) 主要功能是測試在讀取資料時,是否已經讀到檔案末端位置:

int feof(fp);

若讀取資料的位置是在檔案末端,則傳回非零數值,否則傳回零。

ferror( ) 主要用於測試前一個有關檔案指標的操作是否正確: int ferror ( fp ); 如果前一個函數對有關檔案指標的操作,有錯誤,

則傳回值是非零數值,否則傳回零值。

Page 16: 12/23 計程實習課

fwrite( ) 主要目的是將某個資料緩衝區內容,寫入檔案指標所指的二元檔檔案內。 int fwrite(void *buffer, int num_byte, int count, FILE *ftp);

fread( ) 主要目的是將某二元檔檔案內的資料,讀入資料緩衝區內。int fread(void *buffer, int num_byte, int count, FILE *fp );

Page 17: 12/23 計程實習課

fseek( ) 主要目的是設定所要讀取資料的位置,以達隨機位置讀取檔案資料的目的。int fseek(fp, long num_byte, int origin); origin 有三種格式:

0 :表示從檔案開頭位置1 :表示從目前位置2 :表示從檔案末端位置

num_byte 為與 origin 的距離。

rewind( ) 功能在於將檔案指標移至檔案的開頭。

Page 18: 12/23 計程實習課

結構與陣列很類似,因為兩者都是將一些資料連接組合在一起,以下為兩者的比較。 陣列 : 相同型態資料之集合 .

結構 (struct) :可將不同型態的資料組合在一起

結構 (struct)為結構 (structure)的縮寫

結構中的項目通常稱為成員 (member) 。

Page 19: 12/23 計程實習課

能夠結合多個彼此相關的變數在一個名稱之下,且可以包含數個不同資料型態的變數。

結構是一種使用者自定的型態,它可將不同的資料型態串在一起。 舉例:「學生個人資料表」,

學號 ( 字串型態 ) 姓名 ( 字串型態 ) 成績 ( 整數型態 )

Page 20: 12/23 計程實習課

struct 結構名稱標籤 { 資料型態 變數 1;

資料型態 變數 2;

‧‧‧‧‧‧‧‧};

struct 結構名稱 變數 1,變數 2,…,變數m;

struct Student {

char ID[10]; char FirstName[10]; char LastName[10];

int grade;};

struct Student stu;

100

98753506

Wendy

Lo

ID[10]FirstName[

10]LastName[10]

grade

Student

Page 21: 12/23 計程實習課

  上頁敘述會在記憶體裡配置空間出來讓 student 結構變數使用,記憶體的配置情況如下: 記憶體

ID

FirstName

grade

Student

LastName

Page 22: 12/23 計程實習課

將結構型態與結構變數的宣告寫在同一個敘述struct 結構名稱 { 資料型態 欄位名稱 1;

資料型態 欄位名稱 2;

.

.

資料型態 欄位名稱 n;

} 變數 1,變數 2,…,變數 m;

Page 23: 12/23 計程實習課

利用小數點 (.) 來存取結構變數中的成員。

結構變數名稱 . 成員名稱 例如 :

stu.ID = “96753017”

stu.Firstname= “Wendy”

stu.LastName = “Lo”;

stu.grade= 100;

Page 24: 12/23 計程實習課

範例 : struct Student /* 定義結構mydata */

{ char ID[10]; char FirstName[10]; char LastName[10]; int grade; };

struct Student stu={“96753017”,”Wendy”,”Lo”,0 };

/* 宣告結構 Student型態之變數 stu,並設定結構內欄位的初值 */

Page 25: 12/23 計程實習課

結構陣列結構變數亦可以用宣告陣列 , 語法如下 :struct 結構名稱 結構陣列變數名稱 [ 陣列大小 ];Ex: struct Student

{ char ID[10]; char FirstName[10]; char LastName[10]; int grade; };

struct Student stu[100]; /* 結構變數的宣告 */

Page 26: 12/23 計程實習課

#include<stdio.h>#define MAX 2int main(void){ int i; struct data /* 定義結構 data */ { char name[10]; int math; }student[MAX]; for(i=0;i<MAX;i++) /* 宣告結構陣列 student */ { printf(" 學生姓名 :"); gets(student[i].name); printf(" 數學成績 :"); scanf("%d",&student[i].math); fflush(stdin); /* 清空緩衝區內的資料 */ } for(i=0;i<MAX;i++) /* 輸出結構陣列的內容 */ printf("%s 的數學成績 =%d\n",student[i].name,student[i].math); system("pause"); return 0;}

Page 27: 12/23 計程實習課

結構指標結構變數也是指標的一種,只是它是指向結構的指標,而非指向一般變數。宣告格式如下 :

struct 結構名稱 * 結構指標變數名稱 ;Ex: struct student /* 定義結構 mydata */

{ char name[15]; /* 各成員 ( 欄位 ) 的內容 */ char id[10]; int math; int eng; };

struct student * prt; /* 結構變數的宣告 */ptr=&student; /* 將指標指向此結構變數 student*/

Page 28: 12/23 計程實習課

使用指標來存取結構變數內的成員( 欄位 ) 時 ,要利用「 ->」來連接欲存取的成員,如下面格式:

結構指標名稱 -> 結構變數成員

Ex:

如前一頁所宣告的結構變數 student及指標 ptr為例,

ptr->math即代表了指向結構變數 student的 math成員。

Page 29: 12/23 計程實習課

#include<stdio.h>#include<stdlib.h>int main(void){ struct data

{ char name[10]; int eng;}student;

struct data *ptr; ptr=&student;

printf(" 學生姓名 :");gets(ptr->name);printf(" 英文成績 : ");scanf("%d",&ptr->eng);printf(" 英文成績 =%d",ptr->eng);system("pause");return 0;

}

29

Page 30: 12/23 計程實習課

結構可以存放不同的資料型態 , 所以在結構中也可以擁有另一個結構 , 如此就稱為巢狀結構 (nested structure).

格式如下 :struct 結構 1 { /* 結構 1 的成員 */ };

struct 結構 2 { /* 結構 2 的成員 */ struct 結構 1 變數名稱 ; };

Page 31: 12/23 計程實習課

#include<stdio.h>#include<stdlib.h>int main(void){ struct date /*define date*/ {

int month; int day; };struct student /*define nested structure---student*/{ char name[10]; int math; struct date birthday;}s1={“David Li",80, {2,10}};printf("student name:%s\n",s1.name);printf("birthday:%d month, %d day\n",s1.birthday.month,s1.birthday.day);printf("math grade:%d\n",s1.math);return 0;

}

31

Page 32: 12/23 計程實習課
Page 33: 12/23 計程實習課

題目:有一個表示學生國英數成績結構陣列如右所附。請完成二個函數,其原型分別為 void happy_birthday(struct data [], int); int max_grade(struct data []); 其功能可以(1) 列印 12 月份生日的學生姓名; (2) 傳回全班平均成績最高的學生的索引值 。 請完成函數,並依題目輸出要求,測試函數,印出結果。 題目輸入:八個學生資料如右所附。 題目輸出:(1) 印出本月壽星的學生姓名 (2) 印出全班平均成績最高的學生姓名

struct day{int yy, mm, dd; /* 年、月、日 */ };struct data{char name[20]; /* 姓名 */ struct day birthday; /* 生日 */ int chi, math, eng; /* 國文、數學 與 英文成績 */ }; struct data student[8] =

{{"Marry Hu", {77, 2, 3}, 89, 90, 79}, {"Tom Chen", {78, 12, 13}, 79, 69,

88}, {"Billy Wu", {77, 1, 30}, 81, 54, 66}, {"John Hsu", {77, 7, 22}, 69, 49, 70}, {"Tim Huang", {77, 12, 8}, 90, 62, 83}, {"Marry Chen", {78, 5, 27}, 78,93, 91}, {"Tomas Chu", {77, 5, 18}, 80, 50, 68}, {"Ann Wang", {77, 9, 21},100,100,

100}};