3.6
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("some string");
for(auto &c:s)
c = 'x';
cout<<s<<endl;
return 0;
}
3.10
#include <iostream>#include <string>using namespace std;int main(){ string s; cin>>s; for(auto &c:s) if(!ispunct(c)) cout<<c; return 0;}
不存在包含引用的vector因为引用不是对象
默认初始化vector对象,从而创建一个指定类型的空vector,最常用的方法就是定义一个空vector然后运行时获取到元素的值在逐一添加
如果提供的是初始元素值的列表,只能把初始值放在花括号内初始化,类内初始化只能使用拷贝初始化或者初始化列表形式
一般初始化的真实含义依赖于传递初始值用的是花括号还是圆括号,如果是圆括号可以说提供的值是用来构造vector对象的,如果用花括号表示我们相用列表初始化元素
vector<string> v2{"hi"}:正确,初始化列表v2有一个元素
vector<string> v3("hi"):错误,无法用字符串字面值构造vector对象
如果循环体内部包括有想vector对象添加元素的语句,不能使用范围for循环
for(auto &i:v) i*=i; 和for(auto i:v) i*=i;的区别在于前者因为是引用所以改变了v的值,而后者改变的是i的值,v没有变
vector对象的下表运算符可用于访问已存在的元素而不能用于添加元素,试图用下表的形式去访问一个不存在的元素会引发 错误
确保下表合法的一个有效手段就是使用范围for语句
3.17
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
using namespace std;
int main()
{
vector<string> v;
string s;
while(cin>>s)
v.push_back(s);
for(auto &c:v){
for(auto &ch:c)
ch = toupper(ch);
cout<<c<<endl;
}
cout<<endl;
return 0;
}
如果容器为空,则begin和end返回的都是同一个迭代器,都是尾后迭代器
c++所有标准库都定义了==和!=所以养成使用迭代器和!=的习惯很重要
迭代器这个名词有三个含义,一个是迭代器概念本身,一个是容器定义的迭代器类型,还可以是某个迭代器对象
每个容器定义了一个名为iterator的类型,该类型支持迭代器概念所规定的一套操作
但凡是使用了迭代器的循环体都不要向迭代器所属容器添加元素
3.25
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<unsigned> scores(11,0);
unsigned grade;
while(cin>>grade){
if(grade<=100){
auto g = scores.size();
g = grade/10;
for(auto it = scores.begin();it == scores.begin()+g;++it)
(*it)++;
}
}
for(auto c:scores)
cout<<c<<" ";
}
如果不确定元素的确切个数,使用vector
要想理解数组声明的含义,最好从数组名字开始从内向外的顺序阅读
string不是内置的数据类型,int是内置的数据类型,如果在函数内部定义了某种内置类型的数组,默认初始化会令数组含有未定义的值
在一些情况下对数组的操作实际上是指针的操作,所以在使用数组作为auto变量的初试值时,推断得到的啥类型是指针而不是数组。但是decltype得到的是数组
如果一个指针指向了某种内置类型数组的尾元素的下一位置,呢七具备与vector的end函数返回的迭代器类似的功能
内置的下表运算符不是无符号类型,这一点和vector不一样
c风格字符串函数有strlen返回字符串长度不计入空字符;strcmp比较字符串,strcat将p2附加给p1strcpy将p2拷贝给p1
传入以上类型的函数的指针必须指向一空字符串结尾的字符串,不然会出问题
严格的说c++没有多维数组,所谓的多维数组其实就是数组的数组
要使用范围for语句处理多维数组是除了最内层循环外,其他循环的控制变量都应该是引用类型