四、C++讀txt中數據到一個vector中 *****數組
七、關於getline()函數:分在<istream>中的getline()和在<string>中的getline()佈局
九、迭代器大數據
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*當作一個總體。它表示建立了一個大小爲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;
參考博客:
https://www.cnblogs.com/lpxblog/tag/C%2B%2B%E9%9D%A2%E8%AF%95%E9%A2%98/
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 }
報錯緣由: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
示例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
示例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
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的內存溢出。會形成緩衝區溢出,輕者程序崩潰,重者系統會出現問題!!
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 }
向量元素的位置便成爲遍歷器, 同時, 向量元素的位置也是一種數據類型, 在向量中遍歷器的類型爲: 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向量進行交換
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元素互換。同上操做。
加:插入元素: 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;
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 }
運行結果:
參考博客:
https://blog.csdn.net/duan19920101/article/details/50617190
http://www.javashuo.com/article/p-kouqqfmk-cb.html
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
帶註釋版本:
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 }
運行結果:
注:在該vs工程目錄下有一個inputdata.txt文件內容即爲上圖中的數字
將字符串綁定到輸入流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()函數的。可是在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 }
參考博客:http://www.javashuo.com/article/p-bjdypjnh-bk.html
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
此部分在第五部分中構造split()函數有使用到
在<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對應的數組中。
在<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在第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 }
運行結果:
參考博客: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 }