目录
3.1 命名空间的using声明
头文件内不应有using声明
3.2 标准库类型string
cin
和getline
void test()
{
string s;
while (cin >> s)
{
cout << s << endl;
}
}
输入:
abc de
输出:
abc
de
void test()
{
string s;
while (getline(cin, s))
{
cout << s << endl;
}
}
输入:
abc de
输出:
abc de
string对象相加
规则:必须保证=
两边至少有一个是string
range for处理每个字符
void test()
{
string s("abcd");
for (auto c : s)
{
cout << c << " ";
}
}
输出: a b c d
注,如果for (int c : s),那么输出 97 98 99 100,因为是这样的:
char c = 'a';
int temp = c;
cout << temp;
注:向vector
添加元素,不能使用 range for!因为:
但是可以用range for来遍历!
编程习惯!
遍历vector
的时候,依然必须要保证下标的合法的!!
3.3 标准库类型vector
初始化方式:()
和{}
一般来说,圆括号()
表示"构造",花括号{}
表示初始化值的列表
对于后者,也有例外:
注意,对于用 range for
初始化的理解:
// 第一种情况
vector<int> v(10);
for (auto i : v)
{
cout << i << " ";
v[i] = 42;
}
for (auto num : v)
{
cout << num << " ";
}
cout << endl;
最后输出:
0 0 0 0 0 0 0 0 0 0
42 0 0 0 0 0 0 0 0 0
// 另一种情况
vector<int> v2(10);
for (auto &i : v2)
{
i = 42;
}
for (auto num : v2)
{
cout << num << " ";
}
cout << endl;
最后输出:
42 42 42 42 42 42 42 42 42 42
range for
的原理是,每次迭代i
都会被初始化为v
中下一个元素的值;
第3-7
行,因为v
每个元素都是0,因此i
每次都是0,因此v[i] = 42
永远只有第0个元素被赋值为42,其余不变;
第19-22
行,因为i
是个引用,遍历整个v2
,因此每次i = 42
都会把每个元素赋值为42;
C++中vector添加元素和C语言的区别
C在创建vector的时候,顺便指定其容量是最好的;
C++却相反,事先设定大小反而性能可能更差。
缓冲区溢出 与 下标不合法
void test()
{
vector<int >v;
v[10] = 10; // 直接崩溃!因为v是空的,无法用下标访问
vector<int >v1(11, 0); // 初始化v1为11个0
v[10] = 10; // 正确, 因为现在v1有11个元素,因此可以访问
}
3.4 迭代器
迭代器的概念
技巧:平时其实无须注意迭代器的类型,用auto
即可,因此:
vector<int>::iterator iter = v1.begin(); // 完全不用写前面的那一长串!
直接用:
auto iter = v1.begin();
迭代器的运算符
*iter
解引用,获得迭代器所指元素的引用(*iter).age
解引用,获得迭代器所指对象的age
成员iter->age
和上面的等价++/-- iter
移动迭代器
因此,用->
会方便点,就不需要每次都加*
了(->
把解引用和成员访问两个操作结合在一起)
注1:C++迭代器可以往回退,但Python里的迭代器是不行的,例如:
void test()
{
vector<int> v1;
for (int i = 0; i < 10; ++i)
{
v1.push_back(i);
}
vector<int>::iterator iter = v1.begin() + 3;
cout << *iter << endl; // 输出3
--iter; // 回退
cout << *iter; // 输出2
}
注2:C++11没有定义迭代器的加法,因为是没有意义的。而可以用两个迭代器相减,得到迭代器之间的距离。
void test()
{
vector<int>v;
for (int i = 0; i < 10; ++i)
{
v.push_back(i);
}
auto begin = v.begin();
auto end = v.end();
cout << *(begin + end); // 错误
cout << end - begin; // 输出10, 指的是end到begin之间的距离(元素个数)
}
注3:不能对end
进行增减或解引用,因为end
返回的迭代器不实际指示某个元素。
编程习惯!
对于C++来说,推荐使用迭代器去遍历容器!
迭代器的const、非const、cbegin()
void test()
{
vector<int> v1;
for (int i = 0; i < 10; ++i)
{
v1.push_back(i);
}
vector<int>::const_iterator citer = v1.begin() + 4;
*citer = 2; // 错误,因为是const,不可以修改
cout << *citer;
// 或者用C++11的新函数 cbegin cend
for (auto citer = v1.cbegin(); citer != v1.cend(); ++citer)
{
...
}
}
迭代器失效
任何一种可能改变vector
容量的操作,例如push_back
,都会使vector
对象的迭代器失效!
3.5 数组
初始化
关于int
等基本数据类型和string
型的初始化区别
void test()
{
int a[10];
int b[10] = {};
cout << a[2]; // 输出错乱!因为函数内不会默认初始化int型数组
cout << b[2]; // 输出0, 因为上面{}表面已经初始化为全0了
string s[10];
cout << s[2]; // 输出空串, 因为string特性, 不论函数内还是外, 都会默认初始化为空串!
}
int c[10]; // 函数外定义, 那么默认初始化全0
int main()
{
test();
cout << c[3]; // 输出0
return 0;
}
遍历
推荐使用range for
这个遍历方法!
指针和数组的隐式关系
对于auto
:
对于decltype
:该是什么就是什么,不会发生隐式转换
指针也是迭代器
void test()
{
int a[10] = {};
for (int i = 0; i < 10; ++i)
{
a[i] = i;
}
int* begin = a; // 指针也是迭代器
int* end = &a[10]; // 尾后指针
for (; begin != end; ++begin) // 迭代
{
cout << *begin << " ";
}
}
注意,第9
行,a[10]
的索引只到9,但作为尾后指针,可以取到最后一个元素的下一个元素,因此索引是10;这个不存在的元素唯一的作用就是提供地址用于初始化end
。
但是!这样很容易出错,因为C++11引入了标准库函数begin()
和end()
标准库函数begin
和end
注:上面不能用begin
和end
来作为变量名称,不然会报错:
int *begin = begin(ia); int *end= end(ia); --> 错误
附:部分习题答案
练习3-2
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
void test()
{
// 一次读入一行
string s;
//while (getline(cin, s))
//{
// cout << s;
//}
// 一次读入一个词
string s1;
while (cin >> s1)
{
cout << s1;
}
}
int main()
{
test();
return 0;
}
练习3-4
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
void test()
{
cout << "比大小:" << endl;
string s1, s2;
cin >> s1 >> s2;
if (s1 == s2)
{
cout << s1;
}
else
{
string s3 = (s1 > s2) ? s1 : s2;
cout << s3 << endl;
}
cout << "是否等长:" << endl;
cin >> s1 >> s2;
if (s1.size() == s2.size())
{
cout << s1;
}
else
{
string s4 = (s1.size() > s2.size()) ? s1 : s2;
cout << s4 << endl;
}
}
int main()
{
test();
return 0;
}
练习3-5
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
void test()
{
string s1, s2;
while (cin >> s1)
{
if (s1 == "EOF")
{
break;
}
s2 += s1;
}
cout << s2 << endl;
}
int main()
{
test();
return 0;
}
练习3-6
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
void test()
{
string s;
getline(cin, s); // 注,空格也是字符,也会被X替代
for (auto &ch : s)
{
ch = 'X';
}
cout << s;
}
int main()
{
test();
return 0;
}
练习3-7
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
void test()
{
string s;
getline(cin, s); // 注,空格也是字符,也会被X替代
for (char& ch : s)
{
ch = 'X';
}
cout << s;
}
int main()
{
test();
return 0;
}
练习3-8
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
void test()
{
string s;
getline(cin, s);
decltype(s.size()) index = 0;
while (true)
{
if (index == s.size())
{
break;
}
char& r = s[index];
r = 'X';
++index;
}
cout << s;
}
void test1()
{
string s;
getline(cin, s);
for (decltype(s.size()) index = 0; index != s.size(); ++index)
{
char& r = s[index];
r = 'X';
}
cout << s;
}
/// 上面的写复杂了,忘记了还可以下标访问
void test2()
{
string s;
getline(cin, s);
for (decltype(s.size()) index = 0; index != s.size(); ++index)
{
s[index] = 'X';
}
cout << s;
}
int main()
{
test2();
return 0;
}
练习3-10
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
void test()
{
string s1, s2;
getline(cin, s1);
for (auto c : s1)
{
if (ispunct(c))
{
continue;
}
s2 += c;
}
cout << s2;
}
int main()
{
test();
return 0;
}
练习3-14
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
#include <vector>
void test()
{
vector<int> v;
int num = 0;
while (cin >> num)
{
v.push_back(num);
}
//for (vector<int>::iterator begin = v.begin(); begin != v.end(); ++begin)
//{
// cout << *begin << " ";
//}
for (auto num : v)
{
cout << num << " ";
}
}
int main()
{
test();
return 0;
}
练习3-15
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
#include <vector>
void test()
{
vector<string> v;
string s;
while (cin >> s)
{
if (s == "EOF")
{
break;
}
v.push_back(s);
}
for (auto c : v)
{
cout << c << " ";
}
}
int main()
{
test();
return 0;
}
练习3-17
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
#include <vector>
void test()
{
vector<string> v;
string s1, s2;
while (cin >> s1)
{
if (s1 == "EOF")
{
break;
}
for (auto& c : s1)
{
c = toupper(c);
}
v.push_back(s1);
}
for (auto str : v)
{
cout << str << endl;
}
}
int main()
{
test();
return 0;
}
练习3-19
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
#include <vector>
void test()
{
// 方法一
vector<int> v(10, 42);
for (auto i : v)
{
cout << i << " ";
}
cout << endl;
// 方法二
vector<int> v1;
for (int i = 0; i < 10; ++i)
{
v1.push_back(42);
}
for (auto i : v)
{
cout << i << " ";
}
cout << endl;
// 方法三 --> 我没想到
vector<int> v2(10);
for (auto &i : v2)
{
i = 42;
}
cout << endl;
for (auto i : v2)
{
cout << i << " ";
}
cout << endl;
}
int main()
{
test();
return 0;
}
练习3-23
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
#include <vector>
void test()
{
vector<int>v;
for (int i = 0; i < 10; ++i)
{
v.push_back(i);
}
for (auto begin = v.begin(); begin != v.end(); ++begin)
{
*begin *= 2;
}
for (auto begin = v.begin(); begin != v.end(); ++begin)
{
cout << *begin << " ";
}
}
int main()
{
test();
return 0;
}
练习3-24
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
#include <vector>
void test()
{
vector<int>v;
for (int i = 0; i < 10; ++i)
{
v.push_back(i);
}
for (auto begin = v.begin(); begin != v.end(); ++begin)
{
cout << *begin << " ";
}
cout << endl;
// 相邻两数之和
for (auto begin = v.begin(); begin != v.end()-1; ++begin)
{
cout << *begin+*(begin+1) << " ";
}
cout << endl;
// 首位元素之和
//int tag = 1;
//for (auto begin = v.begin(); begin != v.end(); ++begin)
//{
// if (tag == v.size() / 2)
// {
// break;
// }
// cout << *(begin) + *(v.size()-tag-1)
//}
}
int main()
{
test();
return 0;
}
练习3-25
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
#include <vector>
void test()
{
vector<int> v(4);
int score;
auto begin = v.begin();
while (cin >> score)
{
if (score <= 30)
{
++* (begin + score / 10);
}
}
for (auto begin = v.begin(); begin != v.end(); ++begin)
{
cout << *begin << " ";
}
}
int main()
{
test();
return 0;
}
练习3-31
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
#include <vector>
void test()
{
int a[10] = {};
int tag = 0;
for (auto& i : a)
{
i = tag;
++tag;
}
for (auto& i : a)
{
cout << i << " ";
}
}
int main()
{
test();
return 0;
}
练习3-32
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
#include <vector>
void test()
{
int a[10] = {};
int tag = 0;
// 拷贝给另一个数组
for (auto& i : a)
{
i = tag;
++tag;
}
int b[10] = {};
tag = 0;
for (auto i : a)
{
b[tag] = i;
++tag;
}
// 用vector重新实现
vector<int>v;
for (auto& i : a)
{
v.push_back(i);
}
// 打印输出
for (auto& i : v)
{
cout << i << " ";
}
}
int main()
{
test();
return 0;
}
练习3-36
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
#include <vector>
void test()
{
// 比较数组元素是否相等
int a[] = { 1,2,3,4,5,6 };
int b[] = { 1,2,3,4,5,6 };
int numA = 0;
int numB = 0;
for (auto i : a)
{
++numA;
}
for (auto i : b)
{
++numB;
}
if (numA != numB)
{
cout << "不相等";
}
else
{
for (int i = 0; i < numA; ++i)
{
if (a[i] != b[i])
{
cout << "不相等";
}
}
cout << "相等";
}
}
int main()
{
test();
return 0;
}
练习3-39
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
#include <vector>
void test()
{
string s1("wind1");
string s2("wind1");
if (s1.size() != s2.size())
{
cout << "不相等";
}
else
{
int tag = 0;
for (int i = 0; i < s1.size(); ++i)
{
if (s1[i] != s2[i])
{
cout << "不相等";
tag = 0;
break;
}
tag = 1;
}
if (tag)
{
cout << "相等";
}
}
cout << endl;
// 方法二
if (s1 == s2)
{
cout << "相等";
}
else
{
cout << "不相等";
}
}
int main()
{
test();
return 0;
}
练习3-40和3-41
#include <iostream>
#define _CRT_SECURE_NO_DEPRECATE
using namespace std;
#include <string>
#include <vector>
void test()
{
// 整形数组初始化vector对象
const int size = 10;
int a[size] = { 1,2,3,4 };
vector<int>v(begin(a), end(a));
for (auto i : v)
{
cout << i << endl;
}
cout << endl;
// vector对象拷贝给整型数组
int b[size];
auto it = cbegin(a);
for (auto& val : b)
{
val = *it;
++it;
}
for (auto i : b)
{
cout << i << endl;
}
}
int main()
{
test();
return 0;
}