




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第五章文件數據的處理目標:文件是程序設計中處理的重要數據對象之一,文件的主要作用是可以將數據永久地保存在計算機外部存儲介質上,使之成為可以共享的信息。本章主要討論在緩沖文件系統中文件數據的常用處理方法
。本章分文以下三部分5.1文件處理基本概念5.2文件數據的讀寫方法5.3隨機存取文件處理基礎第五章文件數據的處理目標:文件是程序設計中處理的重要數據對象之一,文件的主要作用是可以將數據永久地保存在計算機外部存儲介質上,使之成為可以共享的信息。本章主要討論在緩沖文件系統中文件數據的常用處理方法
。本章分文以下三部分5.1文件處理基本概念5.2文件數據的讀寫方法5.3隨機存取文件處理基礎第五章文件數據的處理目標:文件是程序設計中處理的重要數據對象之一,文件的主要作用是可以將數據永久地保存在計算機外部存儲介質上,使之成為可以共享的信息。本章主要討論在緩沖文件系統中文件數據的常用處理方法
。本章分文以下三部分5.1文件處理基本概念5.2文件數據的讀寫方法5.3隨機存取文件處理基礎5.1文件處理基本概念--文件的概念什么是文件?文件是指具名存放在外部存儲設備上的一組信息,它們以二進制代碼形式存在,可能是一組數據、一個程序,一張照片、一段聲音等等。
文件分類
⑴按文件的結構形式分類;⑵按文件的讀寫方式分類;⑶按文件存儲的外部設備分類;⑷按系統對文件的處理方法分類;文件分類⑴按文件的結構形式分類①二進制文件:內存中的數據按其在內存中的存儲形式原樣存放到計算機外部存儲設備,這類文件可以節省計算機外存空間。②文本文件:全部由字符組成的具有行列結構的文件,即文件的每個元素都是字符或換行符。1024二進制文件文本文件000001000000000000000001000000000000001000000100文件分類⑵按文件的讀寫方式分類①順序存取文件(流式文件
):將文件看成是一個字符流,并不考慮其存儲時的界限,對文件的讀寫是以字符或字節為單位,輸入輸出數據流的開始和結束都受程序的控制而不是受回車換行符的控制。順序文件讀寫入數據時,首先要打開順序文件并將文件內部記錄(讀寫)指針置于文件的開頭,然后將數據按一個文件元素一個文件元素的順序進行讀寫操作。②隨機存取文件具有隨機讀寫功能的文件稱為隨機存取文件。隨機文件對任一元素的讀寫不必象順序文件那樣從頭開始,而是可以直接對文件的某一元素進行訪問。C語言的眾多編譯系統中都提供了隨機讀取文件中任意數據元素的函數。
文件分類⑶按文件存儲的外部設備分類①磁盤文件:保存在磁盤上的文件。程序的運行過程中,需要將一些數據信息輸出到磁盤上保存起來,需要的時候再從磁盤中將數據讀取輸入到系統內存中進行處理。②設備文件。所有的計算機系統外部設備都作為文件對待,這樣的文件稱為設備文件。常用標準設備文件:
KYBD:(鍵盤)、SCRN:(顯示器)、
PRN或LPT1:(打印機)等。3個特殊設備文件:stdin:(標準輸入文件) 由系統指定為鍵盤;stdout:(標準輸出文件) 由系統指定為顯示器;stderr:(標準錯誤輸出文件) 由系統指定為顯示器;C語言中,將磁盤文件和設備文件都作為相同的邏輯文件對待,對這些文件的操作(輸入和輸出等)都采用相同的方法進行。這種邏輯上的統一為C程序的設計提供了極大的便利,從而使得C標準函數庫中的輸入輸出函數既可以用來處理通常的磁盤文件,又可以用來對計算機系統的外部設備進行控制。
文件分類⑷按系統對文件的處理方法分類。①緩沖文件系統:系統自動地在內存中為每一個正在使用的文件開辟一個緩沖區。從內存向磁盤輸出數據必須先送到內存中的緩沖區,待緩沖區裝滿后才將整個緩沖區的數據一起送到磁盤文件中保存。如果從磁盤文件向系統內存讀入數據,則從磁盤文件中一次讀入一批數據到系統緩沖區,然后再從數據緩沖區中將數據送到對應程序的變量數據存儲區。②非緩沖文件系統:系統不自動為程序開辟確定大小的文件緩沖區,而由程序為用到的每個文件設置并管理緩沖區。1983年ANSIC標準決定放棄采用非緩沖文件系統而只使用緩沖文件系統,即使用緩沖文件系統處理文本文件和二進制文件。
文件類型指針緩沖文件系統中,對文件的處理都是通過在內存中開辟一個區域(緩沖區)來存取文件的相關的信息,比如說文件的名字、文件的狀態、文件讀寫指針的當前位置等等,這些關于文件處理的信息在整個文件處理的過程中必須妥善保存和管理。C語言中用一個結構體類型的變量來保存這些信息,該結構體類型變量由語言處理系統預先定義并命名為FILE。VisualC++編譯器中對FILE結構體類型定義如下:struct_iobuf{ char*_ptr;
int_cnt;char*_base;
int_flag;
int_file;
int_charbuf;
int_bufsiz;char*_tmpfname;};typedef
struct_iobufFILE;文件類型指針FILE*指針變量名;定義一個FILE結構體數據類型的指針變量文件處理標準庫函數建立或者打開指定文件成功后,函數會給出該緩沖區的首地址(即FILE變量的首地址),所以程序員需要定義相應的FLIE類型指針來存放該地址。使得文件指針與被打開文件建立起關聯。此后的代碼中既可通過文件指針對該文件中的數據進行各種各樣的操作。如果需要同時處理若干個文件,則需要定義若干個文件類型指針。FILE*fp1,*fp2;同時定義了兩個文件類型指針變量fp1和fp2。5.2C語言中的文件處理基礎程序中對于文件處理的一般過程為:⑴打開(或者建立)要處理的文件。⑵按某種方式處理文件。⑶關閉被處理的文件。在C語言中,文件操作都是通過C提供的函數實現的。這些函數是放在標準輸入輸出函數庫“stdio.h”中文件的打開和關閉函數FILE*fopen(constchar*filename,constchar*mode);功能:按照指定的文件操作模式(方式)打開(或創建)指定的文件,打開(或創建)成功時返回與文件相對應的結構體類型變量的指針,否則返回空(NULL)。fopen的原型中參數的意義如下:⑴filename:指定將要訪問的文件名字,可以使用值為字符串類型的變量或者用雙引號括起來的字符串常量;⑵mode:指定文件模式,即規定文件操作的方式
文件的打開和關閉函數"r"以只讀方式打開一個已有的文本文件;"w"以只寫方式建立一個文本文件;"a"以添加方式打開一個文本文件,將文件數據指針移到文件末尾,在文件末尾進行添加;若文件本身不存在,則先建立一新文件再進行添加;"rb"以只讀方式打開一個二進制文件;"wb"以只寫方式打開一個二進制文件;"ab"以添加方式打開/建立一個二進制文件;"r+"以讀寫方式打開一個已有的文本文件;"w+"以讀寫方式建立一個文本文件;"a+"以讀寫方式打開一個文本文件,文件數據指針移到文件末尾,在文件末尾進行讀寫操作;若文件本身不存在,則先建立一新文件再操作;“rb+”以讀寫方式打開一個已有的二進制文件;"wb+"以讀寫方式建立一個二進制文件;"ab+"以讀寫方式打開/建立一個二進制文件;
文件的打開和關閉fopen函數正確地打開或建立了指定文件時,將返回系統中建立的文件類型結構體變量的地址;fopen函數沒有正常地完成打開或建立文件的任務,則會帶回一個出錯信息并返回一個空值(NULL),程序中需要定義一個文件類型的指針變量用以接收和處理fopen函數返回的信息。為了在關于文件處理的C程序中正確地了解處理文件的狀態,從程序結構上一般使用如下方式去打開或建立文件:FILE*fpt;if((fpt=fopen(file_name,file_mode))==NULL){
printf("Can’topen/createthisfile!\n"); exit(0); }文件的打開和關閉在指定打開或者創建文件的操作模式(操作方法)時必須掌握下面幾條原則:(1)用操作模式"r"打開一個文件時,該文件必須已經存在,且只能從該文件讀出。(2)用操作模式"w"打開的文件只能向該文件寫入時,若指定打開的文件不存在,則以指定的文件名建立該文件;若指定的文件名已經存在,則將該文件打開并將原內容清空(全部刪去)。(3)若要向一個已存在的文件追加新的信息,只能用操作模式"a"方式打開文件,但此時該文件必須是已經存在的,否則將會出錯文件的打開和關閉打開(或創建)一個文件就在內存中分配一段區域作為文件緩沖區,文件在使用過程中將一直占用該內存空間,文件處理完成后應及時地關閉文件以釋放文件所占用的存儲區域。int
fclose(FILE*stream);功能:將與指定文件指針變量相關聯的文件關閉。系統在關閉文件時首先將對應文件緩沖區中還沒有處理完的數據寫回相對應的文件,然后釋放與該指針對應的文件結構體變量,將資源歸還系統。fclose函數若正常關閉了文件,返回值為0,否則返回值為EOF。文件的打開和關閉例5.1從鍵盤上輸入所要創建文件的路徑(即存放目錄)和文件名字,創建一個用于寫操作的文本文件。printf("請輸入欲創建文件所在的目錄名:");gets(PathName);printf("請輸入欲創建文件文件名:");gets(FileName);strcpy(FullName,PathName);strcat(FullName,"\\");strcat(FullName,FileName);if((fp=fopen(FullName,"w"))==NULL) {
printf("Can'tcreatefile%s!\n",FullName);return;}else
printf("創建文件%s成功......\n",FullName);
fclose(fp);}生成文件名
文件的打開和關閉例5.1程序展示了在程序設計中如果需要在某個目錄(文件夾)中創建文件時,文件名字的組合方法。程序一次運行的過程如下所示:請輸入欲創建文件所在的目錄名:d:\cxsjjs(c)請輸入欲創建文件文件名:mydata.txt創建文件d:\cxsjjs(c)\mydata.txt
成功......
文件內部讀寫位置指針和文件尾的檢測方法1.文件內部讀寫位置指針記錄是文件內部的組織單位,不同類型文件的記錄大小也不盡相同。例如文本文件的一個記錄是一個字節,而32位系統的二進制整型數據文件的一個記錄則是4個字節。當打開(或創建)一個文件時,系統自動為打開的文件建立一個文件內部讀寫位置指針(也稱為文件內部記錄指針),該指針在對文件的讀寫過程中用于指示文件的當前讀寫位置,每次對文件進行了讀或寫之后,文件位置指針自動更新指向下一個新的讀寫位置。
文件尾的檢測程序中需要判斷所處理的文件是否處理完成,即文件的讀寫位置指針是否已經移動到了文件尾標志處。對于文本文件,由于任何一個字符的編碼均不是-1,所以可以用-1表示文本文件的文件尾標志,系統中用符號常量EOF來表示。二進制文件中,使用EOF符號常量并不能正確地表示出文件的結尾。ANSIC提供了一個測試文件狀態的函數:int
feof(FILE*stream);功能:測試由stream所對應文件的內部記錄指針是否移動到了文件結尾。當內部文件記錄指針未到文件尾時,函數返回0值;當內部文件記錄指針到達文件尾時,函數返回非0值。5.2文件數據的讀寫方法C程序設計語言提供了一系列關于文件數據讀寫的函數,下面分別討論文件中單個字符數據的讀寫、文件中字符串數據的讀寫、文件中格式化數據的讀寫以及文件中數據塊的讀寫方法和簡單應用。
文件中的單個字符讀寫操作int
fgetc(FILE*stream);功能:從與文件指針變量stream相關聯的文件中讀取一個字符讀取位置由文件的內部記錄指針指定成功:返回其讀取的字符ASCII碼值文件結束或者執行出錯:返回EOF(-1)文件中的單個字符讀寫操作int
fputc(intc,FILE*stream);功能:將用變量c表示的字符數據寫到與文件指針變量stream相關聯的文件寫入位置由文件的內部記錄指針所指定執行成功:返回被寫入文件的字符值執行錯誤:返回EOF
文件中的單個字符讀寫操作例5.1將從鍵盤上輸入的若干字符數據寫入文本文件mydata.txt。(提示:需要結束鍵盤輸入時,輸入ctrl+z(EOF)后按回車鍵。)/*Name:ex0501.cpp*/#include<stdio.h>intmain(){ FILE*fp; charch;
fp=fopen("mydata.txt","w");
if(fp==NULL) {
printf("Can'tcreatefilemydata.txt!\n"); return-1; }
printf("請輸入字符串,用Ctrl+Z<CR>結束輸入:\n");
while((ch=getchar())!=EOF) //從鍵盤上輸入字符寫入文件mydata.txt
fputc(ch,fp);
fclose(fp); return0;}通過使用fputc函數的調用,依次將鍵盤輸入的字符寫入關聯的文件中
文件中的單個字符讀寫操作例5.2從文件mydata.txt(程序ex0501.cpp創建)中讀出所有字符數據,并在系統標準輸出設備顯示器上輸出。if((fp=fopen("mydata.txt","w"))==NULL){
printf("Can'tcreatefilemydata.txt!\n"); return;}printf("請輸入寫入文件的字符數據:\n");do{
ch=fgetc(fp);
putc(ch); }while(ch!=EOF);fclose(fp);文件中的單個字符讀寫操作例5.3編制能夠實現文件拷貝功能的程序。文件名在程序運行時從鍵盤提供,要求:(1)文件數據拷貝部分使用單獨的函數實現。(2)程序既能實現文本文件的拷貝,又能夠是實現二進制文件的拷貝。voidfilecopy(FILE*fin,FILE*fout) //文件拷貝函數的定義{ charch; while(1) {
ch=fgetc(fin);
if(!feof(fin))
fputc(ch,fout); else break; }
文件中的字符串讀寫操作char*fgets(char*string,intn,FILE*stream);功能:從與文件指針變量stream相關聯的文件中最多讀取n-1個字符,添加上字符串結尾字符’\0’構成字符串后存放到string所代表的字符串對象中去。如果在讀入n-1個字符前遇到換行符’\n’或文件結束符EOF時操作也將結束,將遇到的換行符作為一個有效字符處理,然后在讀入的字符串末尾自動加上一個字符串結尾符’\0’后存放到string所代表的字符串對象中,函數執行出錯或遇到了文件的結束標志時返回NULL。
文件中的字符串讀寫操作int
fputs(constchar*string,FILE*stream);功能:將string所代表的字符串寫入文件指針變量stream相關聯的文件。函數fputs正常執行時返回寫入文件中的字符個數,函數執行出錯時返回值為EOF。注意:fputs在向文件中寫入字符串時已經去掉了字符串的結尾標志‘\0’,因而連續寫入的字符串不能被正確地分隔而成為了一個字符串。為了使得寫入文件中的字符串能夠被正常地區別和處理,在使用fputs標準庫函數向文件中寫入字符串數據時每寫入一個字串后要自行在其后添加一個分隔標志字符,為了與讀字符串標準庫函數fgets配合,使用換行符(‘\n’)作為分隔字符。
文件中的字符串讀寫操作例5.5從鍵盤上讀入若干行字符串并將它們存放到指定文件中,僅輸入一個回車時結束輸入過程,
if((fp=fopen(fn,"w"))==NULL){ printf("Can'tcreatefile.!\n"); return;}while(strlen(gets(str))>0){
fputs(str,fp);
fputc('\n',fp););//每個字符串數據后寫入一個換行符以分隔寫入的字符串數據}文件中的字符串讀寫操作程序在成功創建文件后,反復輸入字符串寫入指定文件,每寫入一個字符串立即寫入一個換行符作為子串與字串之間的分隔符號,操作直到某次輸入直接按回車鍵為止(此時輸入的是空串,其字符串長度為0),最后關閉已寫入字符串內容的文件。程序一次執行的輸入數據如下所示:kdfhksdhfkjdsf //輸入數據Dfjsdlkfjsdlkfjlksdjhfklsdsdf;ljsdlkfjlksdjhflk //輸出數據fjksdhfjksdhkfhdslkf文件中的格式化讀寫操作int
fscanf(FILE*stream,constchar*format[,argument]...);函數fscanf與格式化輸入函數scanf的功能基本相同,不同的是scanf函數的數據來源于標準輸入設備(鍵盤),而fscanf函數的數據來源于與stream相關聯的文件,函數的返回值指出了函數正確處理的數據項個數。int
fprintf(FILE*stream,constchar*format[,argument]...);函數fprintf與格式化輸出函數printf的功能基本相同,不同的是printf函數輸出數據的目的地是標準輸出設備(顯示器),而fprintf函數輸出數據的目的地是由stream指定的文件,函數的返回值指出了函數正確寫入文件中的字節數。文件中的格式化讀寫操作例5.7編程序實現功能:隨機產生100個具有3位整數、2位小數的雙精度實數,將它們依次寫入到指定文件中,兩個數據之間用空格分隔,文件名在程序運行時從鍵盤提供。
FILE*f; doublex;
inti; charfn[50];
printf("請輸入文件名:");
gets(fn);
if((f=fopen(fn,"wb"))==NULL) {
printf("創建文件失敗!\n"); return-1; }
srand(time(NULL));
for(i=0;i<100;i++) { x=100+rand()%900+rand()%100*1e-2; fprintf(f,"%.2lf",x);//注意控制格式,寫入數據用空格分隔
}
fclose(f); return0;文件中的格式化讀寫操作例5.8讀出例5.7創建的文件數據中所有數據,然后將它們按降序排序后輸出。/*Name:ex0508.cpp*/#include<stdio.h>#defineN100voidsort(double
v[],intn);voidprintarray(double
v[],intn);intmain(){ FILE*fp; doublea[N];
inti;文件中的格式化讀寫操作charfn[50];
printf("請輸入文件名:");
gets(fn);
if((fp=fopen(fn,"rb"))==NULL) {
printf("打開文件失敗!\n"); return-1; }
for(i=0;i<N;i++)
fscanf(fp,"%lf",&a[i]);
fclose(fp);
sort(a,N); //調用排序函數進行排序
printarray(a,N); //調用輸出函數進行顯示
return0;}文件中的格式化讀寫操作voidsort(double
v[],intn){
int
i,j,k; doublet;
for(i=0;i<n-1;i++) { k=i;
for(j=i+1;j<n;j++)
if(v[j]>v[k]) k=j;
if(k!=i) t=v[i],v[i]=v[k],v[k]=t; }}文件中的格式化讀寫操作voidprintarray(double
v[],intn){
inti;
for(i=0;i<n;i++) { printf("%7.2lf",v[i]); if((i+1)%10==0)
printf("\n"); }}文件中的數據塊讀寫操作size_t
fread(void*buffer,size_tsize,size_tcount,FILE*stream);功能:從與文件指針變量stream相關聯的文件中按指定長度讀取一個數據塊到內存儲器的指定區域。函數的返回值是該函數執行時正確從指定文件中讀出的數據項數(應該與count參數指出的相同)。如果在讀出操作中出現了錯誤則返回值小于count參數指出的應讀出數據項數。文件中的數據塊讀寫操作size_t
fwrite(constvoid*buffer,size_tsize,size_tcount,FILE*stream);功能:將內存儲器中指定區域的數據塊寫入到與文件指針變量stream相關聯的文件中。函數的返回值是該函數執行時正確寫入文件中的數據項數(應該與count參數指出的相同)。如果在寫入操作中出現了錯誤則返回值小于count參數指出的寫入數據項數。
文件中的數據塊讀寫操作函數fread和fwrite用到的4個參數意義時相同的,只不過函數規定的操作方向剛好相反。四個參數的基本意義如下:(1)buffer:參數buffer指定數據在內存儲器中存儲區域首地址。(2)size:參數size指定被操作的一個數據項的字節長度。(3)count:參數count指定一次函數操作(調用)所涉及長度為size的數據項個數,由此可知函數每次操作數據塊的字節長度為size*count。(4)stream:參數stream是與被處理文件相關聯的文件類型指針變量,指出被操作的文件。文件中的數據塊讀寫操作例5.10將一個5x10的整型二維數組數據存入到指定文件中(數組數據用隨機數填充)。/*Name:ex0510.cpp*/#include<stdlib.h>#include<stdio.h>#include<time.h>#defineM5#defineN10intmain(){ voidmkarr(int
v[],int
m,intn);
int
a[M][N],i; FILE*f;charfn[50];
printf("請輸入文件名:");
gets(fn);
if((f=fopen(fn,"wb"))==NULL) {
printf("Can'tcreatefile.\n"); return-1; }文件中的數據塊讀寫操作mkarr(a[0],M,N);
for(i=0;i<M;i++)/*可用fwrite(a,sizeof(int),M*N,f);代替整個循環*/
fwrite(a[i],sizeof(int),N,f);
fclose(f); return0;}voidmkarr(int
v[],int
m,intn){int
i,j;
srand((unsigned)time(NULL));
for(i=0;i<m;i++)
for(j=0;j<n;j++)
v[i*n+j]=rand()%100;}上面程序代碼中,定義了一個5行10列的二維數組,調用函數mkarr用兩位以內的隨機數填充數組元素。然后利用循環,每次將二維數組中的一行寫入文件,循環5次將二維數組全部數據寫入的文件中。寫入數據到文件中時,也可以考慮將二維數組一次性寫入文件,寫入函數的調用方法參見程序中的注釋。5.3隨機存取文件處理基礎文件的順序存取中,文件內部記錄指針在對文件進行每一次讀或寫操作之后都會自動向后移動與讀寫方式相適應的距離,將文件內部記錄指針定位到下一次在文件中讀或寫的位置上。文件的隨機存取就是使用C標準庫中提供的移動文件內部讀寫位置指針標準庫函數,將讀寫位置指針移動到要處理的文件數據區指定位置,然后再通過使用文件數據讀寫標準庫函數進行處理,從而實現修改文件部分內容的功能、提高文件數據處理效率。
文件的隨機存取處理應該分為兩個步驟:第一步是按要求移動文件內部記錄指針到指定的讀寫位置;第二步用系統提供的讀寫方法讀寫所需要的信息。文件的操作位置指針和文件定位1重置文件內部記錄指針voidrewind(FILE*stream);功能:將由stream所關聯文件的文件內部記錄指針從任何位置重新撥回文件開頭。例5.12
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年山西機電職業技術學院高職單招高職單招英語2016-2024歷年頻考點試題含答案解析
- 2025年山東畜牧獸醫職業學院高職單招高職單招英語2016-2024歷年頻考點試題含答案解析
- 2025年安順職業技術學院高職單招高職單招英語2016-2024歷年頻考點試題含答案解析
- 2025年寧波城市職業技術學院高職單招職業技能測試近5年常考版參考題庫含答案解析
- BLS培訓課件教學課件
- 2023年工作總結報告
- 膽源性胰腺炎護理
- 119消防安全講座課件
- 新能源冷暖設備供應及施工承包合同
- 2025年濟南濼口實驗學校八年級下學期物理期中前測考試試卷(含答案)
- 安徽省蕪湖市無為市部分學校2023-2024學年八年級下學期期中數學試題
- 《婦女保健與營養》課件
- Improve6西格瑪改善階段綠帶教材
- 預防便秘的健康宣教內容
- 2024年蜀道集團招聘筆試參考題庫含答案解析
- 初中語文九年級下冊第四單元作業設計單元質量檢測作業
- 2022輔警考試《道路交通安全法》基礎知識題庫(帶答案)
- 液壓仿真技術的現狀及發展趨勢
- nrf2and通路在藥物治療中的作用
- 高考語文復習:詩歌語言鑒賞
- 泌尿外科常見疾病診療指南
評論
0/150
提交評論