《C++primer(第五版)》学习之路-第三章:字符串、向量和数组

【 声明:版权所有,转载请标明出处,请勿用于商业用途。  联系信箱:[email protected]


3.1 命名空间using声明


1.有了using声明就无须专门的前缀(形如命名空间::)也能使用所需的名字了。using声明具有如下的形式:
using namespace::name; 
一旦声明了上述语句,就可以直接访问命名空间中的名字。


3.2 标准库类型string

1.标准库类型string表示可变长的字符序列,使用string类型必须首先包含string头文件。作为标准库的一部分,string定义在命名空间std中。


2.

《C++primer(第五版)》学习之路-第三章:字符串、向量和数组_第1张图片


3.如果使用等号(=)初始化一个变量,实际上执行的是拷贝初始化(copy initialization),编译器把等号右侧的初始值拷贝到新创建的对象中去。与之相反,如果不使用等号,则执行的是直接初始化(direct initialization)。


4.

《C++primer(第五版)》学习之路-第三章:字符串、向量和数组_第2张图片


5.有时我们希望能在最终得到的字符串中保留输入时的空白符,这时应该用getline函数代替原来的>>运算符。getline函数的参数是一个输入流和一个string对象,函数从给定的输入流中读入内容,直到遇到换行符为止(注意换行符也被读进来了),然后把所读的内容存入到那个string对象中去(注意不存换行符)。getline只要一遇到换行符就结束读取操作并返回结果,哪怕输入的一开始就是换行符也是如此。如果输入真的一开始就是换行符,那么所得的结果是个空string。


6.相等性运算符(==和!=)分别检验两个string对象相等或不相等,string对象相等意味着它们的长度相同而且所包含的字符也全都相同。关系运算符<、<=、>、>=分别检验一个string对象是否小于、小于等于、大于、大于等于另外一个string对象。上述这些运算符都依照(大小写敏感的)字典顺序:
1.如果两个string对象的长度不同,而且较短string对象的每个字符都与较长string对象对应位置上的字符相同,就说较短string对象小于较长string对象。
2.如果两个string对象在某些对应的位置上不一致,则string对象比较的结果其实是string对象中第一对相异字符比较的结果。


7.

《C++primer(第五版)》学习之路-第三章:字符串、向量和数组_第3张图片


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

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


3.3 标准库类型vector


1.标准库类型vector表示对象的集合,其中所有对象的类型都相同。集合中的每个对象都有一个与之对应的索引,索引用于访问对象。因为vector"容纳着"其他对象,所以它也常被称作容器(container)。


2.

《C++primer(第五版)》学习之路-第三章:字符串、向量和数组_第4张图片


3.push_back负责把一个值当成vector对象的尾元素"压到(push)"vector对象的"尾端(back)"。例如:

vector v2;      // 空vector对象  
for (int i = 0; i != 100; ++i)  
    v2.push_back(i); // 依次把整数值放到v2尾端  
// 循环结束后v2有100个元素,值从0到99 

4.

《C++primer(第五版)》学习之路-第三章:字符串、向量和数组_第5张图片


3.4 迭代器介绍


1.和指针不一样的是,获取迭代器不是使用取地址符,有迭代器的类型同时拥有返回迭代器的成员。比如,这些类型都拥有名为begin和end的成员,其中begin成员负责返回指向第一个元素(或第一个字符)的迭代器。

// 由编译器决定b和e的类型;参见2.5.2节(第68页)  
// b表示v的第一个元素,e表示v尾元素的下一位置  
auto b = v.begin(), e = v.end(); //b 和e的类型相同 
end成员则负责返回指向容器(或string对象)"尾元素的下一位置(one past the end)"的迭代器,也就是说,该迭代器指示的是容器的一个本不存在的"尾后(off the end)"元素。这样的迭代器没什么实际含义,仅是个标记而已,表示我们已经处理完了容器中的所有元素。end成员返回的迭代器常被称作尾后迭代器(off-the-end iterator)或者简称为尾迭代器(end iterator)。特殊情况下如果容器为空,则begin和end返回的是同一个迭代器。
如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器。


2.

《C++primer(第五版)》学习之路-第三章:字符串、向量和数组_第6张图片


3.const_iterator和常量指针差不多,能读取但不能修改它所指的元素值。相反,iterator的对象可读可写。如果vector对象或string对象是一个常量,只能使用const_iterator;如果vector对象或string对象不是常量,那么既能使用iterator也能使用const_iterator。


4.begin和end返回的具体类型由对象是否是常量决定,如果对象是常量,begin和end返回const_iterator;如果对象不是常量,返回iterator。
cbegin和cend也分别返回指示容器第一个元素或最后元素下一位置的迭代器。有所不同的是,不论vector对象(或string对象)本身是否是常量,返回值都是const_iterator。


5.

《C++primer(第五版)》学习之路-第三章:字符串、向量和数组_第7张图片


3.5 数组


1.数组是一种复合类型(参见2.3节,第50页)。数组的声明形如a[d],其中a是数组的名字,d是数组的维度。维度说明了数组中元素的个数,因此必须大于0。数组中元素的个数也属于数组类型的一部分,编译的时候维度应该是已知的。也就是说,维度必须是一个常量表达式。


2.定义数组的时候必须指定数组的类型,不允许用auto关键字由初始值的列表推断类型。另外和vector一样,数组的元素应为对象,因此不存在引用的数组。


3.可以对数组的元素进行列表初始化,此时允许忽略数组的维度。如果在声明时没有指明维度,编译器会根据初始值的数量计算并推测出来;相反,如果指明了维度,那么初始值的总数量不应该超出指定的大小。如果维度比提供的初始值数量大,则用提供的初始值初始化靠前的元素,剩下的元素被初始化成默认值。


4.

《C++primer(第五版)》学习之路-第三章:字符串、向量和数组_第8张图片


5.c_str函数的返回值是一个C风格的字符串。也就是说,函数的返回结果是一个指针,该指针指向一个以空字符结束的字符数组,而这个数组所存的数据恰好与那个string对象的一样。结果指针的类型是const char*,从而确保我们不会改变字符数组的内容。


6.使用指针和数组很容易出错。一部分原因是概念上的问题:指针常用于底层操作,因此容易引发一些与烦琐细节有关的错误。其他问题则源于语法错误,特别是声明指针时的语法错误。
现代的C++程序应当尽量使用vector和迭代器,避免使用内置数组和指针;应该尽量使用string,避免使用C风格的基于数组的字符串。


3.6 多维数组


1.严格来说,C++语言中没有多维数组,通常所说的多维数组其实是数组的数组。


2.要使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。



PS:部分练习答案


练习3.1

//1.4.1练习1.9 
#include 

using std::cin;
using std::cout;
using std::endl;

int main()
{
	int a = 50,sum=0;
	while(a<=100)
	{
		sum+=a;
		a++;
	}
	cout<

using std::cin;
using std::cout;
using std::endl;

int main()
{
	int a = 10;
	while(a>=0)
	{
		cout<

using std::cin;
using std::cout;
using std::endl;

int main()
{
	int a,b,_min,_max;
	cout<<"请输入两个整数:"<>a>>b;
	_min = a>b?b:a;
	_max = a>b?a:b; 
	cout<<"在这个区间内的整数有:"<

//2.6.2练习2.41 
#include 
#include 
#include "Sales_data.h"

using std::cin;
using std::cout;
using std::endl;
using std::cerr;

int main()
{
	Sales_data data1, data2;
	double price = 0;
	cin >> data1.bookNo >> data1.units_sold >> price;
	data1.revenue = data1.units_sold * price;
	cin >> data2.bookNo >> data2.units_sold >> price;
	data2.revenue = data2.units_sold * price;
	if (data1.bookNo == data2.bookNo)
	{
		unsigned totalCnt = data1.units_sold + data2.units_sold;
		double totalRevenue = data1.revenue + data2.revenue;
		cout << data1.bookNo << " " << totalCnt << " " << totalRevenue << " ";
		if (totalCnt != 0)
			cout << totalRevenue / totalCnt << endl;
		else
			cout << "(no sales)" << endl;
		return 0;
	}
	else
	{
		cerr << "Data must refer to the same ISBN" << endl;
		return -1;
	}
}

练习3.2

//读入整行 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string str;
	while(getline(cin,str)) 
	cout<
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string str;
	while(cin>>str) 
	cout<

练习3.4

#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string s1,s2;
	while(cin>>s1>>s2)
	{
		if(s1==s2)
		cout<<"两个字符串相等"<s2?s1:s2)<

#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string s1,s2;
	while(cin>>s1>>s2)
	{
		if(s1.size()==s2.size())
		cout<<"两个字符串等长"<s2.size()?s1:s2)<

练习3.5

#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string s1,str="";
	while(cin>>s1)
	str+=s1;
	cout<

#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string s1,str="";
	while(cin>>s1)
	{
		if(str!="")
			str+=" ";
		str+=s1;
	}
	cout<

练习3.6

#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string str="This is a c++ program.";
	for(auto &c:str)
	c = 'X';
	cout<

练习3.8

#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string str="This is a c++ program.";
	decltype(str.size()) i = 0;
	while(i

练习3.10

#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main()
{
	string str="Hello,world!!!";
	cout<

练习3.11

如果我们不改变c的值,则合法,否则不合法。


练习3.14

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	int a;
	vector num;
	while(cin>>a)
		num.push_back(a);
	for(auto c:num)
		cout<

练习3.15

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	string a;
	vector num;
	while(cin>>a)
		num.push_back(a);
	for(auto c:num)
		cout<

练习3.16

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	vector v1;
	cout<<"v1 size:"< v2(10);
	cout<<"v2 size:"< v3(10,42);
	cout<<"v3 size:"< v4{10};
	cout<<"v4 size:"< v5{10,42};
	cout<<"v5 size:"< v6{10};
	cout<<"v6 size:"< v7{10,"hi"};
	cout<<"v7 size:"<

练习3.17

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	vector svec;
	string str;
	while(cin>>str)
		svec.push_back(str);
	for(auto &c:svec)
	{
		for(auto &x:c)
		{
			x=toupper(x);
		}
		cout<

练习3.18

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	vector ivec {0};
	ivec[0] = 42;
	return 0;
}

练习3.19

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	vector ivec1(10, 42);
	vector ivec2 {42, 42, 42, 42, 42, 42, 42, 42, 42, 42};
	vector ivec3;
	for (int i = 0; i != 10; ++i)
		ivec3.push_back(42);
}

练习3.20

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	int a;
	vector num;
	while(cin>>a) num.push_back(a);
	
	if(num.size()==0)
	{
		cout<<"请输入数据"<

练习3.21

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

void check(const vector& vec)
{
	if (vec.empty())
		cout << "size: 0; no values." << endl;
	else
	{
		cout << "size: " << vec.size() << "; values:";
		for (auto it = vec.begin(); it != vec.end(); ++it) cout << *it << ",";
		cout << "\b." << endl;
	}
}

void check(const vector& vec)
{
	if (vec.empty())
		cout << "size: 0; no values." << endl;
	else
	{
		cout << "size: " << vec.size() << "; values:";
		for (auto it = vec.begin(); it != vec.end(); ++it)
			if (it->empty())
				cout << "(null)"
				     << ",";
			else
				cout << *it << ",";
		cout << "\b." << endl;
	}
}

int main()
{
	vector v1;
	vector v2(10);
	vector v3(10, 42);
	vector v4 {10};
	vector v5 {10, 42};
	vector v6 {10};
	vector v7 {10, "hi"};

	check(v1);
	check(v2);
	check(v3);
	check(v4);
	check(v5);
	check(v6);
	check(v7);

	return 0;
}

练习3.22

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	vector text;
	string line;
	while(getline(cin,line)) text.push_back(line);
	
	for(auto it = text.begin();it!=text.end()&&!it->empty();it++)
	{
		for(auto &x:*it)
		x = toupper(x);
		cout<<*it<

练习3.23

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	vector num;
	for(int i = 1; i<=10; i++)
		num.push_back(i);
	for(auto it = num.begin(); it!=num.end(); it++)
		*it*=2;
	for(auto c:num)
		cout<


练习3.24

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	int i;
	vector ivec;
	while (cin >> i) ivec.push_back(i);

	if (ivec.empty())
	{
		cout << "请输入数据" << endl;
		return 0;
	}
	else if (ivec.size() == 1)
	{
		cout << *ivec.begin() << "没有相邻元素";
	}

	for (auto it = ivec.begin(); it + 1 != ivec.end(); ++it)
		cout << *it + *(it + 1) << " ";
	cout << endl;

	for (auto beg = ivec.begin(), end = ivec.end() - 1; beg <= end; ++beg, --end)
		cout << *beg + *end << " ";
	cout << endl;

	return 0;
}

练习3.25

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	vector scores(11,0);
	unsigned grade;
	while(cin>>grade)
	{
		if(grade<=100)
		{
			auto it = scores.begin();
			(*(it+grade/10))++;
		}
	}
	for(auto c:scores)
		cout<

练习3.26

因为vector并没有定义两个迭代器的+操作,所以beg+end是非法的,我们只能进行-操作


练习3.31

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	int num[10];
	for(int i = 0; i<10; i++) num[i]=i;
	for(auto c:num)
		cout<

练习3.32

#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main()
{
	int num1[10],num2[10];
	for(int i = 0; i<10; i++) num1[i]=i;
	for(int i = 0; i<10; i++) num2[i] = num1[i];
	for(auto c:num2)
		cout< ivec1(10);
	for(auto it=ivec1.begin();it!=ivec1.end();it++)
	*it = it-ivec1.begin();
	vector ivec2(ivec1);
	for(auto c:ivec2)
	cout<

练习3.35

#include 
#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::begin;
using std::end;

int main()
{
	int num[10]={1,2,3,4,5,6,7,8,9,10};
	auto b = begin(num);
	auto e = end(num);
	for(auto i = b;i!=e;i++)
	*i = 0;
	for(auto c:num)
	cout<

练习3.36

#include 
#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::begin;
using std::end;

bool compare(auto b1,auto e1,auto b2,auto e2)
{
	if(e1-b1!=e2-b2)
		return false;
	while(b1!=e1&&b2!=e2)
	{
		if(*b1!=*b2)
			return false;
		b1++;
		b2++;
	}
	return true;
}

int main()
{
	int num1[3]= {0,1,2};
	int num2[3]= {0,2,3};
	auto b1 = begin(num1);
	auto b2 = begin(num2);
	auto e1 = end(num1);
	auto e2 = end(num2);
	if(compare(b1,e1,b2,e2))
		cout<<"两个数组相等"< vec1 {1,2,3};
	vector vec2 {1,2,3};
	if(vec1==vec2)
		cout<<"两个vector相等"<

练习3.39

#include 
#include 
#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::begin;
using std::end;

int main()
{
	string str1,str2;
	char *cs1,*cs2;
	cout<<"请输入两个c++风格的字符串str1,str2:";
	cin>>str1>>str2;
	if(str1==str2)
	cout<<"str1==str2"<str2)
	cout<<"str1>str2"<>cs1>>cs2;
	if(strcmp(cs1,cs2)==0)
	cout<<"cs1==cs2"<0)
	cout<<"cs1>cs2"<

练习3.40

#include 
#include 
#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::begin;
using std::end;

int main()
{
	char s1[4]="123";
	char s2[4]="456";
	char s3[7];
	strcpy(s3,s1);
	strcat(s3,s2);
	cout<

练习3.41

#include 
#include 
#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::begin;
using std::end;

int main()
{
	int num[]= {0,1,2,3,4,5};
	vector ivec(begin(num),end(num));
	for(auto c:ivec)
		cout<

练习3.42

#include 
#include 
#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::begin;
using std::end;

int main()
{
	vector ivec {0,1,2,3,4,5};
	int num[6];
	for(auto it = begin(num); it!=end(num); it++)
		*it = ivec[it-begin(num)];
	for(auto c:num)
		cout<

练习3.43

#include 
#include 
#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::begin;
using std::end;

int main()
{
	int ia[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

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

	for (size_t i = 0; i != 3; ++i)
		for (size_t j = 0; j != 4; ++j) cout << ia[i][j] << " ";
	cout << endl;

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

	return 0;
}

练习3.44

#include 
#include 
#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::begin;
using std::end;

int main()
{
	int ia[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

    using int_array = int[4];
    for (int_array& p : ia)
        for (int q : p) cout << q << " ";
    cout << endl;

    for (size_t i = 0; i != 3; ++i)
        for (size_t j = 0; j != 4; ++j) cout << ia[i][j] << " ";
    cout << endl;

    for (int_array* p = ia; p != ia + 3; ++p)
        for (int* q = *p; q != *p + 4; ++q) cout << *q << " ";
    cout << endl;

    return 0;
}

练习3.45

#include 
#include 
#include 
#include 
#include 

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::begin;
using std::end;

int main()
{
	int ia[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

    for (auto& p : ia)
        for (int q : p) cout << q << " ";
    cout << endl;

    for (size_t i = 0; i != 3; ++i)
        for (size_t j = 0; j != 4; ++j) cout << ia[i][j] << " ";
    cout << endl;

    for (auto p = ia; p != ia + 3; ++p)
        for (int* q = *p; q != *p + 4; ++q) cout << *q << " ";
    cout << endl;

    return 0;
}


你可能感兴趣的:(《C++primer(第五版)》学习之路-第三章:字符串、向量和数组)