Primer学习笔记第三单元

三、字符串、向量和数组

3.1命名空间的using声明

1.std::cin表示从标准库中读取内容,可以通过using声明,using std::cin;

2.每个名字都需要独立的using声明;

3.头文件一般不适用using声明,以免使用的文件都包含一些名字;

3.2标准库类型string

可变长的字符序列

3.2.1定义和初始化

1.string s4(n,'c');  //定义s为n个字符c组成的串。

直接初始化()   和   拷贝初始化=,多个对象时需要直接初始化;

2.IO操作指令,从第一个真正字符开始,到下一处空白结束(无空白符号);多IO操作可以连着一起;

3.getline ,输入流读取,直到换行符

getline(cin , stringname)

对于string类的输入函数,它会自动忽略开头的空白(空格、制表符、换行等等),从第一个真正的字符开始直到下一个空白。

对于getline()函数,它会保存字符串中的空白符,它读入数据,直到遇到换行符位置。

4.只输出非空行

    string line;
    while (getline(cin, line))
        if (!line.empty())
         cout << line << endl;

5.string对象的比较

1.如果长度不同,每个字符都一样,则短的小;

2.如果对象的某些对应位置不一致,则比较第一对相异字符比较的结果;

6.string对象可以与(字符字面值或者字符串字面值)相加;

字符串字面值与string是不同的类型!!0

以下部分csdn没自动保存,

读写string对象

在执行读取操作时,string 对象会自动忽略开头的空白(空格符、换行符、制表符等)并从第一个真正的字符开始读取,直到遇见下一处空白为止。

使用getline读取一整行

当希望能在输出的字符串中 保留输入的空白字符 时,可以使用 getline 函数。

string 的empty和size操作

empty 函数根据 string 对象是否为空返问一个对应的布尔值;

size 函数返回 string 对象的长度(即 string 对象中字符的个数)。

string::size_type类型

size函数返回值其实是 string::size_type 类型,这是一种无符号类型,而且能足够存放下任何string对象的大小。因此,所有用于存放string类的size函数返回值的变量,都应该是string::size_type类型。

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

如果想对string对象中的每个字符都做点什么操作,目前最好的办法是使用C++11提供的范围 for(range for)语句,可以遍历给定序列中的每个元素并对序列中的每个值执行某种操作。语法形式:

for (declaration : expression)
    statement
其中,expression 部分是一个对象,用于表示一个序列。declaration 部分负责定义一个变量,该变量被用于访问序列中的基础元素。每次迭代,declaration 部分的变量都会被初始化为 expression 部分的下一个元素值。

3.3 标准库类型vector


       标准库类型 vector 表示对象的集合,因为vector 容纳着其他对象,所以也叫做 容器(container),定义在头文件 vector 中。vector 中所有对象的类型都相同,集合中的每个对象都有一个与之对应的索引, 并用于访问该对象。

C++语言既有类模板(class template),也有函数模板。

vector 是一个 类模板,模板本身不是类或函数,相反可以将模板看作为编译器生成类或函数编写的一份说明。编译器根据模板创建类或函数的过程称为 实例化(instantiation),当使用模板时,需要指出编译器应把类或函数实例化成何种类型。

对于类模板,需要通过提供一些额外信息来指定模板到底实例化成什么样的类,需要提供哪些信息由模板决定。提供信息的方式:在模板名字后面跟一对尖括号,在括号内放上信息。

3.3.2 向vector对象中添加元素

      先创建一个空vector,然后在运行时再利用vector的成员函数push_back向其中添加元素。push_back负责把一个值当成vector对象的尾元素 “压到(push)” vector对象的 “尾端(back)” 。

警告:vector对象(以及string对象)的下标运算符可用于访问已存在的元素,而不能用于添加元素。

3.4迭代器的选择

所有标准库容器都可以使用迭代器,但其中少数可以支持下标运算符。

实现对对象的间接访问,不是通过取地址,拥有返回迭代器的成员。

1.不清楚迭代器准确的类型是什么,通过auto定义。

2.可以通过解引用获取指向的元素。

例:实现将单词改为大写

for (auto it = s.begin(); it != s.end() && !isspace(*it); ++it)
*it = toupper(*it);

3.实际上迭代器的类型有iterator和const_iterator,对象读取而无需写操作,最好采用const_iterator,C++11引入cend和cbegin,返回值都是const_iterator。

解引用和成员访问操作结合

(*it).empty和it->empty作用一致

上上上句可以改为下句:其中对s的元素只是读取没有操作,则用了cbegin和cend

for (auto it = s.cbegin(); it != s.cend() && !s.empty(); ++it)

3.4.2迭代器运算

与整数运算,返回值是移动后的迭代器;迭代器差值是距离;比较符是比较指向前后;

没有定义两个迭代器之间的+运算符;

迭代器用于二分搜索

auto beg = text.begin(), end = text.end();
	auto mid = beg + (end - beg) / 2;
	for (mid != end && *mid != sought)
	{
		if (sought < *mid)
			end = mid;
		else
			beg = mid+1;
		mid = beg + (end - beg) / 2;//新的中间点
	}

3.5数组

#include<cstddef>

1.存放类型相同的对象的容器,通过位置访问;与vector不同的是数组的大小确定,维度必须是常量表达式

unsigned cnt=42;string bad [cnt];//错误,其中cnt不是常量表达式,应该使用 constexpr unsigned 命名

2.不允许用auto根据初始值列表指定类型,不存在引用的数组;

3.字符数组的字面值初始化,注意结尾处有一个空字符

char a[ ]={"c",'+','+','\0'};

char a[ ]="C++";//自动添加表示字符串结束的空字符,注意字符串大小是4

4.允许定义

指针数组:int *ptrs[10];

数组的指针 : int (*Parray) [10]=&arr;//  数组而言,由内向外阅读比较好

数组的引用:int (&arrRef) [10] =arr;

 例:int  *(&arry) [10] =ptrs; //arry是一个数组的引用,该数组有10个指针。

3.5.2访问数组元素

1.数组下标为size_t类型

2.可以使用范围for遍历数组的所有元素:

unsigned scores [11] ={};

for(auto i : scores )

cout<<i<<" "<<endl;

练习3.32

#include<iostream>
#include <string>
#include<cstddef>
#include<vector>
using namespace std;
int main()
{
	unsigned ai[10];
	for (size_t i = 0; i != 10; i++)
		ai[i] = i;
	unsigned ai2[10];
	for (size_t j = 0; j != 10; j++)
		ai2[j] = ai[j];
	vector<unsigned> iv(10);
	for (auto iter = iv.begin(); iter != iv.end(); ++iter)
		*iter = iter - iv.begin();
	vector<unsigned> iv2{ iv };
	for (auto k : iv2)
		cout << k << " ";
	cout<< endl;//循环外输入endl,避免每次都endl导致分行
	return 0;
}

3.5.3指针和数组.

1.auto和decltype返回值推断的不同,指针和数组(p118)

2.指向数组的指针也是迭代器,有尾指针,指向尾元素的下一个位置的指针

C++11引入begin和end函数,在iterator头文件中:

int *beg =begin (ia);

int *last= end(ia);

3.迭代器相减类型为ptrdiff_t:auto n =end(arr) - begin(arr);

练习3.36,比较两个数组是否相等,比较两个vector是否相等

#include<iostream>
#include<cstddef>
#include<iterator>
using namespace std;

int main()
{
	unsigned ia[10] = { 1,2,3 }, ia2[10] = {1,2,3};
	bool compare=true;
	if (sizeof(ia) != sizeof(ia2))
		compare = false;
	else
	{
		for (auto i = 0; i != sizeof(ia); i++)
		{
			if (ia[i] != ia2[i])
				compare = false;
		}
	}
	if (compare = false)
		cout << "No" << endl;
	else cout << "Yes" << endl;

	return 0;
}

vector可以直接比较

#include<vector>
#include<iterator>
using namespace std;

int main()
{
	vector<unsigned> vec1 = { 0,1,2 }, vec2 = { 0,1,2 };
	if (vec1 == vec2)
		cout << "Yes" << endl;
	else cout << "No" << endl;
	return 0;
}

3.5.4使用标准库string要比C风格字符串更安全

3.5.5与旧代码的接口

允许用数组初始化vector:

int int_arr[ ]={ 0,1,2,3,4,5};

vector <int>  ivec(begin(int_arr),end(int_arr));

用vector拷贝给数组

for (int* i = begin(arr); i != end(arr); i++)
   *i = ivec[i - begin(arr)];

3.6多维数组

1.一个维度表示数组本身大小(称为行),一个维度表示其元素大小(称为列);

此处与C一致

2.用范围for语句遍历赋值

size_t cnt=0;	
for (auto& row : ia)
		for (auto& col : row)
			col = cnt++;

上述中,必须控制变量row和col为引用,因为要改变元素的值;若为auto row则默认为指向数组首元素的指针,下一个步不能操作。

范围for处理多维数组,除了最内层,其他所有循环的控制变量都应该是引用类型!

3.多维数组的指针,指向第一个内层数组的指针;

C++11中通过auto和decltype避免数组前加上指针类型-----或者通过标准库中begin和end也可以

4.可以用类型别名实现,多维指针

    using int_arry = int[4]; 或者 typedef int int_arry[4];//将类型“4个整数组成的数组”,命名为int_array,用类型名定义外循环的控制变量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值