C++中一些散碎的知識點_int **指針與二維數組問題_memset()和memcpy()_C++中vector的介紹_C++讀txt中數據到一個vector中_C++ split分割字符串函數_隨

目錄

一、int **指針與二維數組問題html

二、memset()和memcpy()ios

三、C++中vector的介紹算法

四、C++讀txt中數據到一個vector中 *****數組

五、C++ split分割字符串函數ide

六、隨機函數初始化函數srand函數

七、關於getline()函數:分在<istream>中的getline()和在<string>中的getline()佈局

八、istringstream的用法測試

九、迭代器大數據

一、int **指針與二維數組問題

01)定義二維數組方法:spa

int matrix[ROWS][COLUMNS];  //定義一個二維數組,其中ROWS和COLUMNS爲常數

02)加入有以下聲明的子函數:

void printMatrix(int ** numbers,int rows,int columns);

03)若是直接使用以下方法調用,是錯誤的;

printMatrix(matrix,ROWS,COLUMNS);  //直接這樣調用時錯誤的

緣由在於matrix是 int (*)[COLUMNS]類型的,可是函數printMatrix須要的是int **類型的,這二者明顯不匹配。

int **從類型上講是一個指向整型指針的指針,那麼若是想要用它來表示一個矩陣須要怎麼作呢?由於它的元素是一個指針,若是若是它的每個元素都表示矩陣的一行,那麼它就能夠用來表示一個矩陣了。實現代碼以下:

 1 //生成矩陣  
 2 int ** generateMatrix(int rows,int columns)  
 3 {  
 4     int **numbers=new int*[rows];  
 5     for(int i=0;i<rows;i++){  
 6         numbers[i]=new int[columns];  
 7         for(int j=0;j<columns;j++)  
 8                 numbers[i][j]=i*columns+j;  
 9     }  
10     return numbers;   
11 }
用int **來表示一個矩陣

把int*當作一個總體。它表示建立了一個大小爲rows的數組,這個數組的每個元素表明一個指針。內存佈局以下:

這裏numbers是一個指向指針的指針,可以用numbers用來表示矩陣的關鍵就在於使用new關鍵字分配的內存是連續的,這樣number[i]的地址就能夠根據numbers的地址計算出來,由於指針變量佔據4個字節的內存區域(32位機器)。若是不使用上面的方式分配內存,numbers就真的只是一個指向指針的指針了

04)正確使用printMatrix(matrix,ROWS,COLUMNS)的測試代碼:

 1 #include <stdlib.h>  
 2 #include <stdio.h>  
 3 #include <iostream>  
 4 //打印矩陣  
 5 void printMatrix(int ** numbers,int rows,int columns){  
 6     for(int i=0;i<rows;i++)  
 7     {  
 8             for(int j=0;j<columns;j++)  
 9                     std::cout<<numbers[i][j]<<" ";  
10         std::cout<<std::endl;  
11     }  
12 }  
13   
14 //生成矩陣  
15 int ** generateMatrix(int rows,int columns)  
16 {  
17     int **numbers=new int*[rows];  
18     for(int i=0;i<rows;i++){  
19         numbers[i]=new int[columns];  
20         for(int j=0;j<columns;j++)  
21                 numbers[i][j]=i*columns+j;  
22     }  
23     return numbers;   
24 }  
25 int main(){  
26     int **numbers=generateMatrix(4,5);  
27     printMatrix(numbers,4,5);  
28     //釋放內存  
29     for(int i=0;i<4;i++)  
30             delete [] numbers[i];  
31     delete numbers;  
32     return 0;
View Code

 參考博客:

https://www.cnblogs.com/lpxblog/tag/C%2B%2B%E9%9D%A2%E8%AF%95%E9%A2%98/

二、memset()和memcpy()

1、memset()用法

void *memset(void *s,int c,size_t n)

做用:將已開闢內存空間 s 的首 n 個字節的值設爲值 c(給空間初始化)

C語言須要包含頭文件string.h;C++須要包含cstring  或  string.h

 1 #include <string.h>
 2  
 3   #include <stdio.h>
 4  
 5   #include <memory.h>
 6  
 7   int main(void)
 8  
 9   {
10  
11   char buffer[] = "Hello world\n";
12  
13   printf("Buffer before memset: %s\n", buffer);
14  
15   memset(buffer, '*', strlen(buffer) );
16  
17   printf("Buffer after memset: %s\n", buffer);
18  
19   return 0;
20  
21   }
示例

輸出結果:

  Buffer before memset: Hello world

  Buffer after memset: ***********

memset() 函數經常使用於內存空間初始化。如:

  char str[100];

  memset(str,0,100);

memset()錯誤用法:

 1 int main(void)
 2  
 3   {
 4  
 5   char *buffer = "Hello world\n";
 6  
 7   printf("Buffer before memset: %s\n", buffer);
 8  
 9   memset(buffer, '*', strlen(buffer) );
10  
11   printf("Buffer after memset: %s\n", buffer);
12  
13   return 0;
14  
15   }
memset()錯誤用法

報錯緣由:char * buffer = "Hello world\n";    字符串"Hello world\n"存在於只讀存儲區,其內容不能被隨意更改!!!!

2、memcpy()函數用法

void *memcpy(void *dest, const void *src, size_t n);

C語言須要包含頭文件string.h;C++須要包含cstring  或  string.h。

用法:用來將src地址處的內容拷貝n個字節的數據至目標地址dest指向的內存中去。函數返回指向dest的指針。

示例1:

做用:將s中的字符串複製到字符數組d中

 1 #include <stdio.h>
 2 #include <string.h>
 3 int main()
 4 {
 5 char *s="Golden Global View";
 6 char d[20];
 7 clrscr();
 8 memcpy(d,s,( strlen(s)+1) );
 9 printf("%s",d);
10 getchar();
11 return 0;
12 }
13 輸出結果:Golden Global View
View Code

示例2:

做用:將s中第14個字符開始的4個連續字符複製到d中。(從0開始)

 1 #include <string.h>
 2 int main(
 3 {
 4 char *s="Golden Global View";
 5 char d[20];
 6 memcpy(d,s+14,4); //從第14個字符(V)開始複製,連續複製4個字符(View) //memcpy(d,s+14*sizeof(char),4*sizeof(char));也可
 7 d[4]='\0';
 8 printf("%s",d);
 9 getchar();
10 return 0;
11 }
12 輸出結果: View
View Code

示例3:

做用:複製後覆蓋原有部分數據;

 1 #include <stdio.h>
 2 #include <string.h>
 3 int main(void)
 4 {
 5 char src[] = "******************************";
 6 char dest[] = "abcdefghijlkmnopqrstuvwxyz0123as6";
 7 printf("destination before memcpy: %s\n", dest);
 8 memcpy(dest, src, strlen(src));
 9 printf("destination after memcpy: %s\n", dest);
10 return 0;
11 }
12 輸出結果:
13 destination before memcpy:abcdefghijlkmnopqrstuvwxyz0123as6
14 destination after memcpy: ******************************as6
View Code

3、注意事項:
    memcpy用來作內存拷貝,你能夠拿它拷貝任何數據類型的對象,能夠指定拷貝的數據長度;例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),會形成b的內存溢出。

    另外:strcpy只能拷貝字符串,它遇到'\0'就結束拷貝;例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字符串長度(第一個‘\0’以前)是否超過50位,如超過,則會形成b的內存溢出。會形成緩衝區溢出,輕者程序崩潰,重者系統會出現問題!!

三、C++中vector的介紹

1)相關頭文件和命名域

     在使用它時, 須要包含頭文件 vector, 即: #include<vector>

     vector屬於std命名域的,所以須要經過命名限定,以下完成你的代碼:using std::vector;

2)、vector向量聲明和初始化

1 vector<int> a ;                             //聲明一個int型向量a
2 vector<int> a(10) ;                       //聲明一個初始大小爲10的向量
3 vector<int> a(10, 1) ;                   //聲明一個初始大小爲10且初始值都爲1的向量
4 vector<int> b(a) ;                         //聲明並用向量a初始化向量b
5 vector<int> b(a.begin(), a.begin()+3) ;        //將a向量中從第0個到第2個(共3個)做爲向量b的初始值

 除此以外, 還能夠直接使用數組來初始化向量:

1 int n[] = {1, 2, 3, 4, 5} ;
2 vector<int> a(n, n+5) ;              //將數組n的前5個元素做爲向量a的初值
3 vector<int> a(&n[1], &n[4]) ;        //將n[1] - n[4]範圍內的元素做爲向量a的初值

3)、元素輸入和輸出

 1 #include<iostream>
 2 #include<vector>
 3 
 4 using namespace std ;
 5 
 6 int main()
 7 {
 8     vector<int> a(10, 0) ;      //大小爲10初值爲0的向量a
 9 
10     //對其中部分元素進行輸入
11     cin >>a[2] ;
12     cin >>a[5] ;
13     cin >>a[6] ;
14 
15     //所有輸出
16     int i ;
17     for(i=0; i<a.size(); i++)
18         cout<<a[i]<<" " ;
19 
20     return 0 ;
21 }
View Code

向量元素的位置便成爲遍歷器, 同時, 向量元素的位置也是一種數據類型, 在向量中遍歷器的類型爲: vector<int>::iterator。 遍歷器不但表示元素位置, 還能夠再容器中先後移動。

1 //使用迭代器所有輸出
2 vector<int>::iterator t ;
3 for(t=a.begin(); t!=a.end(); t++)  //a.begin()表示容器中的第一個元素位置,a.end()表示容器a中最後一個元素位置
4     cout<<*t<<" " ;  // *t 爲指針的間接訪問形式, 意思是訪問t所指向的元素值。

4)、向量的基本操做

 1 1>. a.size()                 //獲取向量中的元素個數
 2 2>. a.empty()                //判斷向量是否爲空
 3 3>. a.clear()                //清空向量中的元素
 4 4>. 複製 a = b ;            //將b向量複製到a向量中
 5 5>. 比較
 6         保持 ==、!=、>、>=、<、<= 的慣有含義 ;
 7         如: a == b ;    //a向量與b向量比較, 相等則返回1
 8  6>. 插入 - insert
 9         ①、 a.insert(a.begin(), 1000);            //將1000插入到向量a的起始位置前
10         
11         ②、 a.insert(a.begin(), 3, 1000) ;        //將1000分別插入到向量元素位置的0-2處(共3個元素)
12         
13         ③、 vector<int> a(5, 1) ;
14             vector<int> b(10) ;
15             b.insert(b.begin(), a.begin(), a.end()) ;        //將a.begin(), a.end()之間的所有元素插入到b.begin()前
16 7>. 刪除 - erase
17         ①、 b.erase(b.begin()) ;                     //將起始位置的元素刪除
18         ②、 b.erase(b.begin(), b.begin()+3) ;        //將(b.begin(), b.begin()+3)之間的元素刪除
19 8>. 交換 - swap
20         b.swap(a) ;            //a向量與b向量進行交換
View Code
 1 c.max_size()       // 返回容器中最大數據的數量。
 2 c.pop_back()       // 刪除最後一個數據。
 3 c.push_back(elem)  // 在尾部加入一個數據。
 4 c.rbegin()         // 傳回一個逆向隊列的第一個數據。
 5 c.rend()           // 傳回一個逆向隊列的最後一個數據的下一個位置。
 6 c.resize(num)      // 從新指定隊列的長度。
 7 c.reserve()        // 保留適當的容量。
 8 c.size()           // 返回容器中實際數據的個數。
 9 c1.swap(c2)
10 swap(c1,c2)        // 將c1和c2元素互換。同上操做。
View Code

加:插入元素:    vec.insert(vec.begin()+i,a);在第i+1個元素前面插入a;

       刪除元素:    vec.erase(vec.begin()+2);刪除第3個元素

      vec.erase(vec.begin()+i,vec.end()+j);刪除區間[i,j-1];區間從0開始

      向量大小:vec.size();

      清空:vec.clear();

5)、和vector相關的算法(如下均須要包含頭文件:#include <algorithm>)

 1 reverse(vec.begin(),vec.end());將元素翻轉,即逆序排列!sort(vec.begin(),vec.end());(默認是按升序排列,即從小到大).
 2 /*輸出Vector的中的元素 */ 
 3 /*方法一:*/
 4 vector<float> vecClass; 
 5 int nSize = vecClass.size();  
 6 for(int i=0;i<nSize;i++)  
 7 {  
 8    cout<<vecClass[i]<<"     ";  
 9 }  
10    cout<<endl;
11 /*方法二:*/
12 vector<float> vecClass; 
13 int nSize = vecClass.size();  
14 for(int i=0;i<nSize;i++)  
15 {  
16    cout<<vecClass.at(i)<<"     ";  
17 }  
18    cout<<endl;  
19 /*方法三:*/
20 for(vector<float>::iterator it = vecClass.begin();it!=vecClass.end();it++)  
21 {  
22     cout<<*it<<"   ";  
23 }  
24     cout<<endl; 
View Code

6)、注意事項

1)、若是你要表示的向量長度較長(須要爲向量內部保存不少數),容易致使內存泄漏,並且效率會很低;

2)、Vector做爲函數的參數或者返回值時,須要注意它的寫法:

     double Distance(vector<int>&a, vector<int>&b) 其中的「&」絕對不能少!!!

7)、其餘

vector默認構造函數會將容器內的值設置爲0

例:

 1 #include <iostream>
 2 #include <vector>
 3 
 4 using namespace std;
 5 
 6 int mian()
 7 {
 8     vector<vector<int>> tempResult(L);
 9     for (int i = 0; i < tempResult.size(); i++)
10            tempResult[i].resize(L);      //resize()函數設置數組大小,會分配內存;reserve()不會分配內存,只是設置容器大小
11     for (int i = 0; i < L; i++)
12     {
13     for (int j = 0; j < L; j++)
14     {
15         cout << tempResult[i][j] << " ";
16     }
17     cout << endl;
18     }
19 
20     system("pause");
21     return 0;
22 }
View Code

運行結果:

參考博客:

https://blog.csdn.net/duan19920101/article/details/50617190

http://www.javashuo.com/article/p-kouqqfmk-cb.html

四、C++讀txt中數據到一個vector中

 1 #include <iostream>
 2 using namespace std;
 3 #include <cmath>
 4 #include <vector>
 5 #include <fstream>
 6  
 7 //將文本文件中得數據讀入vector中,並返回一個vector。
 8 vector<int> *InputData_To_Vector()
 9 {
10   vector<int> *p = new vector<int>;
11   ifstream infile("/Users/……/inputdata.txt");
12   int number;
13   while(! infile.eof())
14   {
15     infile >> number;
16     p->push_back(number);
17   }
18   p->pop_back(); //此處要將最後一個數字彈出,是由於上述循環將最後一個數字讀取了兩次
19   return p;
20 }
21  
22 inline int Num_Square(int n)
23 {
24   return n*n;
25 }
26  
27 int Sum_Of_Num_Square(vector<int> *p)
28 {
29   int Sum2 = 0;
30   vector<int>::iterator it;
31   for(it=p->begin(); it!=p->end(); it++)
32   {
33     Sum2 += Num_Square(*it);
34   }
35   return Sum2;
36 }
37  
38 //調用傳入的vector
39 int main(int argc, const char * argv[]) {
40   // insert code here...
41   vector<int> *file_to_vector = InputData_To_Vector();
42   cout<<"sum2="<<Sum_Of_Num_Square(file_to_vector)<<endl;
43   return 0;
44 }
45  
讀txt數據到一個vector中

帶註釋版本:

 1 #include <iostream>
 2 #include <cmath>
 3 #include <vector>
 4 #include <fstream>
 5 #include <string>
 6 
 7 using namespace std;
 8 
 9 //將文本文件中得數據讀入vector中,並返回一個vector。
10 vector<int> *InputData_To_Vector()
11 {
12     vector<int> *p = new vector<int>;
13     ifstream infile("inputdata.txt");
14     if (infile.peek() == EOF)          //若txt爲空則peek()返回EOF
15     {
16         cout << "file is empty!" << endl;
17         system("pause");
18         return 0;
19     }
20     int number;
21     string str;
22     while (!infile.eof())            //若讀到文件尾,eof()返回true
23     {
24         //infile >> number;            //以空格做爲數字和數字之間的分隔符
25         //p->push_back(number);
26         getline(infile, str, '\n');    //如果逗號做爲分隔符,則使用getline()輸入方法,以後再分割數字
27         cout << str << endl;
28     }
29     //p->pop_back(); //此處要將最後一個數字彈出,是由於上述循環將最後一個數字讀取了兩次
30     infile.close();  //關閉文件
31     return nullptr;
32 }
33 
34 inline int Num_Square(int n)
35 {
36     return n * n;
37 }
38 
39 int Sum_Of_Num_Square(vector<int> *p)
40 {
41     int Sum2 = 0;
42     vector<int>::iterator it;
43     for (it = p->begin(); it != p->end(); it++)
44     {
45         Sum2 += Num_Square(*it);
46     }
47     return Sum2;
48 }
49 
50 //調用傳入的vector
51 int main(int argc, const char * argv[]) {
52     // insert code here...
53     vector<int> *file_to_vector = InputData_To_Vector();
54     /*for (int i = 0; i < file_to_vector->size(); i++)
55         cout << file_to_vector->at(i) << " ";
56     cout << endl;*/
57     //cout << "sum2=" << Sum_Of_Num_Square(file_to_vector) << endl;
58     system("pause");
59     return 0;
60 }
View Code

運行結果:

 

注:在該vs工程目錄下有一個inputdata.txt文件內容即爲上圖中的數字

五、C++ split分割字符串函數

將字符串綁定到輸入流istringstream,而後使用getline的第三個參數,自定義使用什麼符號進行分割就能夠了。

 1 #include <iostream>
 2 #include <sstream>
 3 #include <string>
 4 #include <vector>
 5 using namespace std;
 6 void split(const string& s,vector<int>& sv,const char flag = ' ') {
 7     sv.clear();
 8     istringstream iss(s);
 9     string temp;
10 
11     while (getline(iss, temp, flag)) {
12         sv.push_back(stoi(temp));
13     }
14     return;
15 }
16 
17 int main() {
18     string s("123:456:7");
19     vector<int> sv;
20     split(s, sv, ':');
21     for (const auto& s : sv) {
22         cout << s << endl;
23     }
24     system("pause");
25     return 0;
26 }
C++中本身寫的split函數

注:C++中是沒有split()函數的。可是在Qt中是有的

帶註釋版本:

 1 #include <iostream>  //for istringstream
 2 #include <sstream>
 3 #include <string>
 4 #include <vector>
 5 using namespace std;
 6 void split(const string& s, vector<int>& sv, const char flag = ' ') 
 7 {
 8     sv.clear();
 9     istringstream iss(s);             //將字符串s中的字符輸入到輸入流中去,並構造字符串輸入流對象iss
10     string temp;
11 
12     while (getline(iss, temp, flag))  //將iss中的字符輸入到temp中去,以字符串變量flag爲分隔符,遇到換行符則結束while循環
13     {                                 
14         sv.push_back(stoi(temp));     //int stoi(const string* str) stoi將數字字符串str轉換成十進制並返回
15     }                                 //int atoi(const char* str)  atoi將數字字符串str轉換成十進制並返回
16     return;                           //c_str()將string類型的字符串轉換成char型的,c_str()是string類下的一個方法
17 }
18 
19 int main() 
20 {
21     string s("123:456:7");
22     vector<int> sv;
23     split(s, sv, ':');
24     for (const auto& str : sv)         //str爲一個引用變量,即修改str的值也會修改sv中的值
25     {
26         cout << str << endl;           //等價於不斷輸出sv[0]、sv[1]...
27     }
28     system("pause");
29     return 0;
30 }
View Code

參考博客:http://www.javashuo.com/article/p-bjdypjnh-bk.html

六、隨機函數初始化函數srand

srand函數是隨機數發生器的初始化函數,

    計算機並不能產生真正的隨機數,而是已經編寫好的一些無規則排列的數字存儲在電腦裏,把這些數字劃分爲若干相等的N份,併爲每份加上一個編號用srand()函數獲取這個編號,而後rand()就按順序獲取這些數字,當srand()的參數值固定的時候,rand()得到的數也是固定的,因此通常srand的參數用time(NULL),由於系統的時間一直在變,因此rand()得到的數,也就一直在變,至關因而隨機數了。

    若是想在一個程序中生成隨機數序列,須要至多在生成隨機數以前設置一次隨機種子。 即:只需在主程序開始處調用srand((unsigned)time(NULL)); 後面直接用rand就能夠了。不要在for等循環放置srand((unsigned)time(NULL));

參考博客:https://blog.csdn.net/jx232515/article/details/51510336

七、關於getline()函數:分在<istream>中的getline()和在<string>中的getline()

此部分在第五部分中構造split()函數有使用到

(1)在<istream>中的getline()

在<istream>中的getline()函數有兩種重載形式:(本身的理解)

1 getline(char* s,streamsize n,char str)
2 getline(char* s,streamsize n)

都是從輸入流中讀取至多n的字符保存在s中,即便沒有讀夠n個字符,遇到了str,則讀取也會終止,str不會保存在s中.

在<istream>中的getline()函數有兩種重載形式:(別人的理解)

1 istream& getline (char* s, streamsize n );
2 istream& getline (char* s, streamsize n, char delim );

從istream中讀取至多n個字符(包含結束標記符)保存在s對應的數組中。即便還沒讀夠n個字符,

若是遇到delim或 字數達到限制,則讀取終止,delim都不會被保存進s對應的數組中。

(2)在<string>中的getline()

在<string>中的getline函數有四種重載形式:

1 istream& getline (istream&  is, string& str, char delim);
2 istream& getline (istream&& is, string& str, char delim);
3 istream& getline (istream&  is, string& str);              //默認delim = '\n'
4 istream& getline (istream&& is, string& str);              //默認delim = '\n'

用法和<istream>中的getlien()相似,可是讀取的istream是做爲參數is傳進函數的。讀取的字符串保存在string類型的str中。

函數的變量:

is    :表示一個輸入流,例如cin。

str   :string類型的引用,用來存儲輸入流中的流信息。

delim :char類型的變量,所設置的截斷字符;在不自定義設置的狀況下,遇到’\n’,則終止輸入。

參考博客:https://blog.csdn.net/qfc8930858/article/details/80957329

八、istringstream的用法

istringstream在第5部分中split()函數的構造中有使用到

istringstream 類用於執行C++風格的串流的輸入操做

istringstream用空格做爲字符串分隔符

istringstream的構造函數原形以下:

istringstream::istringstream(string str);

它的做用是從string對象str中讀取字符。

測試代碼:

 1 #include<iostream>  
 2 #include<sstream>               //istringstream 必須包含這個頭文件
 3 #include<string>  
 4 using namespace std;
 5 int main()
 6 {
 7     string str = "I am a boy";
 8     istringstream is(str);     //從str讀取字符串到輸入流中
 9     string s;
10     while (is >> s)            //以空格爲分隔符,遇到換行符'\n'結束
11     {
12         cout << s << endl;
13     }
14     system("pause");
15     return 0;
16 }
View Code

運行結果:

 參考博客:https://blog.csdn.net/longzaitianya1989/article/details/52909786

 九、迭代器

對於如下代碼:

1 vector<string> &strs;
2 for (const auto &s : strs)
3 {
4     //do nothing;
5 }

能夠替換爲:

1 vector<string> strs;
2 const vector<string>::iterator end_it = strs.end();
3 
4 for (vector<string>::iterator it = strs.begin(); it != end_it; ++it) 
5 {
6     const string& s = *it;
7     // Some code here...
8 }

迭代器的幾種輸出方式:

 1 #include<vector>
 2 #include<string>
 3 #include<iostream>
 4 using namespace std;
 5 int main()
 6 {
 7     vector<string> text;
 8     string word;
 9     while (getline(cin, word))
10         {                                         //循環讀入字符串至vector<string>中,以trl+z回車結束
11         text.push_back(word);
12     }
13     //下標迭代方式輸出
14     cout << "下標迭代方式輸出" << endl;
15     for (vector<string>::size_type ix = 0; ix != text.size(); ++ix)
16         cout << text[ix] << endl;
17  
18     //迭代器方式輸出
19     cout << "迭代器方式輸出" << endl;
20     for (vector<string>::iterator it = text.begin(); it != text.end(); it++)
21        {
22         cout << *it << endl;
23     }
24     //int result = uniqueMorseRepresentations(text);
25  
26     //精簡迭代方式輸出
27     cout << "精簡迭代方式輸出" << endl;
28     for (const string& words : text)
29         {
30         cout << words << endl;
31     }
32     getchar();
33     return 1;
34 }
View Code
相關文章
相關標籤/搜索