設(shè)計網(wǎng)站賣錢seo百度點擊軟件
一 指針
每一個變量都有一個內(nèi)存位置,每一個內(nèi)存位置都定義了可使用連字號(&)運(yùn)算符訪問的地址,它表示了在內(nèi)存中的一個地址。
下面的實例,它將輸出定義的變量地址:
#include <iostream>using namespace std;int main ()
{int var1;char var2[10];cout << "var1 變量的地址: ";cout << &var1 << endl;cout << "var2 變量的地址: ";cout << &var2 << endl;return 0;
}
輸出:
var1 變量的地址: 0xbfebd5c0
var2 變量的地址: 0xbfebd5b6
1.1 什么是指針?
指針是一個變量,其值為另一個變量的地址,即,內(nèi)存位置的直接地址。就像其他變量或常量一樣,您必須在使用指針存儲其他變量地址之前,對其進(jìn)行聲明。指針變量聲明的一般形式為:
type *var-name;
在這里,type?是指針的基類型,它必須是一個有效的 C++ 數(shù)據(jù)類型,var-name?是指針變量的名稱。用來聲明指針的星號 * 與乘法中使用的星號是相同的。但是,在這個語句中,星號是用來指定一個變量是指針。以下是有效的指針聲明:
int *ip; /* 一個整型的指針 */
double *dp; /* 一個 double 型的指針 */
float *fp; /* 一個浮點型的指針 */
char *ch; /* 一個字符型的指針 */
所有指針的值的實際數(shù)據(jù)類型,不管是整型、浮點型、字符型,還是其他的數(shù)據(jù)類型,都是一樣的,都是一個代表內(nèi)存地址的長的十六進(jìn)制數(shù)。不同數(shù)據(jù)類型的指針之間唯一的不同是,指針?biāo)赶虻淖兞炕虺A康臄?shù)據(jù)類型不同。
1.2 C++中使用指針
使用指針時會頻繁進(jìn)行以下幾個操作:定義一個指針變量、把變量地址賦值給指針、訪問指針變量中可用地址的值。這些是通過使用一元運(yùn)算符?*?來返回位于操作數(shù)所指定地址的變量的值。下面的實例涉及到了這些操作:
#include <iostream>using namespace std;int main ()
{int var = 20; // 實際變量的聲明int *ip; // 指針變量的聲明ip = &var; // 在指針變量中存儲 var 的地址cout << "Value of var variable: ";cout << var << endl;// 輸出在指針變量中存儲的地址cout << "Address stored in ip variable: ";cout << ip << endl;// 訪問指針中地址的值cout << "Value of *ip variable: ";cout << *ip << endl;return 0;
}
輸出:
Value of var variable: 20
Address stored in ip variable: 0xbfc601ac
Value of *ip variable: 20
1.3 C++指針詳解
在 C++ 中,有很多指針相關(guān)的概念,這些概念都很簡單,但是都很重要。下面列出了 C++ 程序員必須清楚的一些與指針相關(guān)的重要概念:
概念 | 描述 |
---|---|
C++ Null 指針 | C++ 支持空指針。NULL 指針是一個定義在標(biāo)準(zhǔn)庫中的值為零的常量。 |
C++ 指針的算術(shù)運(yùn)算 | 可以對指針進(jìn)行四種算術(shù)運(yùn)算:++、--、+、- |
C++ 指針 vs 數(shù)組 | 指針和數(shù)組之間有著密切的關(guān)系。 |
C++ 指針數(shù)組 | 可以定義用來存儲指針的數(shù)組。 |
C++ 指向指針的指針 | C++ 允許指向指針的指針。 |
C++ 傳遞指針給函數(shù) | 通過引用或地址傳遞參數(shù),使傳遞的參數(shù)在調(diào)用函數(shù)中被改變。 |
C++ 從函數(shù)返回指針 | C++ 允許函數(shù)返回指針到局部變量、靜態(tài)變量和動態(tài)內(nèi)存分配。 |
二 引用
引用變量是一個別名,也就是說,它是某個已存在變量的另一個名字。一旦把引用初始化為某個變量,就可以使用該引用名稱或變量名稱來指向變量。
2.1 引用和指針
引用很容易與指針混淆,它們之間有三個主要的不同:
- 不存在空引用。引用必須連接到一塊合法的內(nèi)存。
- 一旦引用被初始化為一個對象,就不能被指向到另一個對象。指針可以在任何時候指向到另一個對象。
- 引用必須在創(chuàng)建時被初始化。指針可以在任何時間被初始化。
2.2 C++中創(chuàng)建引用
試想變量名稱是變量附屬在內(nèi)存位置中的標(biāo)簽,您可以把引用當(dāng)成是變量附屬在內(nèi)存位置中的第二個標(biāo)簽。因此,您可以通過原始變量名稱或引用來訪問變量的內(nèi)容。例如:
int i = 17;
我們可以為 i 聲明引用變量,如下所示:
int& r = i;
double& s = d;
在這些聲明中,& 讀作引用。因此,第一個聲明可以讀作 "r 是一個初始化為 i 的整型引用",第二個聲明可以讀作 "s 是一個初始化為 d 的 double 型引用"。下面的實例使用了 int 和 double 引用:
#include <iostream>using namespace std;int main ()
{// 聲明簡單的變量int i;double d;// 聲明引用變量int& r = i;double& s = d;i = 5;cout << "Value of i : " << i << endl;cout << "Value of i reference : " << r << endl;d = 11.7;cout << "Value of d : " << d << endl;cout << "Value of d reference : " << s << endl;return 0;
}
輸出:
Value of i : 5
Value of i reference : 5
Value of d : 11.7
Value of d reference : 11.7
引用通常用于函數(shù)參數(shù)列表和函數(shù)返回值。下面列出了 C++ 程序員必須清楚的兩個與 C++ 引用相關(guān)的重要概念:
概念 | 描述 |
---|---|
把引用作為參數(shù) | C++ 支持把引用作為參數(shù)傳給函數(shù),這比傳一般的參數(shù)更安全。 |
把引用作為返回值 | 可以從 C++ 函數(shù)中返回引用,就像返回其他數(shù)據(jù)類型一樣。 |
三 日期和時間
C++ 標(biāo)準(zhǔn)庫沒有提供所謂的日期類型。C++ 繼承了 C 語言用于日期和時間操作的結(jié)構(gòu)和函數(shù)。為了使用日期和時間相關(guān)的函數(shù)和結(jié)構(gòu),需要在 C++ 程序中引用 <ctime> 頭文件。
有四個與時間相關(guān)的類型:clock_t、time_t、size_t?和?tm。類型 clock_t、size_t 和 time_t 能夠把系統(tǒng)時間和日期表示為某種整數(shù)。
結(jié)構(gòu)類型?tm?把日期和時間以 C 結(jié)構(gòu)的形式保存,tm 結(jié)構(gòu)的定義如下:
struct tm {int tm_sec; // 秒,正常范圍從 0 到 59,但允許至 61int tm_min; // 分,范圍從 0 到 59int tm_hour; // 小時,范圍從 0 到 23int tm_mday; // 一月中的第幾天,范圍從 1 到 31int tm_mon; // 月,范圍從 0 到 11int tm_year; // 自 1900 年起的年數(shù)int tm_wday; // 一周中的第幾天,范圍從 0 到 6,從星期日算起int tm_yday; // 一年中的第幾天,范圍從 0 到 365,從 1 月 1 日算起int tm_isdst; // 夏令時
};
下面是 C/C++ 中關(guān)于日期和時間的重要函數(shù)。所有這些函數(shù)都是 C/C++ 標(biāo)準(zhǔn)庫的組成部分,可以在 C++ 標(biāo)準(zhǔn)庫中查看一下各個函數(shù)的細(xì)節(jié)。
序號 | 函數(shù) & 描述 |
---|---|
1 | time_t time(time_t *time); 該函數(shù)返回系統(tǒng)的當(dāng)前日歷時間,自 1970 年 1 月 1 日以來經(jīng)過的秒數(shù)。如果系統(tǒng)沒有時間,則返回 -1。 |
2 | char *ctime(const time_t *time); 該返回一個表示當(dāng)?shù)貢r間的字符串指針,字符串形式?day month year hours:minutes:seconds year\n\0。 |
3 | struct tm *localtime(const time_t *time); 該函數(shù)返回一個指向表示本地時間的?tm?結(jié)構(gòu)的指針。 |
4 | clock_t clock(void); 該函數(shù)返回程序執(zhí)行起(一般為程序的開頭),處理器時鐘所使用的時間。如果時間不可用,則返回 -1。 |
5 | char * asctime ( const struct tm * time ); 該函數(shù)返回一個指向字符串的指針,字符串包含了 time 所指向結(jié)構(gòu)中存儲的信息,返回形式為:day month date hours:minutes:seconds year\n\0。 |
6 | struct tm *gmtime(const time_t *time); 該函數(shù)返回一個指向 time 的指針,time 為 tm 結(jié)構(gòu),用協(xié)調(diào)世界時(UTC)也被稱為格林尼治標(biāo)準(zhǔn)時間(GMT)表示。 |
7 | time_t mktime(struct tm *time); 該函數(shù)返回日歷時間,相當(dāng)于 time 所指向結(jié)構(gòu)中存儲的時間。 |
8 | double difftime ( time_t time2, time_t time1 ); 該函數(shù)返回 time1 和 time2 之間相差的秒數(shù)。 |
9 | size_t strftime(); 該函數(shù)可用于格式化日期和時間為指定的格式。 |
3.1 當(dāng)前日期和時間
下面的實例獲取當(dāng)前系統(tǒng)的日期和時間,包括本地時間和協(xié)調(diào)世界時(UTC)。
#include <iostream>
#include <ctime>using namespace std;int main( )
{// 基于當(dāng)前系統(tǒng)的當(dāng)前日期/時間time_t now = time(0);// 把 now 轉(zhuǎn)換為字符串形式char* dt = ctime(&now);cout << "本地日期和時間:" << dt << endl;// 把 now 轉(zhuǎn)換為 tm 結(jié)構(gòu)tm *gmtm = gmtime(&now);dt = asctime(gmtm);cout << "UTC 日期和時間:"<< dt << endl;
}
當(dāng)上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
本地日期和時間:Sat Jan 8 20:07:41 2011UTC 日期和時間:Sun Jan 9 03:07:41 2011
3.2?使用結(jié)構(gòu) tm 格式化時間
tm?結(jié)構(gòu)在 C/C++ 中處理日期和時間相關(guān)的操作時,顯得尤為重要。tm 結(jié)構(gòu)以 C 結(jié)構(gòu)的形式保存日期和時間。大多數(shù)與時間相關(guān)的函數(shù)都使用了 tm 結(jié)構(gòu)。下面的實例使用了 tm 結(jié)構(gòu)和各種與日期和時間相關(guān)的函數(shù)。
在練習(xí)使用結(jié)構(gòu)之前,需要對 C 結(jié)構(gòu)有基本的了解,并懂得如何使用箭頭 -> 運(yùn)算符來訪問結(jié)構(gòu)成員。
#include <iostream>
#include <ctime>using namespace std;int main( )
{// 基于當(dāng)前系統(tǒng)的當(dāng)前日期/時間time_t now = time(0);cout << "1970 到目前經(jīng)過秒數(shù):" << now << endl;tm *ltm = localtime(&now);// 輸出 tm 結(jié)構(gòu)的各個組成部分cout << "年: "<< 1900 + ltm->tm_year << endl;cout << "月: "<< 1 + ltm->tm_mon<< endl;cout << "日: "<< ltm->tm_mday << endl;cout << "時間: "<< ltm->tm_hour << ":";cout << ltm->tm_min << ":";cout << ltm->tm_sec << endl;
}
當(dāng)上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
1970 到目前時間:1503564157
年: 2017
月: 8
日: 24
時間: 16:42:37
四 基本的輸入輸出
C++ 的 I/O 發(fā)生在流中,流是字節(jié)序列。如果字節(jié)流是從設(shè)備(如鍵盤、磁盤驅(qū)動器、網(wǎng)絡(luò)連接等)流向內(nèi)存,這叫做輸入操作。如果字節(jié)流是從內(nèi)存流向設(shè)備(如顯示屏、打印機(jī)、磁盤驅(qū)動器、網(wǎng)絡(luò)連接等),這叫做輸出操作。
4.1?I/O 庫頭文件
頭文件 | 函數(shù)和描述 |
---|---|
<iostream> | 該文件定義了?cin、cout、cerr?和?clog?對象,分別對應(yīng)于標(biāo)準(zhǔn)輸入流、標(biāo)準(zhǔn)輸出流、非緩沖標(biāo)準(zhǔn)錯誤流和緩沖標(biāo)準(zhǔn)錯誤流。 |
<iomanip> | 該文件通過所謂的參數(shù)化的流操縱器(比如?setw?和?setprecision),來聲明對執(zhí)行標(biāo)準(zhǔn)化 I/O 有用的服務(wù)。 |
<fstream> | 該文件為用戶控制的文件處理聲明服務(wù)。我們將在文件和流的相關(guān)章節(jié)討論它的細(xì)節(jié)。 |
4.2?標(biāo)準(zhǔn)輸出流(cout)
預(yù)定義的對象?cout?是?iostream?類的一個實例。cout 對象"連接"到標(biāo)準(zhǔn)輸出設(shè)備,通常是顯示屏。cout?是與流插入運(yùn)算符 << 結(jié)合使用的,如下所示:
#include <iostream>using namespace std;int main( )
{char str[] = "Hello C++";cout << "Value of str is : " << str << endl;
}
輸出:
Value of str is : Hello C++
C++ 編譯器根據(jù)要輸出變量的數(shù)據(jù)類型,選擇合適的流插入運(yùn)算符來顯示值。<< 運(yùn)算符被重載來輸出內(nèi)置類型(整型、浮點型、double 型、字符串和指針)的數(shù)據(jù)項。
流插入運(yùn)算符 << 在一個語句中可以多次使用,如上面實例中所示,endl?用于在行末添加一個換行符。
4.3?標(biāo)準(zhǔn)輸入流(cin)
預(yù)定義的對象?cin?是?iostream?類的一個實例。cin 對象附屬到標(biāo)準(zhǔn)輸入設(shè)備,通常是鍵盤。cin?是與流提取運(yùn)算符 >> 結(jié)合使用的,如下所示:
#include <iostream>using namespace std;int main( )
{char name[50];cout << "請輸入您的名稱: ";cin >> name;cout << "您的名稱是: " << name << endl;}
輸出:
請輸入您的名稱: cplusplus
您的名稱是: cplusplus
C++ 編譯器根據(jù)要輸入值的數(shù)據(jù)類型,選擇合適的流提取運(yùn)算符來提取值,并把它存儲在給定的變量中。
流提取運(yùn)算符 >> 在一個語句中可以多次使用,如果要求輸入多個數(shù)據(jù),可以使用如下語句:
cin >> name >> age;
//相當(dāng)于下面兩個語句
cin >> name;
cin >> age;
4.4?標(biāo)準(zhǔn)錯誤流(cerr)
預(yù)定義的對象?cerr?是?iostream?類的一個實例。cerr 對象附屬到標(biāo)準(zhǔn)輸出設(shè)備,通常也是顯示屏,但是?cerr?對象是非緩沖的,且每個流插入到 cerr 都會立即輸出。
cerr?也是與流插入運(yùn)算符 << 結(jié)合使用的,如下所示:
#include <iostream>using namespace std;int main( )
{char str[] = "Unable to read....";cerr << "Error message : " << str << endl;
}
輸出:
Error message : Unable to read....
4.5?標(biāo)準(zhǔn)日志流(clog)
預(yù)定義的對象?clog?是?iostream?類的一個實例。clog 對象附屬到標(biāo)準(zhǔn)輸出設(shè)備,通常也是顯示屏,但是?clog?對象是緩沖的。這意味著每個流插入到 clog 都會先存儲在緩沖區(qū),直到緩沖填滿或者緩沖區(qū)刷新時才會輸出。
clog?也是與流插入運(yùn)算符 << 結(jié)合使用的,如下所示:
#include <iostream>using namespace std;int main( )
{char str[] = "Unable to read....";clog << "Error message : " << str << endl;
}
輸出:
Error message : Unable to read....
通過這些小實例,我們無法區(qū)分 cout、cerr 和 clog 的差異,但在編寫和執(zhí)行大型程序時,它們之間的差異就變得非常明顯。所以良好的編程實踐告訴我們,使用 cerr 流來顯示錯誤消息,而其他的日志消息則使用 clog 流來輸出。
五 結(jié)構(gòu)體(struct)
C/C++ 數(shù)組允許定義可存儲相同類型數(shù)據(jù)項的變量,但是結(jié)構(gòu)是 C++ 中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許您存儲不同類型的數(shù)據(jù)項。
結(jié)構(gòu)用于表示一條記錄,假設(shè)您想要跟蹤圖書館中書本的動態(tài),您可能需要跟蹤每本書的下列屬性:
- Title :標(biāo)題
- Author :作者
- Subject :類目
- Book ID :書的 ID
5.1 定義結(jié)構(gòu)
在 C++ 中,struct 語句用于定義結(jié)構(gòu)體(structure)。
結(jié)構(gòu)體是一種用戶自定義的數(shù)據(jù)類型,用于將不同類型的數(shù)據(jù)組合在一起。與類(class)類似,結(jié)構(gòu)體允許你定義成員變量和成員函數(shù)。
為了定義結(jié)構(gòu),您必須使用?struct?語句。struct 語句定義了一個包含多個成員的新的數(shù)據(jù)類型,struct 語句的格式如下:
struct type_name {
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
.
.
} object_names;
type_name?是結(jié)構(gòu)體類型的名稱,member_type1 member_name1?是標(biāo)準(zhǔn)的變量定義,比如?int i;?或者?float f;?或者其他有效的變量定義。在結(jié)構(gòu)定義的末尾,最后一個分號之前,您可以指定一個或多個結(jié)構(gòu)變量,這是可選的。下面是聲明一個結(jié)構(gòu)體類型?Books,變量為?book:
struct Books
{char title[50];char author[50];char subject[100];int book_id;
} book;
結(jié)構(gòu)體優(yōu)點:
- 簡單數(shù)據(jù)封裝:適合封裝多種類型的簡單數(shù)據(jù),通常用于數(shù)據(jù)的存儲。
- 輕量級:相比?
class
,結(jié)構(gòu)體語法更簡潔,適合小型數(shù)據(jù)對象。 - 面向?qū)ο笾С?/strong>:支持構(gòu)造函數(shù)、成員函數(shù)和訪問權(quán)限控制,可以實現(xiàn)面向?qū)ο蟮脑O(shè)計。
5.2 訪問結(jié)構(gòu)成員
為了訪問結(jié)構(gòu)的成員,我們使用成員訪問運(yùn)算符(.)。成員訪問運(yùn)算符是結(jié)構(gòu)變量名稱和我們要訪問的結(jié)構(gòu)成員之間的一個句號。
下面的實例演示了結(jié)構(gòu)的用法:
#include <iostream>
#include <cstring>using namespace std;// 聲明一個結(jié)構(gòu)體類型 Books
struct Books
{char title[50];char author[50];char subject[100];int book_id;
};int main( )
{Books Book1; // 定義結(jié)構(gòu)體類型 Books 的變量 Book1Books Book2; // 定義結(jié)構(gòu)體類型 Books 的變量 Book2// Book1 詳述strcpy( Book1.title, "C++ 教程");strcpy( Book1.author, "Runoob"); strcpy( Book1.subject, "編程語言");Book1.book_id = 12345;// Book2 詳述strcpy( Book2.title, "CSS 教程");strcpy( Book2.author, "Runoob");strcpy( Book2.subject, "前端技術(shù)");Book2.book_id = 12346;// 輸出 Book1 信息cout << "第一本書標(biāo)題 : " << Book1.title <<endl;cout << "第一本書作者 : " << Book1.author <<endl;cout << "第一本書類目 : " << Book1.subject <<endl;cout << "第一本書 ID : " << Book1.book_id <<endl;// 輸出 Book2 信息cout << "第二本書標(biāo)題 : " << Book2.title <<endl;cout << "第二本書作者 : " << Book2.author <<endl;cout << "第二本書類目 : " << Book2.subject <<endl;cout << "第二本書 ID : " << Book2.book_id <<endl;return 0;
}
實例中定義了結(jié)構(gòu)體類型 Books 及其兩個變量 Book1 和 Book2。當(dāng)上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
第一本書標(biāo)題 : C++ 教程
第一本書作者 : Runoob
第一本書類目 : 編程語言
第一本書 ID : 12345
第二本書標(biāo)題 : CSS 教程
第二本書作者 : Runoob
第二本書類目 : 前端技術(shù)
第二本書 ID : 12346
5.3?結(jié)構(gòu)作為函數(shù)參數(shù)
您可以把結(jié)構(gòu)作為函數(shù)參數(shù),傳參方式與其他類型的變量或指針類似。您可以使用上面實例中的方式來訪問結(jié)構(gòu)變量:
#include <iostream>
#include <cstring>using namespace std;
void printBook( struct Books book );// 聲明一個結(jié)構(gòu)體類型 Books
struct Books
{char title[50];char author[50];char subject[100];int book_id;
};int main( )
{Books Book1; // 定義結(jié)構(gòu)體類型 Books 的變量 Book1Books Book2; // 定義結(jié)構(gòu)體類型 Books 的變量 Book2// Book1 詳述strcpy( Book1.title, "C++ 教程");strcpy( Book1.author, "Runoob"); strcpy( Book1.subject, "編程語言");Book1.book_id = 12345;// Book2 詳述strcpy( Book2.title, "CSS 教程");strcpy( Book2.author, "Runoob");strcpy( Book2.subject, "前端技術(shù)");Book2.book_id = 12346;// 輸出 Book1 信息printBook( Book1 );// 輸出 Book2 信息printBook( Book2 );return 0;
}
void printBook( struct Books book )
{cout << "書標(biāo)題 : " << book.title <<endl;cout << "書作者 : " << book.author <<endl;cout << "書類目 : " << book.subject <<endl;cout << "書 ID : " << book.book_id <<endl;
}
當(dāng)上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
書標(biāo)題 : C++ 教程
書作者 : Runoob
書類目 : 編程語言
書 ID : 12345
書標(biāo)題 : CSS 教程
書作者 : Runoob
書類目 : 前端技術(shù)
書 ID : 12346
5.4?結(jié)構(gòu)體的各個部分詳細(xì)介紹
-
struct 關(guān)鍵字:用于定義結(jié)構(gòu)體,它告訴編譯器后面要定義的是一個自定義類型。
-
成員變量:成員變量是結(jié)構(gòu)體中定義的數(shù)據(jù)項,它們可以是任何基本類型或其他自定義類型。在 struct 中,這些成員默認(rèn)是 public,可以直接訪問。
-
成員函數(shù):結(jié)構(gòu)體中也可以包含成員函數(shù),這使得結(jié)構(gòu)體在功能上類似于類。成員函數(shù)可以操作結(jié)構(gòu)體的成員變量,提供對數(shù)據(jù)的封裝和操作。
-
訪問權(quán)限:與 class 類似,你可以在 struct 中使用 public、private 和 protected 來定義成員的訪問權(quán)限。在 struct 中,默認(rèn)所有成員都是 public,而 class 中默認(rèn)是 private。
5.5 指向結(jié)構(gòu)的指針
您可以定義指向結(jié)構(gòu)的指針,方式與定義指向其他類型變量的指針相似,如下所示:
struct Books *struct_pointer;
現(xiàn)在,您可以在上述定義的指針變量中存儲結(jié)構(gòu)變量的地址。為了查找結(jié)構(gòu)變量的地址,請把 & 運(yùn)算符放在結(jié)構(gòu)名稱的前面,如下所示:
struct_pointer = &Book1;
為了使用指向該結(jié)構(gòu)的指針訪問結(jié)構(gòu)的成員,您必須使用 -> 運(yùn)算符,如下所示:
struct_pointer->title;
讓我們使用結(jié)構(gòu)指針來重寫上面的實例,這將有助于您理解結(jié)構(gòu)指針的概念:
#include <iostream>
#include <string>using namespace std;// 聲明一個結(jié)構(gòu)體類型 Books
struct Books
{string title;string author;string subject;int book_id;// 構(gòu)造函數(shù)Books(string t, string a, string s, int id): title(t), author(a), subject(s), book_id(id) {}
};// 打印書籍信息的函數(shù)
void printBookInfo(const Books& book) {cout << "書籍標(biāo)題: " << book.title << endl;cout << "書籍作者: " << book.author << endl;cout << "書籍類目: " << book.subject << endl;cout << "書籍 ID: " << book.book_id << endl;
}int main()
{// 創(chuàng)建兩本書的對象Books Book1("C++ 教程", "csdn", "編程語言", 12345);Books Book2("CSS 教程", "csdn", "前端技術(shù)", 12346);// 輸出書籍信息printBookInfo(Book1);printBookInfo(Book2);return 0;
}
輸出:
書標(biāo)題 : C++ 教程
書作者 : csdn
書類目 : 編程語言
書 ID : 12345
書標(biāo)題 : CSS 教程
書作者 : csdn
書類目 : 前端技術(shù)
書 ID : 12346
5.6?typedef 關(guān)鍵字
下面是一種更簡單的定義結(jié)構(gòu)的方式,您可以為創(chuàng)建的類型取一個"別名"。例如:
typedef struct Books
{char title[50];char author[50];char subject[100];int book_id;
}Books;
可以直接使用?Books?來定義?Books?類型的變量,而不需要使用 struct 關(guān)鍵字。下面是實例:
Books Book1, Book2;
可以使用?typedef?關(guān)鍵字來定義非結(jié)構(gòu)類型,如下所示:
typedef long int *pint32;pint32 x, y, z;
x, y 和 z 都是指向長整型 long int 的指針。
5.7?結(jié)構(gòu)體與類的區(qū)別
在 C++ 中,struct 和 class 本質(zhì)上非常相似,唯一的區(qū)別在于默認(rèn)的訪問權(quán)限:
struct
?默認(rèn)的成員和繼承是?public
。class
?默認(rèn)的成員和繼承是?private
。
可以將?struct
?當(dāng)作一種簡化形式的?class
,適合用于沒有太多復(fù)雜功能的簡單數(shù)據(jù)封裝。
5.7.1 結(jié)構(gòu)體與函數(shù)的結(jié)合
可以通過構(gòu)造函數(shù)初始化結(jié)構(gòu)體,還可以通過引用傳遞結(jié)構(gòu)體來避免不必要的拷貝。
struct Books {string title;string author;string subject;int book_id;// 構(gòu)造函數(shù)Books(string t, string a, string s, int id): title(t), author(a), subject(s), book_id(id) {}void printInfo() const {cout << "書籍標(biāo)題: " << title << endl;cout << "書籍作者: " << author << endl;cout << "書籍類目: " << subject << endl;cout << "書籍 ID: " << book_id << endl;}
};void printBookByRef(const Books& book) {book.printInfo();
}
六?C++ vector 容器
C++ 中的 vector 是一種序列容器,它允許你在運(yùn)行時動態(tài)地插入和刪除元素。
vector 是基于數(shù)組的數(shù)據(jù)結(jié)構(gòu),但它可以自動管理內(nèi)存,這意味著你不需要手動分配和釋放內(nèi)存。
與 C++ 數(shù)組相比,vector 具有更多的靈活性和功能,使其成為 C++ 中常用的數(shù)據(jù)結(jié)構(gòu)之一。
vector 是 C++ 標(biāo)準(zhǔn)模板庫(STL)的一部分,提供了靈活的接口和高效的操作。
基本特性:
- 動態(tài)大小:
vector
?的大小可以根據(jù)需要自動增長和縮小。 - 連續(xù)存儲:
vector
?中的元素在內(nèi)存中是連續(xù)存儲的,這使得訪問元素非常快速。 - 可迭代:
vector
?可以被迭代,你可以使用循環(huán)(如?for
?循環(huán))來訪問它的元素。 - 元素類型:
vector
?可以存儲任何類型的元素,包括內(nèi)置類型、對象、指針等。
使用場景:
- 當(dāng)你需要一個可以動態(tài)增長和縮小的數(shù)組時。
- 當(dāng)你需要頻繁地在序列的末尾添加或移除元素時。
- 當(dāng)你需要一個可以高效隨機(jī)訪問元素的容器時。
要使用 vector,首先需要包含?<vector>?頭文件:
#include <vector>
6.1 創(chuàng)建 Vector
創(chuàng)建一個 vector 可以像創(chuàng)建其他變量一樣簡單:
std::vector<int> myVector; // 創(chuàng)建一個存儲整數(shù)的空 vector
這將創(chuàng)建一個空的整數(shù)向量,也可以在創(chuàng)建時指定初始大小和初始值:
std::vector<int> myVector(5); // 創(chuàng)建一個包含 5 個整數(shù)的 vector,每個值都為默認(rèn)值(0)
std::vector<int> myVector(5, 10); // 創(chuàng)建一個包含 5 個整數(shù)的 vector,每個值都為 10
or:
std::vector<int> vec; // 默認(rèn)初始化一個空的 vector
std::vector<int> vec2 = {1, 2, 3, 4}; // 初始化一個包含元素的 vector
6.2 添加元素
可以使用 push_back 方法向 vector 中添加元素:
myVector.push_back(7); // 將整數(shù) 7 添加到 vector 的末尾
6.3 訪問元素
可以使用下標(biāo)操作符 [] 或 at() 方法訪問 vector 中的元素:
int x = myVector[0]; // 獲取第一個元素
int y = myVector.at(1); // 獲取第二個元素
6.4 獲取大小
可以使用 size() 方法獲取 vector 中元素的數(shù)量:
int size = myVector.size(); // 獲取 vector 中的元素數(shù)量
6.5 迭代訪問
可以使用迭代器遍歷 vector 中的元素:
for (auto it = myVector.begin(); it != myVector.end(); ++it) {std::cout << *it << " ";
}
or 使用范圍循環(huán):
for (int element : myVector) {std::cout << element << " ";
}
6.6 刪除元素
可以使用 erase() 方法刪除 vector 中的元素:
myVector.erase(myVector.begin() + 2); // 刪除第三個元素
6.7 清空 Vector
可以使用 clear() 方法清空 vector 中的所有元素:
myVector.clear(); // 清空 vector
實例:以下是一個完整的使用實例,包括創(chuàng)建 vector、添加元素、訪問元素以及輸出結(jié)果的代碼:
#include <iostream>
#include <vector>int main() {// 創(chuàng)建一個空的整數(shù)向量std::vector<int> myVector;// 添加元素到向量中myVector.push_back(3);myVector.push_back(7);myVector.push_back(11);myVector.push_back(5);// 訪問向量中的元素并輸出std::cout << "Elements in the vector: ";for (int element : myVector) {std::cout << element << " ";}std::cout << std::endl;// 訪問向量中的第一個元素并輸出std::cout << "First element: " << myVector[0] << std::endl;// 訪問向量中的第二個元素并輸出std::cout << "Second element: " << myVector.at(1) << std::endl;// 獲取向量的大小并輸出std::cout << "Size of the vector: " << myVector.size() << std::endl;// 刪除向量中的第三個元素myVector.erase(myVector.begin() + 2);// 輸出刪除元素后的向量std::cout << "Elements in the vector after erasing: ";for (int element : myVector) {std::cout << element << " ";}std::cout << std::endl;// 清空向量并輸出myVector.clear();std::cout << "Size of the vector after clearing: " << myVector.size() << std::endl;return 0;
}
以上代碼創(chuàng)建了一個整數(shù)向量,向其中添加了幾個元素,然后輸出了向量的內(nèi)容、元素的訪問、向量的大小等信息,接著刪除了向量中的第三個元素,并輸出刪除元素后的向量。最后清空了向量,并輸出清空后的向量大小。
輸出結(jié)果為:
Elements in the vector: 3 7 11 5
First element: 3
Second element: 7
Size of the vector: 4
Elements in the vector after erasing: 3 7 5
Size of the vector after clearing: 0
七 數(shù)據(jù)結(jié)構(gòu)
C++ 提供了多種數(shù)據(jù)結(jié)構(gòu),既有基礎(chǔ)的如數(shù)組、結(jié)構(gòu)體、類等,也有高級的 STL 容器如?vector
、map
?和?unordered_map
?等。
下面詳細(xì)介紹 C++ 中常用的數(shù)據(jù)結(jié)構(gòu)及其特點和用法。
7.1 數(shù)組(Array)
數(shù)組是最基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),用于存儲一組相同類型的數(shù)據(jù)。
特點:
- 固定大小,一旦聲明,大小不能改變。
- 直接訪問元素,時間復(fù)雜度為 O(1)。
- 適合處理大小已知、元素類型相同的集合。
int arr[5] = {1, 2, 3, 4, 5};
cout << arr[0]; // 輸出第一個元素
優(yōu)缺點:
- 優(yōu)點:訪問速度快,內(nèi)存緊湊。
- 缺點:大小固定,無法動態(tài)擴(kuò)展,不適合處理大小不確定的數(shù)據(jù)集。
7.2 結(jié)構(gòu)體(Struct)
結(jié)構(gòu)體允許將不同類型的數(shù)據(jù)組合在一起,形成一種自定義的數(shù)據(jù)類型。
特點:
- 可以包含不同類型的成員變量。
- 提供了對數(shù)據(jù)的基本封裝,但功能有限。
示例:
struct Person {string name;int age;
};
Person p = {"Alice", 25};
cout << p.name << endl; // 輸出 Alice
7.3 類(Class)
類是 C++ 中用于面向?qū)ο缶幊痰暮诵慕Y(jié)構(gòu),允許定義成員變量和成員函數(shù)。與?struct
?類似,但功能更強(qiáng)大,支持繼承、封裝、多態(tài)等特性。
特點:
- 可以包含成員變量、成員函數(shù)、構(gòu)造函數(shù)、析構(gòu)函數(shù)。
- 支持面向?qū)ο筇匦?#xff0c;如封裝、繼承、多態(tài)。
class Person {
private:string name;int age;
public:Person(string n, int a) : name(n), age(a) {}void printInfo() {cout << "Name: " << name << ", Age: " << age << endl;}
};
Person p("Bob", 30);
p.printInfo(); // 輸出: Name: Bob, Age: 30
7.4 鏈表(Linked List)
鏈表是一種動態(tài)數(shù)據(jù)結(jié)構(gòu),由一系列節(jié)點組成,每個節(jié)點包含數(shù)據(jù)和指向下一個節(jié)點的指針。
特點:
- 動態(tài)調(diào)整大小,不需要提前定義容量。
- 插入和刪除操作效率高,時間復(fù)雜度為 O(1)(在鏈表頭部或尾部操作)。
- 線性查找,時間復(fù)雜度為 O(n)。
struct Node {int data;Node* next;
};
Node* head = nullptr;
Node* newNode = new Node{10, nullptr};
head = newNode; // 插入新節(jié)點
優(yōu)缺點:
- 優(yōu)點:動態(tài)大小,適合頻繁插入和刪除的場景。
- 缺點:隨機(jī)訪問效率低,不如數(shù)組直接訪問快。
7.5 棧 (Stack)
棧是一種后進(jìn)先出(LIFO, Last In First Out)的數(shù)據(jù)結(jié)構(gòu),常用于遞歸、深度優(yōu)先搜索等場景。
特點:
- 只允許在棧頂進(jìn)行插入和刪除操作。
- 時間復(fù)雜度為 O(1)。
stack<int> s;
s.push(1);
s.push(2);
cout << s.top(); // 輸出 2
s.pop();
優(yōu)缺點:
- 優(yōu)點:操作簡單,效率高。
- 缺點:只能在棧頂操作,訪問其他元素需要彈出棧頂元素。
7.6 隊列(Queue)
隊列是一種先進(jìn)先出(FIFO, First In First Out)的數(shù)據(jù)結(jié)構(gòu),常用于廣度優(yōu)先搜索、任務(wù)調(diào)度等場景。
特點:
- 插入操作在隊尾進(jìn)行,刪除操作在隊頭進(jìn)行。
- 時間復(fù)雜度為 O(1)。
queue<int> q;
q.push(1);
q.push(2);
cout << q.front(); // 輸出 1
q.pop();
優(yōu)缺點:
- 優(yōu)點:適合按順序處理數(shù)據(jù)的場景,如任務(wù)調(diào)度。
- 缺點:無法隨機(jī)訪問元素。
7.7 雙端隊列(Deque)
雙端隊列允許在兩端進(jìn)行插入和刪除操作,是棧和隊列的結(jié)合體。
特點:
- 允許在兩端進(jìn)行插入和刪除。
- 時間復(fù)雜度為 O(1)。
deque<int> dq;
dq.push_back(1);
dq.push_front(2);
cout << dq.front(); // 輸出 2
dq.pop_front();
優(yōu)缺點:
- 優(yōu)點:靈活的雙向操作。
- 缺點:空間占用較大,適合需要在兩端頻繁操作的場景。
7.8 哈希表(Hash Table)
哈希表是一種通過鍵值對存儲數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),支持快速查找、插入和刪除操作。C++ 中的?unordered_map
?是哈希表的實現(xiàn)。
特點:
- 使用哈希函數(shù)快速定位元素,時間復(fù)雜度為 O(1)。
- 不保證元素的順序。
unordered_map<string, int> hashTable;
hashTable["apple"] = 10;
cout << hashTable["apple"]; // 輸出 10
優(yōu)缺點:
- 優(yōu)點:查找、插入、刪除操作效率高。
- 缺點:無法保證元素順序,哈希沖突時性能會下降。
7.9 映射(Map)
map
?是一種有序的鍵值對容器,底層實現(xiàn)是紅黑樹。與?unordered_map
?不同,它保證鍵的順序,查找、插入和刪除的時間復(fù)雜度為 O(log n)。
特點:
- 保證元素按鍵的順序排列。
- 使用二叉搜索樹實現(xiàn)。
map<string, int> myMap;
myMap["apple"] = 10;
cout << myMap["apple"]; // 輸出 10
優(yōu)缺點:
- 優(yōu)點:元素有序,適合需要按順序處理數(shù)據(jù)的場景。
- 缺點:操作效率比?
unordered_map
?略低。
7.10 集合(Set)
set
?是一種用于存儲唯一元素的有序集合,底層同樣使用紅黑樹實現(xiàn)。它保證元素不重復(fù)且有序。
特點:
- 保證元素的唯一性。
- 元素自動按升序排列。
- 時間復(fù)雜度為 O(log n)
set<int> s;
s.insert(1);
s.insert(2);
cout << *s.begin(); // 輸出 1
優(yōu)缺點:
- 優(yōu)點:自動排序和唯一性保證。
- 缺點:插入和刪除的效率不如無序集合。
7.11 動態(tài)數(shù)組(Vector)
vector
?是 C++ 標(biāo)準(zhǔn)庫提供的動態(tài)數(shù)組實現(xiàn),可以動態(tài)擴(kuò)展容量,支持隨機(jī)訪問。
特點:
- 動態(tài)調(diào)整大小。
- 支持隨機(jī)訪問,時間復(fù)雜度為 O(1)。
- 當(dāng)容量不足時,動態(tài)擴(kuò)展,時間復(fù)雜度為攤銷 O(1)。
vector<int> v;
v.push_back(1);
v.push_back(2);
cout << v[0]; // 輸出 1
優(yōu)缺點:
- 優(yōu)點:支持隨機(jī)訪問,動態(tài)擴(kuò)展。
- 缺點:插入和刪除中間元素的效率較低。
內(nèi)容摘錄學(xué)習(xí)自:C++ 數(shù)據(jù)結(jié)構(gòu) | 菜鳥教程