四、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 }