指針是一個變量,其值爲另外一個變量的地址,即,內存位置的直接地址。就像其餘變量或常量同樣,您必須在使用指針存儲其餘變量地址以前,對其進行聲明。指針變量聲明的通常形式爲:html
int *ip; /* 一個整型的指針 */ double *dp; /* 一個 double 型的指針 */ float *fp; /* 一個浮點型的指針 */ char *ch; /* 一個字符型的指針 */
指針的大小是同樣的,都是一個表明內存地址的長的十六進制數。不一樣數據類型的指針之間惟一的不一樣是,指針所指向的變量或常量的數據類型不一樣。前端
指針使用實例:python
#include <iostream> using namespace std; int main () { int var = 20; // 實際變量的聲明 int *ip; // 指針變量的聲明,只聲明未初始化 ip = &var; // 初始化,在指針變量中存儲 var 的地址 cout << "Value of var variable: "; cout << var << endl; //原變量的值是20 // 輸出在指針變量中存儲的地址 cout << "Address stored in ip variable: "; cout << ip << endl; //輸出的是存儲的地址,是地址 // 訪問指針中地址的值 cout << "Value of *ip variable: "; cout << *ip << endl; //加×之後輸出的是地址區域對應的內容是值,這叫指針 return 0; }
指針能夠爲空:ios
在變量聲明的時候,若是沒有確切的地址能夠賦值,爲指針變量賦一個 NULL 值是一個良好的編程習慣。賦爲 NULL 值的指針被稱爲空指針。c++
#include <iostream> using namespace std; int main () { int *ptr = NULL; cout << "ptr 的值是 " << ptr ; return 0; }
指針的可變的:可加可減編程
#include <iostream> using namespace std; const int MAX = 3; int main () { int var[MAX] = {10, 100, 200}; int *ptr; // 指針中的數組地址 ptr = var; for (int i = 0; i < MAX; i++) { cout << "Address of var[" << i << "] = "; cout << ptr << endl; cout << "Value of var[" << i << "] = "; cout << *ptr << endl; // 移動到下一個位置 ptr++; //指針指向的內存地址是能夠經過計算改變的,我估計用的是類似數據存儲位置相近原理 } return 0; }
產生的結果以下:數組
Address of var[0] = 0x7ffe3c8e3980
Value of var[0] = 10
Address of var[1] = 0x7ffe3c8e3984
Value of var[1] = 100
Address of var[2] = 0x7ffe3c8e3988
Value of var[2] = 200數據結構
指針能夠比較大小:dom
#include <iostream> using namespace std; const int MAX = 3; int main () { int var[MAX] = {10, 100, 200}; int *ptr; // 指針默認指向的是數組中的第一個元素,第一個元素的地址,而不是整個數組 ptr = var; int i = 0; while ( ptr <= &var[MAX - 1] ) //指針只要比var[2]小就繼續向下移動 { cout << "Address of var[" << i << "] = "; cout << ptr << endl; cout << "Value of var[" << i << "] = "; cout << *ptr << endl; // 指向上一個位置 ptr++; //指針向下一個元素移動,數組中的內存地址是有講究的,它們按順序排列,因此能夠經過++的方式獲取下一個元素 i++; } return 0; }
指針數組:編程語言
我的以爲指針數組有兩種,一種是建立一個數組用以存儲多個指針,以下:
#include <iostream> using namespace std; const int MAX = 3; int main () { int var[MAX] = {10, 100, 200}; int *ptr[MAX]; //建立一個指針數組,長度爲3 for (int i = 0; i < MAX; i++) { ptr[i] = &var[i]; // 把指針數組中的元素挨個賦值爲var數組中元素的地址 } for (int i = 0; i < MAX; i++) //遍歷指針數組,取值輸出 { cout << "Value of var[" << i << "] = "; cout << *ptr[i] << endl; } return 0; }
返回:
Value of var[0] = 10 Value of var[1] = 100 Value of var[2] = 200
另外一個是建立一個數組不存儲值,而是存儲值存放的內存位置:
#include <iostream> using namespace std; const int MAX = 4; int main () { const char *names[MAX] = { //聲明而且初始化一個指針數組 "Zara Ali", "Hina Ali", "Nuha Ali", "Sara Ali", }; for (int i = 0; i < MAX; i++) { cout << "Value of names[" << i << "] = "; cout << names[i] << endl; //此處要注意,上一個例子打印出內存地址對應的值用的是:*數組名[索引號],而此處不能這樣用,緣由不明,可是若是用*name[i]打印出來的將會是ZHNS,首字母,大約是由於指針指向數組的首個吧,可是name[i]爲什麼能打印出值來,就不得而知了 } return 0; }
返回
Value of names[0] = Zara Ali
Value of names[1] = Hina Ali
Value of names[2] = Nuha Ali
Value of names[3] = Sara Ali
指針能夠指向指針:
聲明:
int **var;
實例:
#include <iostream> using namespace std; int main () { int var; int *ptr; int **pptr; var = 3000; // 獲取 var 的地址 ptr = &var; // 使用運算符 & 獲取 ptr 的地址 pptr = &ptr; // 使用 pptr 獲取值 cout << "var 值爲 :" << var << endl; //3000 cout << "*ptr 值爲:" << *ptr << endl; //3000 cout << "**pptr 值爲:" << **pptr << endl; //3000 return 0; }
指針傳遞給函數:
只要聲明函數的時候說明是指針就能夠了
#include <iostream> #include <ctime> using namespace std; void getSeconds(unsigned long *par); //聲明瞭是無符號常整型的指針,也能夠傳遞數組, int main () { unsigned long sec; getSeconds( &sec ); //用的時候傳遞進去的是地址 // 輸出實際值 cout << "Number of seconds :" << sec << endl; return 0; } void getSeconds(unsigned long *par) { // 獲取當前的秒數 *par = time( NULL ); //實際參數會被改變 return; }
返回:
Number of seconds :1294450468
從函數返回指針:
首先要定義一個返回指針的函數,其次要知道,c++不支持返回純局部變量,除非局部變量爲static
#include <iostream> #include <ctime> #include <cstdlib> using namespace std; // 要生成和返回隨機數的函數 int * getRandom( ) { static int r[10]; // 設置種子 srand( (unsigned)time( NULL ) ); for (int i = 0; i < 10; ++i) //數組是長度爲10的int數組 { r[i] = rand(); cout << r[i] << endl; } return r; } // 要調用上面定義函數的主函數 int main () { // 一個指向整數的指針,由於返回的是指針因此返回的值也必須由指針存儲 int *p; p = getRandom(); for ( int i = 0; i < 10; i++ ) //數組打印出第一個來就好了 { cout << "*(p + " << i << ") : "; cout << *(p + i) << endl; } return 0; }
引用約等於淺拷貝,是原來的變量的別名,因此引用不能爲空,引用不能改變,引用必須在建立的時候被初始化,函數不能返回一個局部變量的引用,static例外
好比:
int i = 17; int& r = i; //r 是一個初始化爲 i 的整型引用
實例:
#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; }
函數返回一個引用實例:
#include <iostream> using namespace std; double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0}; double& setValues( int i ) //從函數的聲明和初始化就能看出來這個函數要返回的是個引用 { return vals[i]; // 返回第 i 個元素的引用 } // 要調用上面定義函數的主函數 int main () { cout << "改變前的值" << endl; for ( int i = 0; i < 5; i++ ) { cout << "vals[" << i << "] = "; cout << vals[i] << endl; } setValues(1) = 20.23; // 改變第 2 個元素 setValues(3) = 70.8; // 改變第 4 個元素 cout << "改變後的值" << endl; for ( int i = 0; i < 5; i++ ) { cout << "vals[" << i << "] = "; cout << vals[i] << endl; } return 0; }
返回:
改變前的值 vals[0] = 10.1 vals[1] = 12.6 vals[2] = 33.1 vals[3] = 24.1 vals[4] = 50 改變後的值 vals[0] = 10.1 vals[1] = 20.23 vals[2] = 33.1 vals[3] = 70.8 vals[4] = 50
引用也能夠做爲參數:
聲明函數的時候這樣作就能夠了:
void swap(int& x, int& y);
c++比c多了處理日期和時間的相關函數和結構,可引用<ctime>,有四個與時間相關的類型:clock_t、time_t、size_t 和 tm。
序號 | 函數 & 描述 |
---|---|
1 | time_t time(time_t *time); 該函數返回系統的當前日曆時間,自 1970 年 1 月 1 日以來通過的秒數。若是系統沒有時間,則返回 .1。 |
2 | char *ctime(const time_t *time); 該返回一個表示當地時間的字符串指針,字符串形式 day month year hours:minutes:seconds year\n\0。 |
3 | struct tm *localtime(const time_t *time); 該函數返回一個指向表示本地時間的 tm 結構的指針。 |
4 | clock_t clock(void); 該函數返回程序執行起(通常爲程序的開頭),處理器時鐘所使用的時間。若是時間不可用,則返回 .1。 |
5 | char * asctime ( const struct tm * time ); 該函數返回一個指向字符串的指針,字符串包含了 time 所指向結構中存儲的信息,返回形式爲:day month date hours:minutes:seconds year\n\0。 |
6 | struct tm *gmtime(const time_t *time); 該函數返回一個指向 time 的指針,time 爲 tm 結構,用協調世界時(UTC)也被稱爲格林尼治標準時間(GMT)表示。 |
7 | time_t mktime(struct tm *time); 該函數返回日曆時間,至關於 time 所指向結構中存儲的時間。 |
8 | double difftime ( time_t time2, time_t time1 ); 該函數返回 time1 和 time2 之間相差的秒數。 |
9 | size_t strftime(); 該函數可用於格式化日期和時間爲指定的格式。 |
實例來一波:
#include <iostream> #include <ctime> using namespace std; int main( ) { // 基於當前系統的當前日期/時間,time_t是ctime中相似於數據類型的一種結構,而time()返回的是1990年至今有多少秒 time_t now = time(0); // 把 now 轉換爲字符串形式,字符串dt是對時間now的一種引用 char* dt = ctime(&now); cout << "本地日期和時間:" << dt << endl; // 把 now 轉換爲 tm 結構 tm *gmtm = gmtime(&now); //這個看起來是指針,函數返回一個指向time的指針 dt = asctime(gmtm); //聽說是格林尼治的時間 cout << "UTC 日期和時間:"<< dt << endl; }
輸出格式化的當前時間:
//這個徹底看不懂 #include <iostream> #include <ctime> #include <stdlib.h> #include <stdio.h> using namespace std; string Get_Current_Date(); int main( ) { // 將當前日期以 20** - ** - ** 格式輸出 cout << Get_Current_Date().c_str() << endl; getchar(); return 0; } string Get_Current_Date() { time_t nowtime; nowtime = time(NULL); //獲取日曆時間 char tmp[64]; strftime(tmp,sizeof(tmp),"%Y-%m-%d %H:%M:%S",localtime(&nowtime)); return tmp; }
I/O庫重要的頭文件:
頭文件 | 函數和描述 |
---|---|
<iostream> | 該文件定義了 cin、cout、cerr 和 clog 對象,分別對應於標準輸入流、標準輸出流、非緩衝標準錯誤流和緩衝標準錯誤流。 |
<iomanip> | 該文件經過所謂的參數化的流操縱器(好比 setw 和 setprecision),來聲明對執行標準化 I/O 有用的服務。 |
<fstream> | 該文件爲用戶控制的文件處理聲明服務。咱們將在文件和流的相關章節討論它的細節。 |
標準輸出流:cout
#include <iostream> using namespace std; int main( ) { char str[] = "Hello C++"; cout << "Value of str is : " << str << endl; }
標準輸入流:
#include <iostream> using namespace std; int main( ) { char name[50]; cout << "請輸入您的名稱: "; cin >> name; //用戶的輸入賦值給name,相似於python的input cout << "您的名稱是: " << name << endl; }
標準錯誤流:cerr 對象是非緩衝的,且每一個流插入到 cerr 都會當即輸出。不大明白用法,且先看吧
#include <iostream> using namespace std; int main( ) { char str[] = "Unable to read...."; cerr << "Error message : " << str << endl; }
標準日誌流:clog 對象是緩衝的。這意味着每一個流插入到 clog 都會先存儲在緩衝在,直到緩衝填滿或者緩衝區刷新時纔會輸出。
#include <iostream> using namespace std; int main( ) { char str[] = "Unable to read...."; clog << "Error message : " << str << endl; }
良好的編程實踐告訴咱們,使用 cerr 流來顯示錯誤消息,而其餘的日誌消息則使用 clog 流來輸出。
C/C++ 數組容許定義可存儲相同類型數據項的變量,可是結構是 C++ 中另外一種用戶自定義的可用的數據類型,它容許您存儲不一樣類型的數據項。
可用struct定義結構,如下是結構實例:
struct Books { char title[50]; char author[50]; char subject[100]; int book_id; } book; //聲明一個結構體類型 Books,變量爲 book:
用英文點號訪問結構成員,
#include <iostream> #include <cstring> using namespace std; // 聲明一個結構體類型 Books struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; int main( ) { Books Book1; // 定義結構體類型 Books 的變量 Book1 Books Book2; // 定義結構體類型 Books 的變量 Book2 // Book1 詳述 strcpy( Book1.title, "C++ 教程"); //strcpy字符串拷貝命令,把第二個字符串的值賦值給第一個,至關於給books結構的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, "前端技術"); Book2.book_id = 12346; // 輸出 Book1 信息 cout << "第一本書標題 : " << Book1.title <<endl; //輸出的時候基本格式是實例加.加結構內容 cout << "第一本書做者 : " << Book1.author <<endl; cout << "第一本書類目 : " << Book1.subject <<endl; cout << "第一本書 ID : " << Book1.book_id <<endl; // 輸出 Book2 信息 cout << "第二本書標題 : " << Book2.title <<endl; cout << "第二本書做者 : " << Book2.author <<endl; cout << "第二本書類目 : " << Book2.subject <<endl; cout << "第二本書 ID : " << Book2.book_id <<endl; return 0; }
結構做爲函數的參數:
#include <iostream> #include <cstring> using namespace std; void printBook( struct Books book ); //聲明一個函數,參數是結構 // 聲明一個結構體類型 Books struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; int main( ) { Books Book1; // 定義結構體類型 Books 的變量 Book1 Books Book2; // 定義結構體類型 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, "前端技術"); Book2.book_id = 12346; // 輸出 Book1 信息 printBook( Book1 ); //直接把結構傳遞進去就好了,不用加struct // 輸出 Book2 信息 printBook( Book2 ); return 0; } void printBook( struct Books book ) //函數實現 { cout << "書標題 : " << book.title <<endl; cout << "書做者 : " << book.author <<endl; cout << "書類目 : " << book.subject <<endl; cout << "書 ID : " << book.book_id <<endl; }
指向結構的指針:
#include <iostream> #include <cstring> using namespace std; void printBook( struct Books *book ); //函數聲明,聲明須要一個結構的實例的指針 struct Books //預約義結構的內容 { char title[50]; char author[50]; char subject[100]; int book_id; }; int main( ) { Books Book1; // 定義結構體類型 Books 的變量 Book1 Books Book2; // 定義結構體類型 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, "前端技術"); Book2.book_id = 12346; // 經過傳 Book1 的地址來輸出 Book1 信息 printBook( &Book1 ); //由於須要的是指針,因此要把book1 book2 的內存地址放進去 // 經過傳 Book2 的地址來輸出 Book2 信息 printBook( &Book2 ); return 0; } // 該函數以結構指針做爲參數 void printBook( struct Books *book ) { cout << "書標題 : " << book->title <<endl; //此處要特別注意,訪問指針指向的實例中的結構內容的話,不能繼續用點號了,要用->號,不用問爲啥,由於是規定 cout << "書做者 : " << book->author <<endl; cout << "書類目 : " << book->subject <<endl; cout << "書 ID : " << book->book_id <<endl; }
補充typedef:
typedef爲C語言的關鍵字,做用是爲一種數據類型定義一個新名字。這裏的數據類型包括內部數據類型(int,char等)和自定義的數據類型(struct等)。在編程中使用typedef目的通常有兩個,一個是給變量一個易記且意義明確的新名字,另外一個是簡化一些比較複雜的類型聲明。
//(1)用typedef聲明一個新類型名來代替已有的類型名。如 typedef int Status //指定標識符Status表明int類型 typedef double DATE //指定標識符DATE表明double類型 int i; Status i; //等價的 //(2)用typedef對數組類型起新名: typedef int NUM[100];//聲明NUM爲整數數組類型,能夠包含100個元素 NUM n;//定義n爲包含100個整數元素的數組,n就是數組名 //(3)對一個結構體類型聲明一個新名字: typedef struct //在struct以前用了關鍵字typedef,表示是聲明新類型名 { int month; int day; int year; } TIME; //TIME是新類型名,但不是新類型,也不是結構體變量名,這樣就能夠用TIME定義該結構體變量,如: TIME birthday; //不用typeof的時候: struct Books //Books是結構體類型 { char title[50]; char author[50]; char subject[100]; int book_id; } book; //book是結構變量