C++字符串、向量和数组知识概要总结

China☆狼群 提交于 2020-02-28 22:26:07
字符串

记一下string的几种没用过的初始化操作,赋值不能这么搞

string s1("value");
string s2(s1);
string s3(6,'z');
string s4=string(6,'a');

上面没咋提拷贝初始化,带等号的都是拷贝初始化,这里都是直接初始化

getline(cin, line); 

可接受句子,遇到换行符则停止,并且换行符也会被读入,但是这个换行符又被丢弃了

while(getline(cin, line)){
       cout << line << endl;
}

while(cin>>line){
       cout << line << endl;
}

从上述两个例子里可以看出getline确实读入了换行符而且确实又把它给丢弃了。

注意注意注意!!
string.size()这个函数返回的值的类型并不是int,而是string::size_type类型的,并且非常值得注意的是这个类型他是无符号类型的,用这个直接带入一些式子中可能会有意想不到的结果的;

尤其要注意的是s.size()<n这样的结构。~!!

关于string大小的判断,比较第一对相异的字符大小即可,若没有相异的,谁长谁大,或者就是相等

可以用字符字面值和字符串字面值转换成string

当string对象和字符字面值以及字符串字面值混在一起使用是,必须确保加号两边至少一个是string
像string a = “aaa”+“666”+b;这样子的也是错误的!

在这里插入图片描述
上图所示的c值的是单个字符。

关于头文件中.h和c开头的区别

内容上完全一样,只不过c开头的属于命名空间std的而.h的却并不是,而是在include文件里的

使用范围for语句改变字符串中的字符一定要用引用。
为什么?
因为不用引用的话改变的只是c的值而已。

如果某个索引是带符号类型的值的话,将会自动转换为无符号的string::size_type类型。

运算的两个运算对象都为真,则逻辑与结果为真;否则结果为假。对这个运算符来说最重要的一点是,C++语言规定只有当左侧运算对象为真时才会检查右侧运算对象的情况。


关于vector

没有用过的vector初始化

vector<T> v1;
vector<T>v(5); //--->表示的是v中初始化了五个值而不是二维vector
vector<T> v2(v1);
vector<T> v2 = v1;
vector<T> v3(n, val)
vector<T> v4(n)
vector<T> v5{a, b, c..}
vector<T> v6={a, b, c..}

关于vector< string> v{5, “bo”}和vector< int> v{5, 6}的区别,仔细看。

v.size 返回的也是size_type类型

运算符的比较方法也和string一毛一样,即字典序顺序

注意:vector不能以下标形式添加元素。只能用来访问已存在的元素


关于迭代器

严格上讲,string对象不属于容器类型,但是string支持很多与容器类似的操作,比如string同样支持迭代器。

V.end() 指的是v尾元素的下一位置
因此end成员返回的迭代器常被称作是尾后迭代器或者叫尾迭代器。

注意一下一种特殊的情况,当容器为空时,begin和end返回的是同一个迭代器,并且还值得注意的是,此时的begin和end返回的是同一个迭代器,都是尾后迭代器。

迭代器的数据类型方法比较陌生,写的很少,所以写一个

vector<int>::iterator it;
string::iterator it2;

还有一种叫只读迭代器的,就是只能读元素

vector<int>::const_iterator it3;

如果iterator的对象是一个常量,那只能用const_iterator,若不是,那用什么都可以。
有些时候,为了便于专门得到const_iterator类型的返回值,c++11新标准引入了两个新函数,分别是cbegin和cend.用法同begin和end,只不过只读。

对于一个字符串组成的vector来说,可以这么写

*(it).empty();

注意注意注意:这个前面的这个圆括号必不可少!
为了简化上述表达式,就有一种箭头运算符->,把解引用和成员访问两个操作结合在了一起。
即it->empty()和*(it).empty()是一个意思。

先得知道知道有些操作比如push_back会使迭代器失效。后面的章节会详解。
所以要记牢,但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素。

关于迭代器运算

目前知道的string和vector可以使用各种迭代器运算,加减了啥的都行

在这里插入图片描述
使用迭代器运算的一个经典二分,easy。


关于数组

定义数组时,维度必须是常量表达式。

unsigned cnt = 42;
constexpr unsigned sz = 42;
int a[sz];//正确,因为sz是常量表达式
int b[cnt];//错误
int s[get_size];//只有当get_size是constexpr时正确,否则错。

数组不允许拷贝和赋值!!!
当然有些编译器支持赋值,这就是所谓的编译器扩展,但为了兼容性,不写这种。

关于数组的指针和指针的数组和数组的引用和引用的数组

  • 引用的数组:实际上数组,但是数组属于一个对象,不能引用,所以这样是不行的!
  • 数组的引用:实际上是引用,该引用了一个数组。int (&arrRef)[10] = arr;
  • 指针的数组;实际上是数组,这个数组中含有的都是整型指针。int *ptrs[10];
  • 数组的指针:实际上是指针,这个指针,指向了一个数组而已。int (*Parray)[10] = arr;
    数组最好从内向外读;

使用数组下标时,通常定义为size_t类型,注意这是无符号类型,

关于数组,小心溢出

string p = num; //num是数组,等价于p = &num[0];
所以呢num就相当于&num[0];
但是但是但是,当使用decltype的时候却有点不对。即
decltype(num) 这个东西返回的类型却并不是指针,而是某个大小的数组。

指针也是迭代器。vector和string迭代器支持的运算,数组的指针全部支持!

可以通过int *e = &arr[10];这种方式将e作为尾迭代器。
尽管能计算得到尾指针,但是容易出错,所以c++11引入了两个名为begin和end的函数。用法见例子就行。

int ia[] = {0,1,2,3,4,5};
int *beg = begin(ia);
int *last  =end(ia);

尾指针不可以解引用,虽然编译器不会报错,但是这属于使用错误,就不能这么用。

指针指向数组可以使用下标,来个例子就够了

int *p = &a[2];
int j  =p[1]; // p[1] 等价为*(p+1)。
int k = p[-2]; //等价为*(p-2);也就是指向a[0];

也很明显,这里的索引不是无符号型的

char ca[] = {'C', '+', '-', '\0'};  //这里必须最后手动加上空字符,不然strlen函数会出错。
cout << strlen(ca);

strcmp(ca1, ca2); 前大正后大负,一样为0;

不能使用string来初始化指向char的指针。

char *str = s;//s为string,所以这是错误的。
const char *str  = s.c_str();//这是正确的。

用c_str()函数可以做到,但是一定只能返回const char类型的,否则会报错。

虽然我们不能用vector来初始化数组,但是我们可以用数组来初始化vector:

vector<int> v(begin(b), end(b));

也可以只是数组的一部分:

vector<int> v(b+1, b+3);
关于多维数组

严格上讲,c++没有多维数组,通常所说的多维数组其实就是数组的数组罢了,谨记

比如 int ia[3][4];
ia可以这么理解:ia是一个含有三个元素的数组,每个元素本身又都是含有四个元素的数组。

for(auto &c : a)
    for(auto v : c)

这个地方注意了,第一行for必须用引用,不用引用就出错,为什么?
因为c不是引用类型,所以编译器在初始化c的时候,会自动将这些数组形式的元素,转换为指向该数组内首元素的指针!

对于二维数组ai[3][4]
附上三种不同遍历方法:
版本一

for(int (&p)[4] : ia){
    for(int &q : p)
        cout << q;
    cout << endl;
}

版本二

for(int p=0; p<3; p++){
    for(int q=0; q<3; q++)
        cout << ia[p][q];
    cout << endl;
}

版本三

for(int (*p)[4] = ia; p != ia+3; ++p){
    for(int *q = *p; q != *p+3; ++q)
        cout << *q;
    cout << endl;
}

一般来说,应该优先选用标准库提供的类型,之后再考虑C++语言内置的低层的替代品数组或指针。

最后

在这里插入图片描述
确定这样简单明了????

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!