模板
模板是泛型編程的基礎(chǔ),泛型編程即以一種獨(dú)立于任何特定類型的方式編寫(xiě)代碼。
模板是創(chuàng)建泛型類或函數(shù)的藍(lán)圖或公式。庫(kù)容器,比如迭代器和算法,都是泛型編程的例子,它們都使用了模板的概念。
每個(gè)容器都有一個(gè)單一的定義,比如 向量,我們可以定義許多不同類型的向量,比如 vector <int> 或 vector <string>。
可以使用模板來(lái)定義函數(shù)和類。
函數(shù)模板
模板函數(shù)定義的一般形式如下所示:
template <class type> ret-type func-name(parameter list) { // 函數(shù)的主體 }
在這里,type 是函數(shù)所使用的數(shù)據(jù)類型的占位符名稱。這個(gè)名稱可以在函數(shù)定義中使用。
類模板
如定義函數(shù)模板一樣,也可以定義類模板。泛型類聲明的一般形式如下所示:
template <class type> class class-name {
.
.
}
例
/*-----函數(shù)模版-----*/
/* T const & 是一體的,& 不是和Max一體,這表示返回類型是引用類型并且是不可修改的const類型*/
template<typename T>
inline T const &Max(T const &a, T const &b) {
return a < b ? b : a;
}
/*-----類模版------*/
template <class T>
class Stack {
private:
vector<T> elems; // 元素
public:
void push(T const&); // 入棧
void pop(); // 出棧
T top() const; // 返回棧頂元素
bool empty() const{ // 如果為空則返回真。
return elems.empty();
}
};
template <class T>
void Stack<T>::push (T const& elem)
{
// 追加傳入元素的副本
elems.push_back(elem);
}
文件和流
| 數(shù)據(jù)類型 | 描述 |
|---|---|
| ofstream | 該數(shù)據(jù)類型表示輸出文件流,用于創(chuàng)建文件并向文件寫(xiě)入信息。 |
| ifstream | 該數(shù)據(jù)類型表示輸入文件流,用于從文件讀取信息。 |
| fstream | 該數(shù)據(jù)類型通常表示文件流,且同時(shí)具有 ofstream 和 ifstream 兩種功能,這意味著它可以創(chuàng)建文件,向文件寫(xiě)入信息,從文件讀取信息。 |
打開(kāi)文件
在從文件讀取信息或者向文件寫(xiě)入信息之前,必須先打開(kāi)文件。open() 函數(shù)是 fstream、ifstream 和 ofstream 對(duì)象的一個(gè)成員。
void open(const char *filename, ios::openmode mode);
在這里,open() 成員函數(shù)的第一參數(shù)指定要打開(kāi)的文件的名稱和位置,第二個(gè)參數(shù)定義文件被打開(kāi)的模式。
| 模式標(biāo)志 | 描述 |
|---|---|
| ios::app | 追加模式。所有寫(xiě)入都追加到文件末尾。 |
| ios::ate | 文件打開(kāi)后定位到文件末尾。 |
| ios::in | 打開(kāi)文件用于讀取。 |
| ios::out | 打開(kāi)文件用于寫(xiě)入。 |
| ios::trunc | 如果該文件已經(jīng)存在,其內(nèi)容將在打開(kāi)文件之前被截?cái)?,即?strong>文件長(zhǎng)度設(shè)為 0。 |
您可以把以上兩種或兩種以上的模式結(jié)合使用。例如,如果想要以寫(xiě)入模式打開(kāi)文件,并希望截?cái)辔募?,以防文件已存在,那么您可以使用下面的語(yǔ)法:
ofstream outfile;
outfile.open("file.dat", ios::out | ios::trunc );
類似地,您如果想要打開(kāi)一個(gè)文件用于讀寫(xiě),可以使用下面的語(yǔ)法:
ifstream afile;
afile.open("file.dat", ios::out | ios::in );
關(guān)閉文件
當(dāng) C++ 程序終止時(shí),它會(huì)自動(dòng)關(guān)閉刷新所有流,釋放所有分配的內(nèi)存,并關(guān)閉所有打開(kāi)的文件。但程序員應(yīng)該養(yǎng)成一個(gè)好習(xí)慣,在程序終止前關(guān)閉所有打開(kāi)的文件。
void close();
寫(xiě)入文件
使用流插入運(yùn)算符( << )向文件寫(xiě)入信息,就像使用該運(yùn)算符輸出信息到屏幕上一樣。唯一不同的是,在這里您使用的是 ofstream 或 fstream 對(duì)象,而不是 cout 對(duì)象。
讀取文件
使用流提取運(yùn)算符( >> )從文件讀取信息,就像使用該運(yùn)算符從鍵盤輸入信息一樣。唯一不同的是,在這里您使用的是 ifstream 或 fstream 對(duì)象,而不是 cin 對(duì)象。
#include <fstream>
#include <iostream>
using namespace std;
int main() {
char data[100];
//以寫(xiě)模式打開(kāi)文件
ofstream outfile;
outfile.open("afile.dat");
cout << "Writing to the file" << endl;
cout << "Enter your name: ";
//讀取輸入數(shù)據(jù)
cin.getline(data, 100);
//向文件寫(xiě)入用戶數(shù)據(jù)
outfile << data << endl;
cout << "Enter your age: ";
cin >> data;
cin.ignore();
// 再次向文件寫(xiě)入用戶輸入的數(shù)據(jù)
outfile << data << endl;
// 關(guān)閉打開(kāi)的文件
outfile.close();
// 以讀模式打開(kāi)文件
ifstream infile;
infile.open("afile.dat");
cout << "Reading from the file" << endl;
infile >> data;
// 在屏幕上寫(xiě)入數(shù)據(jù)
cout << data << endl;
// 再次從文件讀取數(shù)據(jù),并顯示它
infile >> data;
cout << data << endl;
// 關(guān)閉打開(kāi)的文件
infile.close();
return 0;
}
文件位置指針
istream 和 ostream 都提供了用于重新定位文件位置指針的成員函數(shù)。這些成員函數(shù)包括關(guān)于 istream 的 seekg("seek get")和關(guān)于 ostream 的 seekp("seek put")。
__istream_type& seekg(pos_type);
__istream_type& seekg(off_type, ios_base::seekdir);
seekg 和 seekp 的參數(shù)通常是一個(gè)長(zhǎng)整型。第二個(gè)參數(shù)可以用于指定查找方向。
查找方向可以是 ios::beg(默認(rèn)的,從流的開(kāi)頭開(kāi)始定位),也可以是 ios::cur(從流的當(dāng)前位置開(kāi)始定位),也可以是 ios::end(從流的末尾開(kāi)始定位)。
文件位置指針是一個(gè)整數(shù)值,指定了從文件的起始位置到指針?biāo)谖恢玫?strong>字節(jié)數(shù)。下面是關(guān)于定位 "get" 文件位置指針的實(shí)例:
// 定位到 fileObject 的第 n 個(gè)字節(jié)(假設(shè)是 ios::beg)
fileObject.seekg( n );
// 把文件的讀指針從 fileObject 當(dāng)前位置向后移 n 個(gè)字節(jié)
fileObject.seekg( n, ios::cur );
// 把文件的讀指針從 fileObject 末尾往回移 n 個(gè)字節(jié)
fileObject.seekg( n, ios::end );
// 定位到 fileObject 的末尾
fileObject.seekg( 0, ios::end );
STL 概述
C++ STL(標(biāo)準(zhǔn)模板庫(kù))是一套功能強(qiáng)大的 C++ 模板類,提供了通用的模板類和函數(shù),這些模板類和函數(shù)可以實(shí)現(xiàn)多種流行和常用的算法和數(shù)據(jù)結(jié)構(gòu),如向量、鏈表、隊(duì)列、棧。
C++ 標(biāo)準(zhǔn)模板庫(kù)的核心包括以下三個(gè)組件:
| 組件 | 描述 |
|---|---|
| 容器(Containers) | 容器是用來(lái)管理某一類對(duì)象的集合。C++ 提供了各種不同類型的容器,比如 deque、list、vector、map 等。 |
| 算法(Algorithms) | 算法作用于容器。它們提供了執(zhí)行各種操作的方式,包括對(duì)容器內(nèi)容執(zhí)行初始化、排序、搜索和轉(zhuǎn)換等操作。 |
| 迭代器(iterators) | 迭代器用于遍歷對(duì)象集合的元素。這些集合可能是容器,也可能是容器的子集。 |
示例演示了向量容器(一個(gè) C++ 標(biāo)準(zhǔn)的模板),它與數(shù)組十分相似,唯一不同的是,向量在需要擴(kuò)展大小的時(shí)候,會(huì)自動(dòng)處理它自己的存儲(chǔ)需求。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// 創(chuàng)建一個(gè)向量存儲(chǔ) int
vector<int> vec;
int i;
// 顯示 vec 的原始大小
cout << "vector size = " << vec.size() << endl;
// 推入 5 個(gè)值到向量中
for(i = 0; i < 5; i++){
vec.push_back(i);
}
// 顯示 vec 擴(kuò)展后的大小
cout << "extended vector size = " << vec.size() << endl;
// 訪問(wèn)向量中的 5 個(gè)值
for(i = 0; i < 5; i++){
cout << "value of vec [" << i << "] = " << vec[i] << endl;
}
// 使用迭代器 iterator 訪問(wèn)值
vector<int>::iterator v = vec.begin();
while( v != vec.end()) {
cout << "value of v = " << *v << endl;
v++;
}
return 0;
}