C++筆記
明年就要找工作了,只有Python用的比較熟好像不太行,抓緊熟悉一遍C++開(kāi)始刷題吧!這里會(huì)不斷更新C++的學(xué)習(xí)筆記,主要記錄一些重要的知識(shí)點(diǎn)。
常用數(shù)據(jù)類型:
int,char,float, double
在函數(shù)內(nèi),局部變量的值會(huì)覆蓋全局變量的值
定義常量常用的兩種方法,將常量用大寫字母表示是很好的習(xí)慣
#define LENGTH 10
#define WIDTH 5
#define NEWLINE '\n'
const int LENGTH = 10;
const int WIDTH = 5;
const char NEWLINE = '\n';
修飾符 signed、unsigned、long 和 short 可應(yīng)用于整型,signed 和 unsigned 可應(yīng)用于字符型,long 可應(yīng)用于雙精度型
register 存儲(chǔ)類用于定義存儲(chǔ)在寄存器中而不是 RAM 中的局部變量。寄存器只用于需要快速訪問(wèn)的變量,比如計(jì)數(shù)器
register int miles;
static 存儲(chǔ)類指示編譯器在程序的生命周期內(nèi)保持局部變量的存在,而不需要在每次它進(jìn)入和離開(kāi)作用域時(shí)進(jìn)行創(chuàng)建和銷毀。因此,使用 static 修飾局部變量可以在函數(shù)調(diào)用之間保持局部變量的值
static 修飾符也可以應(yīng)用于全局變量。當(dāng) static 修飾全局變量時(shí),會(huì)使變量的作用域限制在聲明它的文件內(nèi)
#include <iostream>
// 函數(shù)聲明
void func(void);
static int count = 10; /* 全局變量 */
int main()
{
while(count--)
{
func();
}
return 0;
}
// 函數(shù)定義
void func( void )
{
static int i = 5; // 局部靜態(tài)變量
i++;
std::cout << "變量 i 為 " << i ;
std::cout << " , 變量 count 為 " << count << std::endl;
}
上述代碼在多次調(diào)用fun()函數(shù)時(shí),i的值得到了保持
位運(yùn)算符
^ 為異或預(yù)算,~為補(bǔ)碼運(yùn)算符,具有"翻轉(zhuǎn)"位效果,即0變成1,1變成0
<< 為二進(jìn)制左移運(yùn)算符,左操作數(shù)的值向左移動(dòng)右操作數(shù)指定的位數(shù)
>> 為二進(jìn)制右移運(yùn)算符。左操作數(shù)的值向右移動(dòng)右操作數(shù)指定的位數(shù)
雜項(xiàng)運(yùn)算符
| sizeof | sizeof 運(yùn)算符返回變量的大小。例如,sizeof(a) 將返回 4,其中 a 是整數(shù)。 |
|---|---|
| Condition ? X : Y | 條件運(yùn)算符。如果 Condition 為真 ? 則值為 X : 否則值為 Y。 |
| , | 逗號(hào)運(yùn)算符會(huì)順序執(zhí)行一系列運(yùn)算。整個(gè)逗號(hào)表達(dá)式的值是以逗號(hào)分隔的列表中的最后一個(gè)表達(dá)式的值。 |
| .(點(diǎn))和 ->(箭頭) | 成員運(yùn)算符用于引用類、結(jié)構(gòu)和共用體的成員。 |
| Cast | 強(qiáng)制轉(zhuǎn)換運(yùn)算符把一種數(shù)據(jù)類型轉(zhuǎn)換為另一種數(shù)據(jù)類型。例如,int(2.2000) 將返回 2。 |
| & | 指針運(yùn)算符 & 返回變量的地址。例如 &a; 將給出變量的實(shí)際地址。 |
| * | 指針運(yùn)算符 * 指向一個(gè)變量。例如,*var; 將指向變量 var。 |
循環(huán)與條件語(yǔ)句
while,for,do...while
循環(huán)控制語(yǔ)句
break,continue
無(wú)限循環(huán)
while(1)
for( ; ; )
條件判斷語(yǔ)句
if else
switch
Exp1 ? Exp2 : Exp3;
函數(shù)
函數(shù)是一組一起執(zhí)行一個(gè)任務(wù)的語(yǔ)句。每個(gè) C++ 程序都至少有一個(gè)函數(shù),即主函數(shù) main() ,所有簡(jiǎn)單的程序都可以定義其他額外的函數(shù)。
C++ 中的函數(shù)定義的一般形式如下:
return_type function_name( parameter list )
{
body of the function
}
int max(int num1, int num2)
{
// 局部變量聲明
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
一個(gè)函數(shù)可以返回一個(gè)值。return_type 是函數(shù)返回的值的數(shù)據(jù)類型。有些函數(shù)執(zhí)行所需的操作而不返回值,在這種情況下,return_type 是關(guān)鍵字 void。
向函數(shù)傳遞參數(shù)的傳值調(diào)用方法,把參數(shù)的實(shí)際值復(fù)制給函數(shù)的形式參數(shù)。在這種情況下,修改函數(shù)內(nèi)的形式參數(shù)不會(huì)影響實(shí)際參數(shù)。
向函數(shù)傳遞參數(shù)的指針調(diào)用方法,把參數(shù)的地址復(fù)制給形式參數(shù)。在函數(shù)內(nèi),該地址用于訪問(wèn)調(diào)用中要用到的實(shí)際參數(shù)。這意味著,修改形式參數(shù)會(huì)影響實(shí)際參數(shù)。
向函數(shù)傳遞參數(shù)的引用調(diào)用方法,把引用的地址復(fù)制給形式參數(shù)。在函數(shù)內(nèi),該引用用于訪問(wèn)調(diào)用中要用到的實(shí)際參數(shù)。這意味著,修改形式參數(shù)會(huì)影響實(shí)際參數(shù)。
數(shù)字
使用內(nèi)置的數(shù)學(xué)函數(shù),需要引用數(shù)學(xué)頭文件 <cmath>。
#include <iostream>
#include <cmath>
using namespace std;
int main ()
{
// 數(shù)字定義
short s = 10;
int i = -1000;
long l = 100000;
float f = 230.47;
double d = 200.374;
// 數(shù)學(xué)運(yùn)算
cout << "sin(d) :" << sin(d) << endl;
cout << "abs(i) :" << abs(i) << endl;
cout << "floor(d) :" << floor(d) << endl;
cout << "sqrt(f) :" << sqrt(f) << endl;
cout << "pow( d, 2) :" << pow(d, 2) << endl;
return 0;
}
隨機(jī)數(shù)
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main ()
{
int i,j;
// 用時(shí)間戳來(lái)設(shè)置種子
srand( (unsigned)time( NULL ) );
/* 生成 10 個(gè)隨機(jī)數(shù) */
for( i = 0; i < 10; i++ )
{
// 生成實(shí)際的隨機(jī)數(shù)
j= rand();
cout <<"隨機(jī)數(shù): " << j << endl;
}
return 0;
}
其中#include <cstdlib>中是一些常用的函數(shù),但是又不知道把它們放到哪里合適,因此就都放到了stdlib.h這個(gè)頭文件中,rand()與srand()就是其中的函數(shù)。
數(shù)組
聲明方法:type arrayName [ arraySize ];
double balance[10];
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
多維數(shù)組:
int a[3][4] = {
{0, 1, 2, 3} , /* 初始化索引號(hào)為 0 的行 */
{4, 5, 6, 7} , /* 初始化索引號(hào)為 1 的行 */
{8, 9, 10, 11} /* 初始化索引號(hào)為 2 的行 */
};
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
指向數(shù)組的指針
double *p;
double balance[10];
p = balance;
使用數(shù)組名作為常量指針是合法的,反之亦然。因此,*(balance + 4) 是一種訪問(wèn) balance[4] 數(shù)據(jù)的合法方式。一旦把第一個(gè)元素的地址存儲(chǔ)在 p 中,您就可以使用*p、*(p+1)、*(p+2) 等來(lái)訪問(wèn)數(shù)組元素。
傳遞數(shù)組給函數(shù)
C++ 傳數(shù)組給一個(gè)函數(shù),數(shù)組類型自動(dòng)轉(zhuǎn)換為指針類型,因而傳的實(shí)際是地址。如果想要在函數(shù)中傳遞一個(gè)一維數(shù)組作為參數(shù),必須以下面三種方式來(lái)聲明函數(shù)形式參數(shù),這三種聲明方式的結(jié)果是一樣的,因?yàn)槊糠N方式都會(huì)告訴編譯器將要接收一個(gè)整型指針。
void myFunction(int *param) //形式參數(shù)是一個(gè)指針
{
.
.
}
void myFunction(int param[10]) //形式參數(shù)是一個(gè)已定義大小的數(shù)組
{
.
.
}
void myFunction(int param[]) //形式參數(shù)是一個(gè)未定義大小的數(shù)組
{
.
.
}
從函數(shù)返回?cái)?shù)組
C++ 不允許返回一個(gè)完整的數(shù)組作為函數(shù)的參數(shù)??梢酝ㄟ^(guò)指定不帶索引的數(shù)組名來(lái)返回一個(gè)指向數(shù)組的指針。另外,C++ 不支持在函數(shù)外返回局部變量的地址,除非定義局部變量為 static 變量。
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
// 要生成和返回隨機(jī)數(shù)的函數(shù)
int * getRandom( )
{
static int r[10];
// 設(shè)置種子
srand( (unsigned)time( NULL ) );
for (int i = 0; i < 10; ++i)
{
r[i] = rand();
cout << r[i] << endl;
}
return r;
}
// 要調(diào)用上面定義函數(shù)的主函數(shù)
int main ()
{
// 一個(gè)指向整數(shù)的指針
int *p;
p = getRandom();
for ( int i = 0; i < 10; i++ )
{
cout << "*(p + " << i << ") : ";
cout << *(p + i) << endl;
}
return 0;
}
字符串
C++ 提供了以下兩種類型的字符串表示形式:
- C 風(fēng)格字符串
- C++ 引入的 string 類類型
C 風(fēng)格的字符實(shí)際上是使用 null 字符 '\0' 終止的一維字符數(shù)組。因此,一個(gè)以 null 結(jié)尾的字符串,包含了組成字符串的字符。下面的聲明和初始化創(chuàng)建了一個(gè) "Hello" 字符串。由于在數(shù)組的末尾存儲(chǔ)了空字符,所以字符數(shù)組的大小比單詞 "Hello" 的字符數(shù)多一個(gè)。
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
char greeting[] = "Hello";
C++ 中有大量的函數(shù)用來(lái)操作以 null 結(jié)尾的字符串:
| 函數(shù) | 作用 |
|---|---|
| strcat(s1, s2); | 連接字符串 s2 到字符串 s1 的末尾,返回的是s1. |
| strlen(s1); | 返回字符串 s1 的長(zhǎng)度。 |
| strcmp(s1, s2); | 如果 s1 和 s2 相同返回 0;如果 s1<s2 返回值小于 0;如果 s1>s2 返回值大于 0。 |
| strchr(s1, ch); | 返回一個(gè)指針,指向字符串 s1 中字符 ch 的第一次出現(xiàn)的位置。 |
| strstr(s1, s2); | 返回一個(gè)指針,指向字符串 s1 中字符串 s2 的第一次出現(xiàn)的位置。 |
| strcpy(s1, s2); | 復(fù)制字符串 s2 到字符串 s。 |
#include <iostream>
#include <cstring>
using namespace std;
int main ()
{
char str1[11] = "Hello";
char str2[11] = "World";
char str3[11];
int len ;
// 復(fù)制 str1 到 str3
strcpy( str3, str1);
cout << "strcpy( str3, str1) : " << str3 << endl;
// 連接 str1 和 str2
strcat( str1, str2);
cout << "strcat( str1, str2): " << str1 << endl;
// 連接后,str1 的總長(zhǎng)度
len = strlen(str1);
cout << "strlen(str1) : " << len << endl;
return 0;
}
String 類
基本操作示例:
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str1 = "Hello";
string str2 = "World";
string str3;
int len ;
// 復(fù)制 str1 到 str3
str3 = str1;
cout << "str3 : " << str3 << endl;
// 連接 str1 和 str2
str3 = str1 + str2;
cout << "str1 + str2 : " << str3 << endl;
// 連接后,str3 的總長(zhǎng)度
len = str3.size();
cout << "str3.size() : " << len << endl;
return 0;
}
指針
每一個(gè)變量都有一個(gè)內(nèi)存位置,每一個(gè)內(nèi)存位置都定義了可使用連字號(hào)(&)運(yùn)算符訪問(wèn)的地址,它表示了在內(nèi)存中的一個(gè)地址。
#include <iostream>
using namespace std;
int main ()
{
int var1;
char var2[10];
cout << "var1 變量的地址: ";
cout << &var1 << endl;
cout << "var2 變量的地址: ";
cout << &var2 << endl;
return 0;
}
指針是一個(gè)變量,其值為另一個(gè)變量的地址,即,內(nèi)存位置的直接地址。就像其他變量或常量一樣,必須在使用指針存儲(chǔ)其他變量地址之前,對(duì)其進(jìn)行聲明。指針變量聲明的一般形式為:
type *var-name;
type 是指針的基類型,它必須是一個(gè)有效的 C++ 數(shù)據(jù)類型,var-name 是指針變量的名稱。用來(lái)聲明指針的星號(hào) * 與乘法中使用的星號(hào)是相同的,在這個(gè)語(yǔ)句中,星號(hào)是用來(lái)指定一個(gè)變量是指針。所有指針的值的實(shí)際數(shù)據(jù)類型,不管是整型、浮點(diǎn)型、字符型,還是其他的數(shù)據(jù)類型,都是一樣的,都是一個(gè)代表內(nèi)存地址的長(zhǎng)的十六進(jìn)制數(shù)。不同數(shù)據(jù)類型的指針之間唯一的不同是,指針?biāo)赶虻淖兞炕虺A康臄?shù)據(jù)類型不同。
在變量聲明的時(shí)候,如果沒(méi)有確切的地址可以賦值,為指針變量賦一個(gè) NULL 值是一個(gè)良好的編程習(xí)慣。賦為 NULL 值的指針被稱為空指針。NULL 指針是一個(gè)定義在標(biāo)準(zhǔn)庫(kù)中的值為零的常量。
int *ptr = NULL;
可以對(duì)指針進(jìn)行四種算術(shù)運(yùn)算:++、--、+、-。這里ptr+1或-1表示移動(dòng)4 個(gè)字節(jié)。指針也可以用關(guān)系運(yùn)算符進(jìn)行比較,如 ==、< 和 >。如果 p1 和 p2 指向兩個(gè)相關(guān)的變量,比如同一個(gè)數(shù)組中的不同元素,則可對(duì) p1 和 p2 進(jìn)行大小比較。注:這里比較的是地址的大小而不是所指內(nèi)容的大小。
指針和數(shù)組是密切相關(guān)的。事實(shí)上,指針和數(shù)組在很多情況下是可以互換的。例如,一個(gè)指向數(shù)組開(kāi)頭的指針,可以通過(guò)使用指針的算術(shù)運(yùn)算或數(shù)組索引來(lái)訪問(wèn)數(shù)組。
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;
// 指針中的數(shù)組地址
ptr = var;
for (int i = 0; i < MAX; i++)
{
cout << "var[" << i << "]的內(nèi)存地址為 ";
cout << ptr << endl;
cout << "var[" << i << "] 的值為 ";
cout << *ptr << endl;
// 移動(dòng)到下一個(gè)位置
ptr++;
}
return 0;
}
也可以將指針地址存入數(shù)組中,即所謂的指針數(shù)組:
int var[MAX] = {10, 100, 200};
int *ptr[MAX];
for (int i = 0; i < MAX; i++)
{
ptr[i] = &var[i]; // 賦值為整數(shù)的地址
}
C++ 允許從函數(shù)返回指針。必須在定義函數(shù)時(shí)聲明這是一個(gè)返回指針的函數(shù),如下所示:
int * myFunction()
{
...
}
引用
引用變量是一個(gè)別名,也就是說(shuō),它是某個(gè)已存在變量的另一個(gè)名字。一旦把引用初始化為某個(gè)變量,就可以使用該引用名稱或變量名稱來(lái)指向變量。引用很容易與指針混淆,它們之間有三個(gè)主要的不同:
- 不存在空引用。引用必須連接到一塊合法的內(nèi)存。
- 一旦引用被初始化為一個(gè)對(duì)象,就不能被指向到另一個(gè)對(duì)象。指針可以在任何時(shí)候指向到另一個(gè)對(duì)象。
- 引用必須在創(chuàng)建時(shí)被初始化。指針可以在任何時(shí)間被初始化。
int& r = i;
double& s = d;
C++之所以增加引用類型, 主要是把它作為函數(shù)參數(shù),以擴(kuò)充函數(shù)傳遞數(shù)據(jù)的功能。
#include <iostream>
using namespace std;
// 函數(shù)聲明
void swap(int& x, int& y);
int main ()
{
// 局部變量聲明
int a = 100;
int b = 200;
cout << "交換前,a 的值:" << a << endl;
cout << "交換前,b 的值:" << b << endl;
/* 調(diào)用函數(shù)來(lái)交換值 */
swap(a, b);
cout << "交換后,a 的值:" << a << endl;
cout << "交換后,b 的值:" << b << endl;
return 0;
}
// 函數(shù)定義
void swap(int& x, int& y)
{
int temp;
temp = x; /* 保存地址 x 的值 */
x = y; /* 把 y 賦值給 x */
y = temp; /* 把 x 賦值給 y */
return;
}
日期 & 時(shí)間
為了使用日期和時(shí)間相關(guān)的函數(shù)和結(jié)構(gòu),需要在 C++ 程序中引用 <ctime> 頭文件。使用結(jié)構(gòu) tm 格式化時(shí)間如下:
#include <iostream>
#include <ctime>
using namespace std;
int main( )
{
// 基于當(dāng)前系統(tǒng)的當(dāng)前日期/時(shí)間
time_t now = time(0);
cout << "1970 到目前經(jīng)過(guò)秒數(shù):" << now << endl;
tm *ltm = localtime(&now);
// 輸出 tm 結(jié)構(gòu)的各個(gè)組成部分
cout << "年: "<< 1900 + ltm->tm_year << endl;
cout << "月: "<< 1 + ltm->tm_mon<< endl;
cout << "日: "<< ltm->tm_mday << endl;
cout << "時(shí)間: "<< ltm->tm_hour << ":";
cout << ltm->tm_min << ":";
cout << ltm->tm_sec << endl;
}
/*
struct tm {
int tm_sec; // 秒,正常范圍從 0 到 59,但允許至 61
int tm_min; // 分,范圍從 0 到 59
int tm_hour; // 小時(shí),范圍從 0 到 23
int tm_mday; // 一月中的第幾天,范圍從 1 到 31
int tm_mon; // 月,范圍從 0 到 11
int tm_year; // 自 1900 年起的年數(shù)
int tm_wday; // 一周中的第幾天,范圍從 0 到 6,從星期日算起
int tm_yday; // 一年中的第幾天,范圍從 0 到 365,從 1 月 1 日算起
int tm_isdst; // 夏令時(shí)
}
*/
數(shù)據(jù)結(jié)構(gòu)
結(jié)構(gòu)是 C++ 中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許存儲(chǔ)不同類型的數(shù)據(jù)項(xiàng)。
struct type_name {
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
...
} object_names;
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book;
實(shí)例:
#include <iostream>
#include <cstring>
using namespace std;
// 聲明一個(gè)結(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 的變量 Book1
Books Book2; // 定義結(jié)構(gòu)體類型 Books 的變量 Book2
// Book1 詳述
strcpy( Book1.title, "C++ 教程");
strcpy( Book1.author, "Runoob");
strcpy( Book1.subject, "編程語(yǔ)言");
Book1.book_id = 12345;
// Book2 詳述
strcpy( Book2.title, "CSS 教程");
strcpy( Book2.author, "Runoob");
strcpy( Book2.subject, "前端技術(shù)");
Book2.book_id = 12346;
return 0;
}
也可以把結(jié)構(gòu)作為函數(shù)參數(shù),傳參方式與其他類型的變量或指針類似。
可以定義指向結(jié)構(gòu)的指針,方式與定義指向其他類型變量的指針相似,如下所示:
struct Books *struct_pointer;
現(xiàn)在,可以在上述定義的指針變量中存儲(chǔ)結(jié)構(gòu)變量的地址。為了查找結(jié)構(gòu)變量的地址,需要把 & 運(yùn)算符放在結(jié)構(gòu)名稱的前面,如下所示:
struct_pointer = &Book1;
為了使用指向該結(jié)構(gòu)的指針訪問(wèn)結(jié)構(gòu)的成員,必須使用 -> 運(yùn)算符,如下所示:
struct_pointer->title;
可以使用typedef 更簡(jiǎn)單地定義結(jié)構(gòu)
typedef struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
}Books;
// 這樣直接可以用Books 定義結(jié)構(gòu)
Books Book1, Book2;