字符串向量和数组
using
的使用说明::
表示作用域限定符号,可以使用using namespace::name
来统一使用命名空间;using namespace std; using std::cout; using std::cin;
也可以通过
using std::out
这样的方式在,需要使用的时候进行使用,这样使用的话,每个using
都需要引入一条声明;- 在自己声明的头文件里面,一般是不能够包含
using
声明的,防止和主文件里面命名空间发生冲突;
string
对象的简单使用
- 定义和初始化
string
对象string s1; string s2 = s1; string s3("hello"); string s4(10,'c');
- 对于上面的初始化类型:如果使用
=
进行的是拷贝初始化,不使用=
进行的是直接初始化操作; - 常用的操作:
- 读入数据
string s; cin >> s;
;在输入的过程中,会自动忽略开头的空白字符,但是不会忽略字符中间的空白字符,同时,
支持cin >> s1 >> s2;
;这种一次输入多个字符的操作; - 使用
getline()
来读取一行getline(cin,string line)
,函数的返回值是读取的字符长度;在字符输出的过程时,需要
手动的加上换行符;因为读入line
里面的不包含换行符号; empty
根据string
对象是否为空,返回一个对应的bool
值;size
用于返回字符串的长度;size_type
类型,是一个无符号类型的值,用于存放任何大小的,所以需要注意的是unsigned
和int
是不能够进行比较== and !=
:用于判断字符串是否相等.严格区分大小写,严格按照字典序进行比较;+
表示就是将字符串进行拼接,s1 + s2
,同样的也支持字面值常量和string
对象相加,但是两个字面值是没有办法
相加的"hello"+","
这种表示就是错误的- 切记字符串字面值和
string
是不同的类型;
- 读入数据
- 定义和初始化
关于字符串处理的一些函数:
函数名 功能 isalnum(c) 表示 c
是字母或者是数字isalpha(c) 表示 c
是字母iscntrl(c) 是控制字符为真 isdigit(c) 表示是数字 isgraph(c) 表示不是空格但是可以打印 islower(c) 表示是小写字母 isprint(c) 表示是可打印字符 ispunct(c) 表示是标点符号 ispace(c) 表示是空白字符 isupper(c) 表示是大写字母 isxdigit(c) 表示是16进制数字 tolower(c) 如果是大写字母,输出相应的小写 toupper(c) 表示如果是小写字母,输出相应的大写 C++11
支持的一种新的写法:for(declaration : expression){ statement; }
1.
expression
表示的含义是一个对象,或者是一个队列;declaration
用于定义一个变量,这个变量用于访问序列中的基础元素,每次进行迭代,这个元素的值,都会被初始化为下一个元素的值,如果希望改变对象中单个元素的值,就需要使用引用操作;- 2.同时也是可以使用下标运算符来访问
string
对象里面的元素的,需要严格保证下标不越界,如果使用下进行访问,首先应该确定对象是否为空s.empty()
操作; toupper.cpp
;
#include<iostream>
#include <vector>
using namespace std;
int main(){
vector<string> mystring{"Hello","world","this","is","a","freshman"};
for(auto h:mystring){
for(auto &m:h){
m=toupper(m);
}
cout << h << " ";
}
}
- 对于
string
支持的常见操作就不赘述了;
标准库类型<vector>
<vector>
:在C++
语言中包含类模板和函数模板,<vector>
表示的是类模板,模板本身并不是类或者函数,模板更像是一种说明,实例化表示的是编译器根据模板创建类或者函数的过程,也就是在使用模板时,需要声明模板的类型;例如vector<int> myvector
;<vector>
支持大多数类型作为模板参数,但是引用不属于具体类型,所以引用不能够作为模板参数;<vector>
作为模板参数<vector><vector><int>>
这种那个情况也是支持的;vector
可以容纳大多数对象作为其模板参数,但是引用不是对象,所以不能够用作实例化,内置类型(除了引用)
以及类类型,vector
类型都是可以的;
int lk=10;
int rlk=lk;
//这种就是错误的;
vector<rlk> myvectorrlk;
定义和初始化
<vector>
的方法方法 含义 vector<T> v1
表示执行默认初始化 vector<T> V2(V1)
v2
里面包含v1
的所有副本vector<T> v2 = v1
表示执行拷贝构造函数 vector<T> V3(n,va1)
等价于 v2(v1)
,v2
中包含所有v1
的副本vector<T> V4(n)
表示执行n个元素的初始化 vector<T> V5(a,b,c,...)
表示每个元素被付给相应的初始值 vector<T> V5=(a,b,c,...)
等价于前者 关于初始化的几种例外情况
- 1.在使用拷贝初始化时,只能够提供一个初始值;
- 2.如果提供的是一个类里面的初始值,只能够使用拷贝初始化和
{}
形式的列表初始化; - 3.如果提供的是初始元素的列表,只能够在
{}
里面进行初始化; {}
和()
的区别:()
里面的值只有一个时,用于说明元素的数量,里面的值有两个时,用于指定元素的数量和初始值;//表示mystring里面包含十个元素,但是不建议这样使用; vectro<string> mystring(10); //包含两个元素时,用于指定元素的数量以及元素; vector<string> mystring(10,"YCM");
{}
里面的用于指定元素的初始值;- 特殊情况:
{}
:首先执行的是列表初始化,如果无法执行,比如vector<string> V7{10}
,就会执行string V7
个数的限定;- 这种情况编译器是允许的,但是不建议这样使用;
<vector>
的push_back()
操作push _back()
操作的含义就是将元素放在当前数组的尾部;通畅不建议在开始就指定<vector>
的大小,而是让其根据需要自己增长;- 使用下标操作可以访问已经存在的元素,但使不能够用于添加新的元素;尽可能使用范围
for
语句来避免循环超出范围;
操作 表示的含义 v.empty()
如果里面不包含任何元素返回真,否则翻回假 v.size()
返回里面元素的个数 v.push_back()
向当前的末尾添加一个元素 v[n]
返回v中第n个元素位置的引用 v1 = v2
进行元素的覆盖操作 v1 == v2
按照字典序判断是否相等 vector<>
对于下标索引的操作和string<>
类型是相同的;vector<>
,如果里面不包含任何的元素,那么是不能够使用下标索引来访问或者添加元素的,但是可以使用.push_back
方法;- 对于
vector
来说,如果有向里面添加元素的语句,就不应该使用for
循环,这里的for
循环表示的是for(auto h:vector)
,这样的形式,但是还是可以使用范围for
,通过改变保存的end
的值来进行添加元素的;
迭代器
- 所有的标准库容器都支持迭代器操作,但是并不都支持下标操作;
- 迭代器可以从一个元素移动到另一个元素,有效的迭代器指向某一个元素;
- 迭代器拥有
.begin()
和.end()
成员分别用于指向第一个元素和最后一个元素的的下一个位置; - 如果迭代器为空,那么返回的就是同一个迭代器,都是尾迭代器;
- 迭代器运算符
运算符 | 含义 |
---|---|
*iter | 用于返回迭代器iter 元素的引用 |
iter->men | 解引用,并得到成员men |
iter1 == iter2 | 用于判断两个迭代器是否相等 |
- 迭代器的操作比较适合于
for
循环来完成,例如for(auto iter=s.begin();iter != s.end();iter++)
; - 标准库提供了两种类型
iterator
和const_iterator
,前者用于表示可读写对象里面的元素,后者表示只能够访问,不能够操作; - 迭代器的类型是由
begin
和end
进行返回的,const vector<int>
,那么迭代器的返回类型就是const_iterator
否则就是前者,这是编译器的默认行为; C++11
提供了.cbegin()
函数和.cend()
来提供const_itertor
,只读功能;- 如果使用了迭代器,就不能给迭代器所属的容器添加元素(很重要);
- 迭代器支持常用的算数操作;
.end()-.begin()
得到就是元素的个数,得到的结果的类型是difference_type
使用迭代器实现的二分查找的例子
auto beg = text.begin(),end = text.end();
auto mid = (text.begin()+text.end())/2;
while(mid != end && *mid != sought){
if(sought < *mid){
end = mid;
}
else {
beg = mid +1;
}
mid = beg + (end - mid)/2;
}
数组
- 数组在申请大小之后是不能够改变的,不能够随意的向数组中添加超过数组容量的元素;
- 如果无法确定元素的个数,请使用数组;
- 对于复杂的数组声明,没有
()
按照从右往左的顺序,如果有()
,应该按照从内往外的顺序进行分析,例如int *(&arry)[10]
,首先来说&arry
表示这是一个引用,和下标运算符结合,就是一个包含10个元素的数组的引用,根据类型运算符,这是指针类型,这个声明的含义就是包含10个int
型指针的数组的引用; - 数组元素的访问可以使用
for
语句结合下标运算符来,数组下表应该定义为size_t
类型,而不是int
类型;书上推荐使用for(auto i:score)
,这样的方法来访问数组元素,避免出错; - 数组的下标越界检查,仍然是程序员不应该违反的准则;
- 对于数组里面元素的访问也是可以使用
for(auto &h:arryname){
do_something;
}
数组和指针
- 数组名表示的就是数组元素的首地址,对于数组中的其他元素可以使用
&
运算符得到地址; - 在很多时候需要使用数组名的地方,编译器都会替换成为数组的地址;
- 当时用
auto ia2(数组名)
,auto
的类型实际上是一个数组指针,默认是进行了转换的,所以ia2
是不能够进行整型赋值的; decltype
,进行变量的声明得到的将是一个和数组,并且和已知的数组由相同个数的元素;C++11
对于数组的下标操作引入了两个函数,begin()和end()
,使用数组名作为参数,用来获得首地址和尾地址;- 对于数组最后一个元素的下一个指针,是不能够进行自操作,也不能够进行解引用操作;
- 指针相减的类型是一种
ptrdiff_t
的标准库类型,包含在头文件<cstddef>
里面; - 两个指针进行比较的前提是必须指向同一个对象;
- 标准库限定了使用的下标运算符必须是无符号类型,内置的下标运算符是可以处理负值的,但是前提是处理后的结果仍然在数组表示的范围里面(包括尾元素的下一个位置);
string
的对象支持算数运算符的比较,但是C
里面的字符串数组是不支持的,通常需要使用C
语言提供的函数来进行比较;- 通常来说任何出现字符串字面值的地方都可以使用空字符结束的字符串数组来替代;
- 允许使用以空字符结束的字符数组来初始化
string
对象,或者为string
对象赋值; - 在
string
对象的加法中,允许使用以空字符结束的字符数组作为其中一个运算对象,但是不能两个都是字符数组;` - 如果需要通过
string
对象来初始化字符数组,就需要使用函数.c_str()
;
数组和vector
对象
- 不能够通过
vector
对象来初始化数组,但是可以通过数组来初始化vector
对象;vector<int> ivec(begin(int_arr),end(int_arr))
; 多维数组
- 多维数组其实就是数组的数组,前者用于表示数组的元素,后者用于表示数组每个元素里面有多少个元素;
- 如果需要改变多维数组里面的值,那么每层循环都需要使用
&
操作; - 如果仅仅是需要遍历多维数组,那么除了最内层循环之外,其余的需要使用
&
操作,是为了防止最内层之外的转换成指针,对指针进行遍历,没有价值; - 对于指针来说也可以是迭代器;
int arr[]={1,2,3,4,5,6,7,8,9}; int *parr = arr; int i=0; for(parr;i<sizeof(arr)/sizeof(arr[0]);++i){ do_something; parr++; }