1.标准库类型string:
- 初始化string对象:直接初始化与拷贝初始化
string s1 = "hiya"; //拷贝初始化(使用 = 初始化变量)
string s2("hiya"); //直接初始化
string s3(10,'c'); //直接初始化,s3的内容是cccccccccc
- string对象上的部分操作:(1)getline (is, s) 从is中读取一行赋給s,返回is
- (2)s.empty() s为空返回true, 否则返回false
- (3)s.size() 返回s中字符的个数
- (4)s[n] 返回s中第n个字符的引用,位置n从0计起
- string::size_type类型:它是一个无符号类型的值而且能够存放任何string对象的大小
//允许编译器通过auto或者decltype来推断变量的类型
auto len = line.size(); //len的类型是string::size_type
//如果一条表达式中已经有了size()函数就不要再使用int了,这样可以避免混用int和unsigned可能带来的问题
2.多个string对象的操作:
//比较string对象
/************************************************************
1.如果两个string对象的长度不同,而且较短string对象的每个字符都与较长string对象对应位置上的字符相同,就说较短string对象小于较长string对象
2.如果两个string对象在某些对应的位置上不一致,则string对象比较的结果其实是string对象中第一对相异字符比较的结果。
************************************************************/
string str = "Hello";
string phrase = "Hello World"; //判断对象str小于对象phrase
string slang = "Hiya"; //判断对象slang既大于str也大于phrase
//string对象相加、字面值和string对象相加
string s1 = "Hello, ", s2 = "world\n";
string s3 = s1 + s2; //s3的内容是Hello, world\n
string s1 = "hello", s2 = "world";
string s3 = s1 + "," + s2 +'\n';
3.处理string对象中的字符:
- 定义在cctype头文件中的一组标准库函数处理单个字符
- 使用范围for语句处理每个字符:
//使用范围for语句不改变字符串中的字符
string str("some string");
for (auto c : str) //使用auto得到c的类型,意思是对于str中的每个字符
cout << c << endl; //输出每个字符
//使用范围for语句改变字符串中的字符
string s("Hello world!!!");
for (auto &c : s) //对于s中的每个字符(c是引用)
c = toupper(c); //赋值语句改变s中字符的值,将字符全部改为小写
cout << s << endl; //输出字符串s
4.标准库类型vector(容器):
- 定义和初始化vector对象:
vector<T> vec; //T可以是内置类型、类类型或vector类型
//列表初始化vector对象
vector<string> v1{"a", "an", "the"}; //列表初始化
//值初始化
vector<int> ivec(10, 1); //10个元素,每个都初始化未1
//区分以下两种初始化方式
vector<int> v2(10, 1);
vector<int> v3{10, 1}; //v3有两个元素,分别为10和1
/****************************************************
1.如果用的是圆括号,可以说提供的值是用来构造vector对象的
2.如果用的是花括号,可以表述成我们想列表初始化该vector对象
****************************************************/
- vector支持的操作(部分):(1)v.empty() 如果v不含有任何元素,返回真;否则返回假
- (2)v.size() 返回v中元素的个数
- (3)v.push_back(t) 向v的尾端添加一个值为t的元素
- (4)v[n] 返回v中第n个位置的引用
- vector对象(及string对象)的下标运算符可用于访问已存在的元素,而不能用于添加元素
5.迭代器(iterator):
- 使用迭代器可以访问某个元素
- 迭代器也能从一个元素移动到另外一个元素
- 标准容器迭代器的运算符:
*iter //返回迭代器iter所指元素的引用
iter->mem //解引用iter并获取该元素的名为mem的成员,等价于(*iter).mem
++iter //令iter指示容器中的下一个元素
--iter //令iter指示容器中的上一个元素
iter == iter1
iter != iter1 //判断两个迭代器是否相等
//begin和end运算符
vector<int> v;
auto beg = v.begin();
auto last = v.end();
- 迭代器类型:iterator和const_iterator两种类型,后者只能读不能写
- 两个迭代器的距离:右侧的迭代器向前移动多少位置能追上左侧的迭代器,类型是名为difference_type的带符号型整数
6.数组(部分重点特性):
- 不允许拷贝和赋值:
int a[] = {0, 1, 2}; //含有3个整数的数组
int a2[] = a; //错误:不允许使用一个数组初始化另一个数组
a2 = a; //错误:不能把一个数组直接赋值给另一个数组
- 要想理解数组声明的含义,最好的方法是从数组的名字开始按照由内到外的顺序阅读
- 在使用数组下标时,通常将其定义为size_t类型,它是一种机器相关的无符号类型,在cstddef文件中定义
- 指针和数组:
//对数组的元素使用取地址符就能得到指向该元素的指针
string numbers[] = {"one", "two", "three"};
string *p = &numbers[0]; //p指向numbers的第一个元素
//标准库函数begin()和end(),定义在iterator头文件中
int ia[] = {0, 1, 2, 3, 4, 5};
int *beg = begin(ia); //指向ia首元素的指针
int *last = end(ia); //指向ia尾元素的指针
- 使用数组初始化vector对象:只需指明要拷贝区域的首元素地址和尾后地址
int int_arr[] = {0, 1, 2, 3, 4, 5};
vector<int> vec(begin(int_arr), end(int_arr));
7.多维数组(数组的数组):
- 多维数组的初始化:
//使用花括号初始化多维数组
int ia[3][4] = {
{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11}
};
//显示的初始化每行的首元素
int ia[3][4] = {{0}, {4}, {8}};
//显示的初始化第一行,其他的元素默认初始化
int ia[3][4] = {0, 3, 6, 9};
- 使用for语句处理多维数组:
//使用普通for语句处理多维数组
constexpr size_t rowcnt = 3, colcnt = 4;
int ia[rowcnt, colcnt]; //12个未初始化的元素
//对于每一行
for (size_t i = 0;i != rowcnt;++i)
{
//对于行内每一列
for (size_t j = 0;j != colcnt;++j)
{
//将元素的位置索引作为它的值
ia[i][j] = i * colcnt + j;
}
}
//使用范围for语句处理多维数组
size_t cnt = 0;
for (auto &row : ia) //对于外层数组的每个元素
{
for (auto &col : row) //对于内层数组的每个元素
{
col = cnt; //将下个值赋給该元素
++cnt; //将cnt加1
}
}
//使用指针处理多维数组
int ia[3][4];
for (auto p = ia;p != *p + 4; ++p) //p指向含有4个整数的数组
{
for (auto q = *p;q != *p + 4; ++q) //q指向4个整数数组的首元素,q指向一个整数
{
cout << *q << " ";
}
cout << endl;
}
//使用begin()和end()函数处理
for (auto p = begin(ia);p != end(ia); ++p) //p指向含有4个整数的数组
{
for (auto q = begin(*p);q != end(*p); ++q) //q指向4个整数数组的首元素,q指向一个整数
{
cout << *q << " ";
}
cout << endl;
}
- 使用类型别名简化多维数组的指针
using int_array = int[4];
typedef int int_array[4]; //int_array表示4个整数的数组
8.部分习题解答:
3.3:
对于string类的输入函数,它会自动忽略开头的空白(空格、制表符、换行等等),从第一个真正的字符开始直到下一个空白。 对于getline()函数,它会保存字符串中的空白符,它读入数据,直到遇到换行符位置。
3.5:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str, sumstr;
while (cin >> str)
{
sumstr += str;
}
cout << sumstr << endl;
system("pause");
return 0;
}
3.6:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str = "fanhaihua";
for (auto &c : str)
{
c = 'x';
}
cout << str<< endl;
system("pause");
return 0;
}
3.7:
单使用char类型改变不了字符的值,必须使用char &
3.10:
;
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
string str("hello!world!");
for (auto c : str)
{
if (!ispunct(c))
{
cout << c;
}
}
system("pause");
return 0;
}
3.17:
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
using namespace std;
int main()
{
vector<string> text;
string s;
while (cin >> s)
{
text.push_back(s);
}
for (auto it = text.begin();
it != text.end()&& !it->empty(); ++it) //it指向容器内元素的首地址
{
for (int j = 0; j < (*it).length(); ++j) //j在每个元素内循环
{
(*it)[j] = toupper((*it)[j]);
}
}
for (auto c : text)
{
cout << c << endl;
}
system("pause");
return 0;
}
3.20:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<int> v2;
int n, sum;
while (cin >> n)
{
v2.push_back(n);
}
for (int i = 0,j = v2.size()-1; i <j; ++i,--j)
{
cout << v2[i] + v2[j] << endl;
}
system("pause");
return 0;
}
3.22:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("Hello world!!!");
for (auto it = s.begin();
it != s.end() && !isspace(*it); ++it
{
*it = toupper(*it);
}
cout << s << endl;
system("pause");
return 0;
}
3.23:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<int> vec(10,5);
for (auto it = vec.begin();it != vec.end();++it)
{
*it = *it * 2;
cout << *it <<endl;
}
}
3.24:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v2;
int n, sum;
while (cin >> n)
{
v2.push_back(n);
}
for (auto beg = v2.begin(), last = v2.end() - 1;beg < last;++beg,--last)
{
cout << *beg + (*last) << endl;
}
system("pause");
return 0;
}
3.25:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> grade(11, 0);
int number;
while (cin >> number)
{
if (number > 100)
{
cout << "The input number is wrong" << endl;
}
auto it = grade.begin();
int n = number / 10;
it += n;
++(*it);
}
for (int i = 0; i < 10; ++i)
{
cout << i * 10 << "~" << i * 10 + 10 << "\t";
cout << grade[i] << endl;
}
system("pause");
return 0;
}
3.36:
//容器版本比较
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v1 = { 1,2,3,4,5 };
vector<int> v2 = { 2,3,4,5 };
int num = 0;
if (v1.size() == v2.size())
{
for (auto i = v1.begin(), j = v2.begin();
i < v1.end(); ++i, ++j)
{
if (*i != *j)
{
cout << "not equal" << endl;
}
else
{
num++;
}
}
}
else
{
cout << "not equal" << endl;
}
if (num == 5)
{
cout << "equal" << endl;
}
system("pause");
return 0;
}
3.41:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};
vector<int> vec(a, a+10);
for (int i = 0;i < 10;++i)
{
cout << "vec[" << i << "]" << vec[i] << endl;
}
system("pause");
return 0;
}
3.42:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int a[10];
vector<int> vec(10, 1);
for (int i = 0;i < 10;++i)
{
a[i] = vec[i];
cout << "a[" << i << "]" << a[i] << endl;
}
system("pause");
return 0;
}
3.43、3.44、3.45:
//初始化二维数组
//版本1:
for (int(&p)[4] : ia)
{
for (const int(&q) : p)
cout << q << "\t";
cout << endl;
}
//版本2:
for (size_t i = 0; i < 3; ++i)
{
for (size_t j = 0; j < 4; ++j)
cout << ia[i][j] << "\t";
cout << endl;
}
//版本3:
for (int(*p)[4] = ia; p != end(ia); ++p)
{
for (int *q = *p; q != end(*p); ++q)
cout << *q <<"\t";
cout << endl;
}*/
//3.34即用类型别名替代上述出现的类型
//3.35即用auto代替上述出现的类型