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
相关文章
相关标签/搜索