1. 程式人生 > >C++程式設計學習筆記 複習/拾遺 4

C++程式設計學習筆記 複習/拾遺 4

類和物件應用

基於專案的多檔案管理

  1. 將類的設計與類的使用分離

類定義與main函式(類測試) 不在一個檔案中。

  1. 將類的宣告和類的成員函式實現分離

類定義與成員函式定義
不在一個檔案中

優點:
便於分工合作
便於軟體的維護。

例5.1:設計一個圓類,並計算圓的面積
//類的定義(Circle.h檔案)
class Circle
{
	public:
		Circle(double a=0);
		double Area();	
	protected:
		double r;
};

//類的成員函式實現( Circle.cpp檔案)
#include   "Circle.h"
Circle::Circle(double a)
{
	r=a;
}
double Circle::Area()
{
	return 3.14*r*r;
}

// 主函式(main.cpp檔案)
#include <iostream>
#include "Circle.h"
using namespace std;
int main()
{
	 Circle c(5);
	 cout<<c.Area()<<endl; 	
    return 0;
}
 

步驟

1、建立一個控制檯型別的專案L5.1,帶一個main.cpp檔案,其內容是main函式
2、在L5.1工程中為circle類建立2個檔案(circle.h和circle.cpp檔案)
1)在專案管理面板的專案名L5.1上右鍵單擊,選擇新建檔案,新增新檔案,如圖所示。

在這裡插入圖片描述
注意手動操作,新建的檔案與專案檔案要儲存在同一個目錄下。

2)檔案->新建->新建一個類,或者檢視類面板上右鍵單擊,選擇新建類,如圖所示:
在這裡插入圖片描述
系統自動加了框架程式碼。
在這裡插入圖片描述

  1. 輸入類名circle
  2. 輸入建構函式引數
  3. 勾選建立建構函式
  4. 預設檔名circle.cpp及circle.h
  5. 單擊新建類的對話方塊中的建立按鈕,即為circle類建立了2個檔案

最後按照例5.1程式碼所在檔案情況,依次新增到相應位置:
在這裡插入圖片描述

例項

#include <iostream>
#include <string>
using namespace std;
class student
{
public:
	void output();
	void set(const string &p,int i,double x,double y)//[4]
	{	name=p;	num=i;	m_c=x;	m_math=y;}
	double jstotal()//[5]
	{	return m_c+m_math;	}
	student(const string &p="wang",int i=1,double x=0,double y=0)//[7]
	{	name=p;	num=i;	m_c=x;	m_math=y;}
private:
	string name;//姓名
	int num ; //學號
	double m_c;//語文成績
	double m_math;//數學成績
};
void student::output()
{
cout<<"姓名:"<<name<<","<<"學號:"<< num<<","
<<"語文:"<< m_c<<","<<"數學:"<< m_math <<endl;//[4]
}
int main()
{
	//string x("wang");//等價於string x="wang";
	//student s;//[1]定義物件
	//s.set(x,1,85.5);//[2]設定學生資料
	//s.output();//[3]輸出學生資料
	//s.set(x,1,92.1);//[4]修改學生成績資料
	//cout<<"總成績:"<<s.jstotal()<<endl;//[6]
	student t;//[8]定義物件t
	t.output();//[8]輸出學生資料
	cout<<"總成績:"<<t.jstotal()<<endl;//[8]
	student z("liuxiang",2,100,95);//定義物件z
	z.output(); 
	cout<<"總成績:"<<z.jstotal()<<endl;
	return 0;
}

student.h:類定義

#include <string>
using namespace std;
class student
{
	public:
	void output();
	void set(const string &p,int i,double x,double y);
	double jstotal();
	student(const string &p="wang",int i=1,double x=0,double y=0);
	protected:
	string name;//姓名
	int num ; //學號
	double m_c;//語文成績
	double m_math;//數學成績
};

student.cpp:成員函式定義

#include "student.h"
#include <iostream>
#include <string>
using namespace std;
void student::output()
{
cout<<"姓名:"<<name<<","<<"學號:"<< num<<","
<<"語文:"<< m_c<<","<<"數學:"<< m_math <<endl;//[4]
}
void student::set(const string &p,int i,double x,double y)//[4]
{	name=p;	num=i;	m_c=x;	m_math=y;}

double student::jstotal()//[5]
{	return m_c+m_math;	}

student::student(const string &p,int i,double x,double y)//[7]
{	name=p;	num=i;	m_c=x;	m_math=y;}

專案:main.cpp:類測試

#include <iostream>
#include <string>
#include "student.h"
using namespace std;
int main() {
	//string x("wang");//等價於string x="wang";
	//student s;//[1]定義物件
	//s.set(x,1,85.5);//[2]設定學生資料
	//s.output();//[3]輸出學生資料
	//s.set(x,1,92.1);//[4]修改學生成績資料	
	//cout<<"總成績:"<<s.jstotal()<<endl;//[6]
	student t;//[8]定義物件t
	t.output();//[8]輸出學生資料
	cout<<"總成績:"<<t.jstotal()<<endl;//[8]
	student z("liuxiang",2,100,95);//定義物件z
	z.output(); 
	cout<<"總成績:"<<z.jstotal()<<endl;
	return 0;
}

系統這些標頭檔案中的內容包含是因為系統這些標頭檔案中的內容包含ifndef或者#pragma once,該巨集就是為了避免同一個標頭檔案被include多次時,不會出現重定義的錯誤。

輸入/輸出流類的繼承層次結構

iostream類庫提供了數百種I/O功能,其介面部分分別包含在幾個標頭檔案中:
無格式I/O和格式化I/O:標頭檔案iostream

格式化I/O :包含標頭檔案iomanip

檔案處理操作 :包含標頭檔案fstream

注意:iostream屬於多繼承

在這裡插入圖片描述

檔案操作

  • 檔案和流
    在這裡插入圖片描述
    C++把每一個檔案都看成一個有序的位元組流,對檔案的操作可採用與輸入輸出流相關的方法。

標頭檔案fstream包含了流類ifstream(從檔案輸入)、ofstream(向檔案輸出)和fstream(從檔案輸入/輸出)的定義。

  • 檔案的處理由三個步驟組成:開啟檔案,讀寫,關閉檔案。
  1. 開啟檔案,兩種方法:

1)先建立檔案流物件,再呼叫成員函式open()將它與某一個檔案關聯 ifstream infile; // 輸入檔案流物件
infile.open(“a.txt”); infile.open(“a.dat”,ios::binary); //開啟讀二進位制檔案
2)在建立檔案流物件的同時通過建構函式來開啟檔案。如:
ifstream infile (“a.txt”);
ifstream outfile(“a.dat”,ios::binary);//開啟讀二進位制檔案 測試檔案是否被正確開啟的方法如下: if ( ! infile) { … // 處理檔案開啟失敗情況的程式碼 }

  1. 關閉檔案:成員函式close()

    infile.close( );//等價於if(!infile.is_open())或if(!infile.fail())


  1. 開啟檔案,兩種方法:
    1)先建立檔案流物件,再呼叫成員函式open()將它與某一個檔案關聯
    ofstream outfile; // 輸出檔案流物件
    outfile.open("a.txt ");
    outfile.open(“a.txt”,ios::binary); //開啟寫二進位制檔案
    2)在建立檔案流物件的同時通過建構函式來開啟檔案。如:
    ofstream outfile (“a.txt”);
    ofstream outfile(“a.dat”,ios::binary);//開啟寫二進位制檔案
    測試檔案是否被正確開啟的方法如下:
    if ( ! outfile)
    { …// 處理檔案開啟失敗情況的程式碼
    }
  2. 關閉檔案:成員函式close()
    outfile.close( );//等價於if(!outfile.is_open())或if(!outfile.fail())

  1. 開啟檔案,兩種方法:
    1)先建立檔案流物件,再呼叫成員函式open()將它與某一個檔案關聯
    fstream iofile; // 輸入輸出檔案流物件
    iofile.open(檔名,檔案開啟方式);//不能省略
    2)在建立檔案流物件的同時通過建構函式來開啟檔案。檔案開啟方式不能省略。如下:
    fstream iofile(檔名, ios::in);//讀文字檔案
    fstream iofile(檔名, ios::out);//寫文字檔案
    fstream iofile(檔名, ios::in|ios::binary);//讀二進位制檔案
    fstream iofile(檔名, ios::out|ios::binary);//寫二進位制檔案
    測試檔案是否被正確開啟的方法如下:
    if ( ! iofile)
    { … // 處理檔案開啟失敗情況的程式碼
    }
  2. 關閉檔案:成員函式close()
    iofile.close( );//等價於if(!iofile.is_open())或if(!iofile.fail())

在這裡插入圖片描述

文字檔案的讀寫

使用插入與提取運算子對文字檔案進行讀寫

在這裡插入圖片描述


例5.3:寫文字檔案示例

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
	ofstream outfile("d:\\grade.txt");
	//等價於:fstream outfile("d:\\grade.txt",ios::out);
	//寫文字檔案

	if(!outfile)	
	{	
		cout << "檔案開啟失敗!"<<endl;
		return 1;	
	}
	outfile << "程式設計" << "  " << 95 << endl;
	outfile << "大學英語" << "  " << 90.5 << endl;
	outfile << "高等數學" << "  " << 93 << endl;
	outfile << "普通物理" << "  " << 87.5 << endl;
	outfile.close();
	return 0;			
} 

在這裡插入圖片描述

例5.4:讀文字檔案示例

#include <iostream>
#include <fstream>
using namespace std;
int main()
{	ifstream infile("d:\\grade.txt");
//等價於:fstream infile(“d:\\grade.txt”,ios::in);
//讀文字檔案

	if(!infile)
	{	
		cout << "檔案開啟失敗!"<<endl;
		return 1;	
	}
	char course[20];
	float score;
	infile >> course >> score;
	cout << course << "  " << score << endl;
	infile >> course >> score;
	cout << course << "  " << score << endl;
	infile >> course >> score;
	cout << course << "  " << score << endl;
	infile >> course >> score;
	cout << course << "  " << score << endl;
	infile.close();
	return 0;
} 

在這裡插入圖片描述

例5.5 使用成員函式get()完成讀文字檔案操作

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
	char ch;
	int count=0;		// 計數器
	ifstream infile("d:\\grade.txt");
	//等價於:fstream infile("d:\\grade.txt",ios::in);
	//讀文字檔案

	if(!infile)
	{	
		cout << "檔案開啟失敗"<<endl;
		return 1;
	}
	while(!infile.eof( ))  	
	{
		infile.get(ch);		// 從檔案流中讀入下一個字元
		cout<<ch;		// 螢幕輸出從檔案中讀入的字元
		if(ch>='0' && ch<='9') count++;  // 若是數字字元,計數器加1
	}
	cout<<endl<<"檔案中共有數字字元:"<<count<<"個。"<<endl;
	infile.close();
	return 0;
} 

在這裡插入圖片描述

例5.6: 開啟一個由若干個整陣列成的文字檔案“number.txt”,找出其中所有的質數並存入另一個文字檔案“prime.txt”中。

#include <iostream>
#include <fstream>
using namespace std;
int isprime(int a) 		// 素數判別函式
{	for(int i=2; i<=a/2; i++)
		if(a%i == 0) return 0; 
	return 1;
}
int main()
{	ifstream infile("number.txt");
	ofstream outfile("prime.txt");
	if(!infile || !outfile)
	{	cout << "檔案開啟失敗!"<<endl;
		return 1;	
	}
	int num;
	while(!infile.eof() )		
	{	infile>>num;
		if(isprime(num)) outfile<<num<<"  ";
	}	
	infile.close();
	outfile.close();
	return 0;
} 

二進位制檔案

二進位制檔案以位(bit)為單位,整個檔案是由0和1組成的無格式的原始資料序列。在二進位制方式下的輸入輸出過程中,系統不對資料進行任何轉換。
文字檔案以位元組(byte)為單位,整個檔案實際儲存的是一串ASCII字元。可用文書處理器進行編輯。在文字方式下的輸入輸出過程中,系統進行字元轉換。

二進位制檔案讀寫

二進位制檔案的讀寫比文字檔案複雜,不能用插入或提取符。

①put()函式向流寫入一個字元,其原型是ofstream &put(char ch),使用也比較簡單,如file1.put(‘c’);就是向流寫一個字元’c’。
②get()函式從流讀入字元或者字串,比較靈活,有3種常用的過載形式。
③讀寫資料塊   要讀寫二進位制資料塊,使用成員函式read()和write()成員函式,它們原型如下:

 read(unsigned char *buf,int num);    
 write(const unsigned char *buf,int num);

read()從檔案中讀取 num 個字元到 buf 指向的快取中
write() 從buf 指向的快取寫 num 個字元到檔案中

// 例5.7:二進位制檔案拷貝的程式
#include <iostream>
#include <fstream>
using namespace std;
int main()
{	char s[50], d[50];
	cout<<"請輸入準備複製的檔名(含字尾名):";
	cin>>s;
	cout<<"請輸入新生成的檔名(含字尾名):";
	cin>>d;
	ifstream infile(s, ios::binary);
	ofstream outfile(d, ios::binary);
	if(!infile || !outfile)
	{	cout << "檔案開啟失敗!"<<endl;
		return 1;	
	}
	int num;
	while(!infile.eof() )		
	{	infile.read ((char*)&num,sizeof(num));// 成員函式read( )用於從輸入流中讀取一個整數
		outfile.write((char*)&num,sizeof(num));// 成員函式write( )將讀入的整數num寫到輸出流中
	}
	infile.close();
	outfile.close();
	return 0;
}