模板:程式設計:C++:檔案

出自 陳富國維基館
於 2013年4月10日 (三) 17:21 由 Wells (對話 | 貢獻) 所做的修訂
前往: 導覽搜尋

C++的檔案讀寫

((參考課本第16章))

我們所認知的檔案是放在儲存媒體(硬碟、網路硬碟、磁帶等)上的,可以透過檔案總管對檔案進行open、close、copy、delete等動作;實際上,在我們的作業系統中,“檔案“基本上不單純,檔案這個名詞被抽象化可代表作業系統中所有的裝置,如果是在可讀寫的儲存媒體上,那麼這個檔案是可讀寫的,若是在僅供讀取的裝置上(光碟機),那麼這個檔案就只能被讀取。因此,程式要存取裝置,只要對該裝置的代表檔案進行開啟,對該裝置檔案進行讀或寫的動作,這樣的做法,將裝置的存取動作簡單化成為對檔案的讀寫,不必特別針對每個裝置的特性來處理輸入或輸出的動作。

因此,在C++中,有所謂的輸出輸入的資料流(istream, ostream類別),從這2個類別再向下衍生出2個檔案的輸入輸出類別:ifstream與ofstream。 而fstream就同時衍生自ifstream與ofstrean,同時具備對檔案的讀寫能力。底下是幾個操作檔案需注意的事項:

  • 檔案在操作上一定是先通過open()手段,指定一個欲開啟的檔案,在進行開檔的時候,可以指定要對檔案的操作型式,像是讀取、寫入、附加資料等。
  • 檔案的讀取方式:1.讀取一定數量的字元到一個資料緩衝區(通常是一個字元陣列),2.讀取單一個字元,3,讀取文字檔案中的一整行到一個資料緩衝區。
  • 一個檔案打開後,檔案指標指向檔頭,讀取或寫資料時,此指標會逐一字元往後,在讀檔案時,若讀出來的字元為"EOF"(End Of File),即表示到達檔案結尾,此時讀取檔案動作就應該停止。
  • 檔案打開後,若是有寫資料的動作,可以下flush(方法)將在資料緩衝區的資料寫回檔案,以確保所有的資料都正確地存入檔案。
  • 程式最終,要將打開的檔案以close()方法進行關檔的動作。

檔案的寫入方式最簡單,以前使用過的輸出cout本身就是一個檔案,當我們開啟一個檔案要進行寫入動作的時候,只需要將檔案的物件參考,比方說是file,替換掉cout即可,例如:

cout << "This is a test!\n";

換成:

file << "This is a test!\n";

這樣就可以將字串"This is a test!\n"寫入檔案。

課堂練習

將下列文字放入一個文字檔,再寫一程式將文字檔內容:

  1. 秀在螢幕上
  2. 寫入另一個檔案中

注意:寫完請舉手要求老師或小老師檢查。

問題:印出一數N的質因數
做法:
判斷2~(N-1)是否為N的因數,並且是否為質數

(i迴圈開始)
1.使用一迴圈敘述,使用迭代變數i,下限值為2,上限值為N-1,i若能整除N,則
  (j迴圈開始)
  1.1 使用一個布林變數isPrime,初值為true(此布林變數表示N是否為質數,程式一開始先認定N為質數)
  1.2 使用一迴圈敘述,使用迭代變數j,下限值為2,上限值為i-1,若j可整除i,設定isPrime為false,跳出j迴圈
  (j迴圈結束)
  1.3 若isPrime為tru則輸出j
(i迴圈結束)

2.結束

程式範例解答
#include <iostream>
using namespace std;
void main(void){
  int n;
  cout<<"請輸入";
  cin>>n;
  for(int i=2;i<= n-1;i++ ){
    if(n%i==0){
      bool Isprime=true;
      for(int j=2;j<=i-1&& Isprime;j++){
         if(i%j==0){
           Isprime=false;
           break;
        }
      }
      if (Isprime){
        cout<<i<<endl;
      }
    }
  }
  system("pause");
}

成績檔案讀取並分割欄位範例

有一成績檔score.txt,內容如下:

7525001,83,90,65
7525002,75,63,65
7525003,79,95,50
7525004,95,95,91
7525005,88,60,100
7525006,78,87,55
7525007,86,76,82
7525008,82,60,85
7525009,76,60,70
7525010,66,57,47
7525011,75,75,55
7525012,71,45,68
7525013,89,82,85
7525014,41,35,46
7525015,63,42,51
7525016,65,42,55
7525017,64,35,58
7525018,63,55,42
7525019,32,21,65
7525020,81,55,86
7525021,70,48,65
7525022,64,60,40
7525023,58,65,20
7525024,77,75,60
7525025,71,73,47
7525026,72,60,50
7525027,51,33,27
7525028,72,70,52
7525029,70,90,32
7525030,62,65,30
7525031,59,60,27
7525032,84,80,75
7525033,72,60,55
7525034,69,46,53
7525035,97,90,86
7525036,50,45,17
7525037,58,35,43

底下程式示範如何開啟score.txt,讀入每一行,並將每一行的欄位分開。

#include <iostream>
#include <fstream> 
using namespace std;

//字串分割函式,不需要改,直接使用,使用方式請看主程式main
char** str_split( char* str, char delim, int* numSplits ) 
{
    char** ret;
    int retLen;
    char* c;

    if ( ( str == NULL ) ||
        ( delim == '\0' ) )
    {
        /* Either of those will cause problems */
        ret = NULL;
        retLen = -1;
    }
    else
    {
        retLen = 0;
        c = str;

        /* Pre-calculate number of elements */
        do
        {
            if ( *c == delim )
            {
                retLen++;
            }

            c++;
        } while ( *c != '\0' );

        ret = (char **)malloc( ( retLen + 1 ) * sizeof( *ret ) );
        ret[retLen] = NULL;

        c = str;
        retLen = 1;
        ret[0] = str;

        do
        {
            if ( *c == delim )
            {
                ret[retLen++] = &c[1];
                *c = '\0';
            }

            c++;
        } while ( *c != '\0' );
    }

    if ( numSplits != NULL )
    {
        *numSplits = retLen;
    }

    return ret;
}

 
void main()
{
    char* strCpy; //複製的字串指標
    char** split; //分割出來的子字串陣列
    int num; //分割出來的子字串數量
    int i;
	
	ifstream file;       // 建立檔案輸出、輸入物件 
	char str[80];    // 每一行文字長度 
	file.open("c:\\temp\\score.txt",ios::in);
    while (! file.eof())  
    {  // 每次讀取一行至 buffer 陣列 
        file.getline(str,sizeof(str)); 

		split = str_split( str, ',', &num );//呼叫str_split函式,將str字串以逗點分割,傳出分割好的子字串陣列
		
		if ( split == NULL ) //如果字子字串陣列為空值(NULL)
		{       
			cout << "字串分割傳回空值" ;
		}
		else
		{			
			for ( i = 0; i < num; i++ )
			{
				cout <<  split[i] << "     "; // 輸出每一個子字串陣列的字串
			}
			cout << endl;
		}
		free(split);
	}
	file.close();
	system("pause");
}

程式結果如下:

7525001     83     90     65
7525002     75     63     65
7525003     79     95     50
7525004     95     95     91
7525005     88     60     100
7525006     78     87     55
7525007     86     76     82
7525008     82     60     85
7525009     76     60     70
7525010     66     57     47
7525011     75     75     55
7525012     71     45     68
7525013     89     82     85
7525014     41     35     46
7525015     63     42     51
7525016     65     42     55
7525017     64     35     58
7525018     63     55     42
7525019     32     21     65
7525020     81     55     86
7525021     70     48     65
7525022     64     60     40
7525023     58     65     20
7525024     77     75     60
7525025     71     73     47
7525026     72     60     50
7525027     51     33     27
7525028     72     70     52
7525029     70     90     32
7525030     62     65     30
7525031     59     60     27
7525032     84     80     75
7525033     72     60     55
7525034     69     46     53
7525035     97     90     86
7525036     50     45     17
7525037     58     35     43
請按任意鍵繼續 . . .

課堂練習作業

修改上面的程式,輸出底下資料:

學號	國文	數學	英語	總分
7525001	83	90	65	238
7525002	75	63	65	203
7525003	79	95	50	224
7525004	95	95	91	281
7525005	88	60	100	248
7525006	78	87	55	220
7525007	86	76	82	244
7525008	82	60	85	227
7525009	76	60	70	206
7525010	66	57	47	170
7525011	75	75	55	205
7525012	71	45	68	184
7525013	89	82	85	256
7525014	41	35	46	122
7525015	63	42	51	156
7525016	65	42	55	162
7525017	64	35	58	157
7525018	63	55	42	160
7525019	32	21	65	118
7525020	81	55	86	222
7525021	70	48	65	183
7525022	64	60	40	164
7525023	58	65	20	143
7525024	77	75	60	212
7525025	71	73	47	191
7525026	72	60	50	182
7525027	51	33	27	111
7525028	72	70	52	194
7525029	70	90	32	192
7525030	62	65	30	157
7525031	59	60	27	146
7525032	84	80	75	239
7525033	72	60	55	187
7525034	69	46	53	168
7525035	97	90	86	273
7525036	50	45	17	112
7525037	58	35	43	136
班級平均	70.48648649	61.75675676	56.75675676	189