• 【C++】《C++ Primer》第三章 知识点总结


    目录

    3.1 命名空间的using声明

    头文件内不应有using声明

    3.2 标准库类型string

    cin和getline

    string对象相加

    range for处理每个字符

    编程习惯!

    3.3 标准库类型vector

    初始化方式:()和{}

    C++中vector添加元素和C语言的区别

    缓冲区溢出 与 下标不合法

    3.4 迭代器

    迭代器的概念

    迭代器的运算符

    编程习惯!

    迭代器的const、非const、cbegin()

    迭代器失效

    3.5 数组

    初始化

    遍历

    指针和数组的隐式关系

    指针也是迭代器

    标准库函数begin和end

    附:部分习题答案


    3.1 命名空间的using声明

    头文件内不应有using声明

    3.2 标准库类型string

    cingetline

    1. void test()
    2. {
    3. string s;
    4. while (cin >> s)
    5. {
    6. cout << s << endl;
    7. }
    8. }
    9. 输入:
    10. abc de
    11. 输出:
    12. abc
    13. de
    1. void test()
    2. {
    3. string s;
    4. while (getline(cin, s))
    5. {
    6. cout << s << endl;
    7. }
    8. }
    9. 输入:
    10. abc de
    11. 输出:
    12. abc de

    string对象相加

    规则:必须保证=两边至少有一个是string

    range for处理每个字符

    1. void test()
    2. {
    3. string s("abcd");
    4. for (auto c : s)
    5. {
    6. cout << c << " ";
    7. }
    8. }
    9. 输出: a b c d
    10. 注,如果for (int c : s),那么输出 97 98 99 100,因为是这样的:
    11. char c = 'a';
    12. int temp = c;
    13. cout << temp;

    注:向vector添加元素,不能使用 range for!因为:

    但是可以用range for来遍历!

    编程习惯!

    遍历vector的时候,依然必须要保证下标的合法的!!

    3.3 标准库类型vector

    初始化方式:(){}

    一般来说,圆括号()表示"构造",花括号{}表示初始化值的列表

    对于后者,也有例外:

    注意,对于用 range for初始化的理解:

    1. // 第一种情况
    2. vector<int> v(10);
    3. for (auto i : v)
    4. {
    5. cout << i << " ";
    6. v[i] = 42;
    7. }
    8. for (auto num : v)
    9. {
    10. cout << num << " ";
    11. }
    12. cout << endl;
    13. 最后输出:
    14. 0 0 0 0 0 0 0 0 0 0
    15. 42 0 0 0 0 0 0 0 0 0
    16. // 另一种情况
    17. vector<int> v2(10);
    18. for (auto &i : v2)
    19. {
    20. i = 42;
    21. }
    22. for (auto num : v2)
    23. {
    24. cout << num << " ";
    25. }
    26. cout << endl;
    27. 最后输出:
    28. 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++却相反,事先设定大小反而性能可能更差。

    缓冲区溢出 与 下标不合法

    1. void test()
    2. {
    3. vector<int >v;
    4. v[10] = 10; // 直接崩溃!因为v是空的,无法用下标访问
    5. vector<int >v1(11, 0); // 初始化v1为11个0
    6. v[10] = 10; // 正确, 因为现在v1有11个元素,因此可以访问
    7. }

    3.4 迭代器

    迭代器的概念

    技巧:平时其实无须注意迭代器的类型,用auto即可,因此:

    1. vector<int>::iterator iter = v1.begin(); // 完全不用写前面的那一长串!
    2. 直接用:
    3. auto iter = v1.begin();

    迭代器的运算符

    • *iter 解引用,获得迭代器所指元素的引用
    • (*iter).age 解引用,获得迭代器所指对象的age成员
    • iter->age 和上面的等价
    • ++/-- iter 移动迭代器

    因此,->会方便点,就不需要每次都加*了(->把解引用和成员访问两个操作结合在一起)

    注1:C++迭代器可以往回退,但Python里的迭代器是不行的,例如:

    1. void test()
    2. {
    3. vector<int> v1;
    4. for (int i = 0; i < 10; ++i)
    5. {
    6. v1.push_back(i);
    7. }
    8. vector<int>::iterator iter = v1.begin() + 3;
    9. cout << *iter << endl; // 输出3
    10. --iter; // 回退
    11. cout << *iter; // 输出2
    12. }

    注2:C++11没有定义迭代器的加法,因为是没有意义的。而可以用两个迭代器相减,得到迭代器之间的距离。

    1. void test()
    2. {
    3. vector<int>v;
    4. for (int i = 0; i < 10; ++i)
    5. {
    6. v.push_back(i);
    7. }
    8. auto begin = v.begin();
    9. auto end = v.end();
    10. cout << *(begin + end); // 错误
    11. cout << end - begin; // 输出10, 指的是end到begin之间的距离(元素个数)
    12. }

    注3:不能对end进行增减或解引用,因为end返回的迭代器不实际指示某个元素。

    编程习惯!

    对于C++来说,推荐使用迭代器去遍历容器!

    迭代器的const、非const、cbegin()

    1. void test()
    2. {
    3. vector<int> v1;
    4. for (int i = 0; i < 10; ++i)
    5. {
    6. v1.push_back(i);
    7. }
    8. vector<int>::const_iterator citer = v1.begin() + 4;
    9. *citer = 2; // 错误,因为是const,不可以修改
    10. cout << *citer;
    11. // 或者用C++11的新函数 cbegin cend
    12. for (auto citer = v1.cbegin(); citer != v1.cend(); ++citer)
    13. {
    14. ...
    15. }
    16. }

    迭代器失效

    任何一种可能改变vector容量的操作,例如push_back,都会使vector对象的迭代器失效!

    3.5 数组

    初始化

    关于int等基本数据类型和string型的初始化区别

    1. void test()
    2. {
    3. int a[10];
    4. int b[10] = {};
    5. cout << a[2]; // 输出错乱!因为函数内不会默认初始化int型数组
    6. cout << b[2]; // 输出0, 因为上面{}表面已经初始化为全0了
    7. string s[10];
    8. cout << s[2]; // 输出空串, 因为string特性, 不论函数内还是外, 都会默认初始化为空串!
    9. }
    10. int c[10]; // 函数外定义, 那么默认初始化全0
    11. int main()
    12. {
    13. test();
    14. cout << c[3]; // 输出0
    15. return 0;
    16. }

    遍历

    推荐使用range for这个遍历方法!

    指针和数组的隐式关系

    对于auto

    对于decltype:该是什么就是什么,不会发生隐式转换

    指针也是迭代器

    1. void test()
    2. {
    3. int a[10] = {};
    4. for (int i = 0; i < 10; ++i)
    5. {
    6. a[i] = i;
    7. }
    8. int* begin = a; // 指针也是迭代器
    9. int* end = &a[10]; // 尾后指针
    10. for (; begin != end; ++begin) // 迭代
    11. {
    12. cout << *begin << " ";
    13. }
    14. }

    注意,第9行,a[10]的索引只到9,但作为尾后指针,可以取到最后一个元素的下一个元素,因此索引是10;这个不存在的元素唯一的作用就是提供地址用于初始化end

    但是!这样很容易出错,因为C++11引入了标准库函数begin()end()

    标准库函数beginend

    注:上面不能用beginend来作为变量名称,不然会报错:

    int *begin = begin(ia); int *end= end(ia); --> 错误

     

    附:部分习题答案

    练习3-2 

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. void test()
    6. {
    7. // 一次读入一行
    8. string s;
    9. //while (getline(cin, s))
    10. //{
    11. // cout << s;
    12. //}
    13. // 一次读入一个词
    14. string s1;
    15. while (cin >> s1)
    16. {
    17. cout << s1;
    18. }
    19. }
    20. int main()
    21. {
    22. test();
    23. return 0;
    24. }

    练习3-4

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. void test()
    6. {
    7. cout << "比大小:" << endl;
    8. string s1, s2;
    9. cin >> s1 >> s2;
    10. if (s1 == s2)
    11. {
    12. cout << s1;
    13. }
    14. else
    15. {
    16. string s3 = (s1 > s2) ? s1 : s2;
    17. cout << s3 << endl;
    18. }
    19. cout << "是否等长:" << endl;
    20. cin >> s1 >> s2;
    21. if (s1.size() == s2.size())
    22. {
    23. cout << s1;
    24. }
    25. else
    26. {
    27. string s4 = (s1.size() > s2.size()) ? s1 : s2;
    28. cout << s4 << endl;
    29. }
    30. }
    31. int main()
    32. {
    33. test();
    34. return 0;
    35. }

    练习3-5

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. void test()
    6. {
    7. string s1, s2;
    8. while (cin >> s1)
    9. {
    10. if (s1 == "EOF")
    11. {
    12. break;
    13. }
    14. s2 += s1;
    15. }
    16. cout << s2 << endl;
    17. }
    18. int main()
    19. {
    20. test();
    21. return 0;
    22. }

    练习3-6

     

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. void test()
    6. {
    7. string s;
    8. getline(cin, s); // 注,空格也是字符,也会被X替代
    9. for (auto &ch : s)
    10. {
    11. ch = 'X';
    12. }
    13. cout << s;
    14. }
    15. int main()
    16. {
    17. test();
    18. return 0;
    19. }

    练习3-7

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. void test()
    6. {
    7. string s;
    8. getline(cin, s); // 注,空格也是字符,也会被X替代
    9. for (char& ch : s)
    10. {
    11. ch = 'X';
    12. }
    13. cout << s;
    14. }
    15. int main()
    16. {
    17. test();
    18. return 0;
    19. }

    练习3-8

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. void test()
    6. {
    7. string s;
    8. getline(cin, s);
    9. decltype(s.size()) index = 0;
    10. while (true)
    11. {
    12. if (index == s.size())
    13. {
    14. break;
    15. }
    16. char& r = s[index];
    17. r = 'X';
    18. ++index;
    19. }
    20. cout << s;
    21. }
    22. void test1()
    23. {
    24. string s;
    25. getline(cin, s);
    26. for (decltype(s.size()) index = 0; index != s.size(); ++index)
    27. {
    28. char& r = s[index];
    29. r = 'X';
    30. }
    31. cout << s;
    32. }
    33. /// 上面的写复杂了,忘记了还可以下标访问
    34. void test2()
    35. {
    36. string s;
    37. getline(cin, s);
    38. for (decltype(s.size()) index = 0; index != s.size(); ++index)
    39. {
    40. s[index] = 'X';
    41. }
    42. cout << s;
    43. }
    44. int main()
    45. {
    46. test2();
    47. return 0;
    48. }

    练习3-10

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. void test()
    6. {
    7. string s1, s2;
    8. getline(cin, s1);
    9. for (auto c : s1)
    10. {
    11. if (ispunct(c))
    12. {
    13. continue;
    14. }
    15. s2 += c;
    16. }
    17. cout << s2;
    18. }
    19. int main()
    20. {
    21. test();
    22. return 0;
    23. }

    练习3-14

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. #include
    6. void test()
    7. {
    8. vector<int> v;
    9. int num = 0;
    10. while (cin >> num)
    11. {
    12. v.push_back(num);
    13. }
    14. //for (vector::iterator begin = v.begin(); begin != v.end(); ++begin)
    15. //{
    16. // cout << *begin << " ";
    17. //}
    18. for (auto num : v)
    19. {
    20. cout << num << " ";
    21. }
    22. }
    23. int main()
    24. {
    25. test();
    26. return 0;
    27. }

    练习3-15

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. #include
    6. void test()
    7. {
    8. vector v;
    9. string s;
    10. while (cin >> s)
    11. {
    12. if (s == "EOF")
    13. {
    14. break;
    15. }
    16. v.push_back(s);
    17. }
    18. for (auto c : v)
    19. {
    20. cout << c << " ";
    21. }
    22. }
    23. int main()
    24. {
    25. test();
    26. return 0;
    27. }

    练习3-17 

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. #include
    6. void test()
    7. {
    8. vector v;
    9. string s1, s2;
    10. while (cin >> s1)
    11. {
    12. if (s1 == "EOF")
    13. {
    14. break;
    15. }
    16. for (auto& c : s1)
    17. {
    18. c = toupper(c);
    19. }
    20. v.push_back(s1);
    21. }
    22. for (auto str : v)
    23. {
    24. cout << str << endl;
    25. }
    26. }
    27. int main()
    28. {
    29. test();
    30. return 0;
    31. }

    练习3-19

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. #include
    6. void test()
    7. {
    8. // 方法一
    9. vector<int> v(10, 42);
    10. for (auto i : v)
    11. {
    12. cout << i << " ";
    13. }
    14. cout << endl;
    15. // 方法二
    16. vector<int> v1;
    17. for (int i = 0; i < 10; ++i)
    18. {
    19. v1.push_back(42);
    20. }
    21. for (auto i : v)
    22. {
    23. cout << i << " ";
    24. }
    25. cout << endl;
    26. // 方法三 --> 我没想到
    27. vector<int> v2(10);
    28. for (auto &i : v2)
    29. {
    30. i = 42;
    31. }
    32. cout << endl;
    33. for (auto i : v2)
    34. {
    35. cout << i << " ";
    36. }
    37. cout << endl;
    38. }
    39. int main()
    40. {
    41. test();
    42. return 0;
    43. }

    练习3-23

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. #include
    6. void test()
    7. {
    8. vector<int>v;
    9. for (int i = 0; i < 10; ++i)
    10. {
    11. v.push_back(i);
    12. }
    13. for (auto begin = v.begin(); begin != v.end(); ++begin)
    14. {
    15. *begin *= 2;
    16. }
    17. for (auto begin = v.begin(); begin != v.end(); ++begin)
    18. {
    19. cout << *begin << " ";
    20. }
    21. }
    22. int main()
    23. {
    24. test();
    25. return 0;
    26. }

    练习3-24

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. #include
    6. void test()
    7. {
    8. vector<int>v;
    9. for (int i = 0; i < 10; ++i)
    10. {
    11. v.push_back(i);
    12. }
    13. for (auto begin = v.begin(); begin != v.end(); ++begin)
    14. {
    15. cout << *begin << " ";
    16. }
    17. cout << endl;
    18. // 相邻两数之和
    19. for (auto begin = v.begin(); begin != v.end()-1; ++begin)
    20. {
    21. cout << *begin+*(begin+1) << " ";
    22. }
    23. cout << endl;
    24. // 首位元素之和
    25. //int tag = 1;
    26. //for (auto begin = v.begin(); begin != v.end(); ++begin)
    27. //{
    28. // if (tag == v.size() / 2)
    29. // {
    30. // break;
    31. // }
    32. // cout << *(begin) + *(v.size()-tag-1)
    33. //}
    34. }
    35. int main()
    36. {
    37. test();
    38. return 0;
    39. }

    练习3-25

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. #include
    6. void test()
    7. {
    8. vector<int> v(4);
    9. int score;
    10. auto begin = v.begin();
    11. while (cin >> score)
    12. {
    13. if (score <= 30)
    14. {
    15. ++* (begin + score / 10);
    16. }
    17. }
    18. for (auto begin = v.begin(); begin != v.end(); ++begin)
    19. {
    20. cout << *begin << " ";
    21. }
    22. }
    23. int main()
    24. {
    25. test();
    26. return 0;
    27. }

    练习3-31

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. #include
    6. void test()
    7. {
    8. int a[10] = {};
    9. int tag = 0;
    10. for (auto& i : a)
    11. {
    12. i = tag;
    13. ++tag;
    14. }
    15. for (auto& i : a)
    16. {
    17. cout << i << " ";
    18. }
    19. }
    20. int main()
    21. {
    22. test();
    23. return 0;
    24. }

    练习3-32

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. #include
    6. void test()
    7. {
    8. int a[10] = {};
    9. int tag = 0;
    10. // 拷贝给另一个数组
    11. for (auto& i : a)
    12. {
    13. i = tag;
    14. ++tag;
    15. }
    16. int b[10] = {};
    17. tag = 0;
    18. for (auto i : a)
    19. {
    20. b[tag] = i;
    21. ++tag;
    22. }
    23. // 用vector重新实现
    24. vector<int>v;
    25. for (auto& i : a)
    26. {
    27. v.push_back(i);
    28. }
    29. // 打印输出
    30. for (auto& i : v)
    31. {
    32. cout << i << " ";
    33. }
    34. }
    35. int main()
    36. {
    37. test();
    38. return 0;
    39. }

    练习3-36

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. #include
    6. void test()
    7. {
    8. // 比较数组元素是否相等
    9. int a[] = { 1,2,3,4,5,6 };
    10. int b[] = { 1,2,3,4,5,6 };
    11. int numA = 0;
    12. int numB = 0;
    13. for (auto i : a)
    14. {
    15. ++numA;
    16. }
    17. for (auto i : b)
    18. {
    19. ++numB;
    20. }
    21. if (numA != numB)
    22. {
    23. cout << "不相等";
    24. }
    25. else
    26. {
    27. for (int i = 0; i < numA; ++i)
    28. {
    29. if (a[i] != b[i])
    30. {
    31. cout << "不相等";
    32. }
    33. }
    34. cout << "相等";
    35. }
    36. }
    37. int main()
    38. {
    39. test();
    40. return 0;
    41. }

    练习3-39 

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. #include
    6. void test()
    7. {
    8. string s1("wind1");
    9. string s2("wind1");
    10. if (s1.size() != s2.size())
    11. {
    12. cout << "不相等";
    13. }
    14. else
    15. {
    16. int tag = 0;
    17. for (int i = 0; i < s1.size(); ++i)
    18. {
    19. if (s1[i] != s2[i])
    20. {
    21. cout << "不相等";
    22. tag = 0;
    23. break;
    24. }
    25. tag = 1;
    26. }
    27. if (tag)
    28. {
    29. cout << "相等";
    30. }
    31. }
    32. cout << endl;
    33. // 方法二
    34. if (s1 == s2)
    35. {
    36. cout << "相等";
    37. }
    38. else
    39. {
    40. cout << "不相等";
    41. }
    42. }
    43. int main()
    44. {
    45. test();
    46. return 0;
    47. }

    练习3-40和3-41

    1. #include
    2. #define _CRT_SECURE_NO_DEPRECATE
    3. using namespace std;
    4. #include
    5. #include
    6. void test()
    7. {
    8. // 整形数组初始化vector对象
    9. const int size = 10;
    10. int a[size] = { 1,2,3,4 };
    11. vector<int>v(begin(a), end(a));
    12. for (auto i : v)
    13. {
    14. cout << i << endl;
    15. }
    16. cout << endl;
    17. // vector对象拷贝给整型数组
    18. int b[size];
    19. auto it = cbegin(a);
    20. for (auto& val : b)
    21. {
    22. val = *it;
    23. ++it;
    24. }
    25. for (auto i : b)
    26. {
    27. cout << i << endl;
    28. }
    29. }
    30. int main()
    31. {
    32. test();
    33. return 0;
    34. }

     

  • 相关阅读:
    HIVE SQL regexp_extract和regexp_replace配合使用正则提取多个符合条件的值
    NNDL 实验八 网络优化与正则化(4)参数初始化
    app逆向(8)|app的加固+脱壳和frida+rpc介绍
    好客租房120-在脚手架中使用sass
    Python 模拟Laguerre Polynomial拉盖尔多项式
    23软考备考已开始,网络工程师知识点速记~(3)
    【数据结构】链表的学习和介绍
    P3051 [USACO12MAR]Haybale Restacking G
    MySQL 查询语句大全
    第2-3-8章 分片上传和分片合并的接口开发-文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss
  • 原文地址:https://blog.csdn.net/Wind_2028/article/details/127534830