字符串、向量和数组

一。使用声明(使用namespace :: name)

1.每个名字都要独立的使用声明

     使用std :: cin;

     使用std :: cout; 使用std :: endl;

     可以一行只放一个声明语句,也可以多个,但必须以分号结尾。

2.头文件不应包含使用声明

      位于头文件的代码一般来说不应该使用使用声明,避免在包含头文件时产生不必要的冲突。

二。标准库类型字符串(可变长的字符序列)

       使用前必须包含字符串头文件,字符串定义在性病中。

    1.如何定义和初始化字符串

        字符串s1; //默认初始化,S1是一个空串

        字符串s2 = s1; // S2是S1的副本

        字符串s3 =“hiya”; // s3是该字符串字面值的副本

        字符串s4(10,'c'); // s4的内容是cccccccccc

        如果使用(=)初始化一个变量,执行实际上的的英文拷贝产品初始化,与之相反,如果不使用(=)执行则的的英文直接初始化

   2.string对象上的操作

        string s5 =“hiya”; //拷贝初始化string s6(“hiya”); //直接初始化

        cout << s将s写到输出流os当中,返回os

cin >> s从中读取字符串赋值给s,字符串以空白分隔,结果为

getline(is,s)从中读取一行赋给s,返回是

s.empty()s为空返回true,否则返回false

s.size()对于size函数来说,返回string :: size_type类型的值。(可以用auto或者decltype推断变量的类型)返回s中字符的个数

s [n]返回中第n个字符的引用,位置n从0计起

s1 + s2返回s1和s2连接后的结果

s1 = s2用s2的副本代替s1中原来的字符

s1 == s2如果sl和s2中所含的字符完全一样,则它们相等; 字符串对象的相

s1!= ms2等性判断对字母的大小写敏感

<,<=,>,> =利用字符在字典中的顺序进行比较,且对字母的大小写敏感

字面值和字符串对象相加

  String s1 =“hello”; s2 =“world”;

  String s3 = s1 +“,”+ s2 +“\ n”;

   当把字符串对象和字符字面值及字符串字面值混在一条语句中使用时,确保必须每个加法运算符的两侧至少有一个字符串的英文:

  String s6=s1+”,”+”world”;  //正确,因为string  s6=(s1+”,”)+”world”;

处理string对象中的字符

表3.3: cctype头文件中的函数

isalnum(c) 当c是字母或数字时为真

isalpha(c) 当c是字母时为真

iscntrl(c) 当c是控制字符时为真

isdigit(c) 当c是数字时为真

isgraph(c) 当c不是空格但可打印时为真

islower(c) 当c是小写字母时为真

isprint(c) 当c是可打印字符时为真(即c是空格或c具有可视形式)

ispunct(c) 当c是标点符号时为真(即c不是控制字符、数字、字母、可打印空白中的一种)

isspace(c) 当c是空白时为真(即c是空格、横向制表符、纵向制表符、回车符、换行符、进纸符中的一种)

isupper(c) 当c是大写字母时为真

isxdigit(C) 当c是十六进制数字时为真

tolower(c) 如果C是大写字母,输出对应的小写字母:否则原样输出。

toupper(c)如果C是小写字母,输出对应的大写字母,否则原样输出。

处理每个字符?使用基于范围的for语句

 for(declaration : expression)

        statement

其中expression部分是一个对象,用于表示一个序列。Declaration部分负责定义一个变量,该变量将被用于访问序列中的基础元素。

  string str(“some string”);

   for(auto c:str)

     cout<<c<<endl;

三.标准库类型vector(对象的集合(容器))

C++语言既有类模板,也有函数模板,其中vector是一个类模板。模板本身不是类或函数,相反可以将模板看做编译器生成类或函数的一份说明。编译器根据模板创建类或函数的过程称为实例化,当时用模板时,需要指出编译器应把类或函数实例化成何种类型。

vector<int>ivec;//ivec保存int类型的对象

vector<vector<string>>file;//该向量的元素是vector对象;

1.定义和初始化vector对象

vector<T> v1  v1是一个空vector,它潜在的元素是T类型的,执行默认初始化vector<T> v2 (v1)  v2中包含有v1所有元素的副本

vector<T> v2 = v1  等价于v2(v1),v2中包含有v1所有元素的副本vector<T> v3 (n, val)  v3包含了n个重复的元素,每个元素的值都是val

vector<T> v4 (n)  v4包含了n个重复地执行了值初始化的对象

vector<T> v5{a,b,c. ..}  v5包含了初始值个数的元素,每个元素被赋予相应的初始值vector<T> v5={a,b,c..}  等价于v5{a,b,c...}

2.向vector中添加元素

利用vector的成员函数push_back()向其中添加元素。push_back负责把一个值当成vector对象的尾元素压到vector对象的尾端。

vector<int> v2;

for(int i=0;i!=100;i++)

   v2.push_back(i);

可以对确认已存在的元素执行下标操作,不能用下标形式添加元素!!!

3.其他vector操作

v.empty() 如果v不含有任何元素,返回真:否则返回假

v.size() 返回v中元素的个数

V.push_ back(t) 向v的尾端添加一个值为t的元素

V[n] 返回v中第n个位置上元素的引用

v1=v2 用v2中元素的拷贝替换v1中的元素

vI = {a,b,C... }用列表中元素的拷贝替换v1中的元素

v1 == v2 v1 != v2 v1和v2相等当且仅当它们的元素数量相同且对应位置的元素值都相作

<,<=, >, >= 顾名思义,以字典顺序进行比较

四.迭代器介绍

1.    使用迭代器

获取迭代器不是使用取地址符,有迭代器的类型同时返回迭代器的成员。比如,这些类型都拥有名为begin和end的成员,其中begin()负责返回指向第一个元素的迭代器,end()负责返回指向最后一个元素的后一位(尾后)的迭代器,常被称作尾后迭代器

2.    迭代器运算符

*iter

返回迭代器iter所指元素的引用

iter->mem

解引用itet并获取该元素的名为mem的成员,等价于(*iter).. mem

++iter

令iter指示容器中的下一个元素

--iter

令iter指示容器中的上一个元素

iterl== iter2  iter1!=iter2

判断两个迭代器是否相等(不相等),如果两个迭代器指示的是同一个元素或者它们是同一个容器的尾后迭代器,则相等;反之,不相等

3.    某些对vector对象的操作会使迭代器失效

vector对象虽然可以动态的增长,但是也有一些副作用。已知的一个限制是不能在范围for循环中向vector对象添加元素。另外一个是任何一种可能改变vector对象容量的操作,比如push_back,都会使该vector对象的迭代器失效。

五.数组

   多维数组的下标引用

  可以使用下标运算符来访问多维数组的元素,此时数组的每个维度对应一个下标运算符。如果表达式含有的下标运算符数量和数组的维度一样多,该表达式的结果将是给定类型的元素。反之,如果表达式含有的下标运算符数量比数组的维度小,则表达式的结果将是给定索引处的一个内层数组:

  //用arr的首元素为ia最后一行的最后一个元素赋值ia[2][3] = arr[0][0][0];

  int (&row)[4] = ia[1]; //把row绑定到ia的第二个4元素数组上

  在第一个例子中,对于用到的两个数组来说,表达式提供的下标运算符数量都和它们各自的维度相同。在等号左侧,ia[2]得到数组ia的最后一行,此时返回的是表示ia最后一行的那个一维数组而非任何实际元素;对这个一维数组再取下标,得到编号为[3]的元素,也就是这一行的最后一个元素。

  类似的,等号右侧的运算对象包含3个维度。首先通过索引0得到最外层的数组,它是一个大小为20的(多维)数组;接着获取这20个元素数组的第一个元素,得到一个大小为30的一维数组;最后再取出其中的第一个元素。

  在第二个例子中,把row定义成一个含有4个整数的数组的引用,然后将其绑定到ia的第2行。

使用范围for语句处理多维数组

size_tcnt = 0; //对于外层教组的每一个无素

for (auto&row : ia)   //对于内层教组的每一个无素

for (auto&col : row)  //将下一个值赋给该元素

co1 =cnt;  

++cnt;   //将cnt加1

这个循环赋给IA元素的值和之前那个循环是完全相同的,区别之处是通过使用范围为语句把管理数组索引的任务交给了系统来完成。因为要改变元素的值,所以得把控制变量行和山口声明成引用类型。第一个用于循环遍历IA的所有元素,这些元素是大小为4的数组,因此行的类型就应该是含有4个整数的数组的引用。第二个用于循环遍历那些4元素数组中的某一个,因此COL的类型是整数的引用。每次迭代把CNT的值赋给IA的当前元素,然后将CNT加1,在上面的例子中,因为要改变数组元素的值,所以我们选用引用类型作为循环控制变量,但其实还有一个深层次的原因促使我们这么做举一个例子,考虑如下的循环:

for(const auto&row:ia)//对于外层教组的每一个元素

for(autocol:row)//对于内层教组的每个元素

cout << col << endl;

这个循环中并没有任何写操作,可是我们还是将外层循环的控制交量量声明成了引用类型,这是为了避免数组被自动转成指针假设不用引用类型,则循环如下述形式:

for(autorow:ia)

for(autocol:row)

程序将无法通过编译,这是因为,像之前一样第一个循环遍历元素实际上是大小为4的数组。因为行不是引用类型,所以编译器初始化排时会自动将这些数组形式的元素转换成指向该数组内首元素的指针。这样得到的列的类型就是INT *,显然内层的循环就不合法了,编译器将试图在一个INT *内遍历,这显然和程序的初衷相去甚远。

猜你喜欢

转载自blog.csdn.net/yshshhgxq/article/details/80501914
今日推荐