字符串、向量和数组---C++ 基础
来源:互联网 发布:胜任力测评软件 编辑:程序博客网 时间:2024/06/10 10:51
前言
上一章,复习了基本数据类型,趁热打铁,继续把字符串、向量(vector)和数组搞定。
字符串是由字符组成,也是序列结构,因此,本章其实设计到的数据结构是序列。那么就需要考虑是否能够随机访问,如何遍历,如何进行一些基本操作,以及这些基本操作的效率问题。
整个系列的复习会将所有涉及到的stl进行分析,工作量可能会大,但是复习嘛,总是一步一个脚印。废话不多说,开始干货。
3.1 using声明命名空间
命名空间这个东西使得大的项目的名称管理的效率得到了提升。如果需要使用库函数,那么需要加上命名空间才能使用相应的名称。而using就使得不用每个名称前都需要加命名空间。
#include <iostream>using std::cin; // 一般来说,大家都喜欢之间using namespace std,这样就不用对每个对象都使用using了int main() {}
既然提到了#include,我觉得有必要复习一下预处理器命令,以及宏,这个还是非常重要,我在复习设计模式的,涉及到的一个问题,c++如何实现反射?,详细请见博客另一篇文章《C++反射的实现》
注意:
头文件里不应该包含using声明,因为,头文件的内容会拷贝到所有引用它的文件中,如果头文件里有某个声明,那么每个使用了这个头文件的文件都会有这个声明,名称污染。。。不知哪听来的
3.2 string类型
此处的string类型是标准库中的string,定义在std命名空间里。导入的头文件是string,而不是string.h,后者是c标准下的字符串数组的库函数集合。
#include <string>// 注意,不是string.h,如果想要使用c下的字符串处理函数,使用后者using namespace std;
string类型是可变长的字符序列。
- 初始化
string s1; // 默认初始化,空串string s2 = s1; // s2 是 s1 的副本string s2(s1); // 直接初始化string s3("hiya");string s3 = "hiya"; // s3 是 字面值的副本string s4(10, 'c'); // s4 "cccccccccc"
- 操作
os << s // 写入输出流is >> s // 从流读出字符串,以空白分隔getline(is, s) // 从流中读出一行s.empty() s.size()s[n]s1 + s2s1 = s2s1 == s2s1 != s2 <, <=, >, >=s.push_back(char s)s.pop_back()s.begin()s.end()s.rbegin()s.rend()s.reverse()s.clear()s.back()s.front()s += "hello"s.find(str, pos) // 没找到返回-1, 返回string::size_type类型,保证能够在当前机器上存储string对象大小
注意:
string.size() 返回的是size_type类型,这是一个无符号类型,因此,在比较时要特别注意隐式转换(有符号类型会隐式转换成无符号类型),我们知道找不到返回的是size_t 类型的 -1,这个数其实是可能的最大数。
另外string类型的加法,必须要有一个运算对象是string,(字符串字面值不是字符串string类型)
注意:
s = "hello" + "," + s; // 错误,因为"hello"是一个字符串字面值,不是字符串
- 处理string对象中的字符
#include <cctype>string s = "hello world";for (auto &c : s) { // 要修改字符,必须要使用引用 cout << isalnum(c) << endl; tolower(c);}char a = 'a';isalnum(a);isalpha(a);isdigit(a);isspace(a);tolower(a);toupper(a);
3.3 标准库类型vector
vector是标准库里的一类容器,表示对象的有序集合(不包含引用)。
- 定义和初始化vector对象
vector其内存占用空间是只增不减,erase和clear都不能减少vector占用的内存。所有内存空间在vector析构的时候回收。
#include <vector>using namespace std;vector<T> v1;vector<T> v2(v1);vector<T> v2 = v1;vector<T> v3(n, val);vector<T> v4(n);vector<T> v5{a, b, c};vector<T> v5 = {a, b, c};vector<string> v6 = {10, "1"}; // 十个string对象vector<int> v7 = {10, 1}; // 两个对象
- 操作
vector<int > arr;arr.push_back(10);arr.pop_back();arr.empty();arr.size();arr.front();arr.back();vector<int> foo(3, 100);foo.swap(bar); // swap 是常数时间复杂度(仅仅交换了指针),因此常常用来清空vector,进行内存释放for (auto &e : arr) { e = 11; // 可以进行修改,但不要对arr进行添加或者删除}
前面提到了vector怎样清除内存占用的问题。这里就要用到临时对象以及析构的概念了。
vector<int> arr(100000, 0);...//建立临时对象,然后调用swap函数,临时对象会立即调用析构函数,进行内存释放vector<int>().swap(arr);a.pop_back();vector<int>(arr).swap(arr); // 释放一个
注意:
vector 使用下标访问元素,必须是已经存在的下标,不要放低级错误
3.4 迭代器介绍
迭代器在标准库中是一种访问容器对象更加通用的方式,只有少数几个容器是支持下标访问的,目前已知的有vector、string、deque、map、unordered_map。
- 使用迭代器
auto b = v.begin();auto e = v.end(); // 记住auto的方法,非常简便,不用写过多的类型*iter // 返回对象引用iter -> mem // 取名为mem的成员++ iter-- iteriter1 == iter2iter1 != iter2
注意:
再次提醒,任何改变容器对象数量,都会使得迭代器失效
- 迭代器运算
iter + n iter - n iter += n iter -= n iter1 - iter2 >, >=, <, <=auto mid = vi.begin() + v.size() / 2; // 取中点
3.5 数组
数组类似vector,但是数组的大小在定义时就已经确定了。
注意:
数组不允许使用 auto 关键字由初始化列表来推断类型
- 定义和初始化
int a[10]; // 默认初始化 // 显示初始化int arr[5] = {1, 1}; // 1 1 0 0 0int arr[] = {1, 1} // 1 1int arr[2] = {1, 2, 3} // 错误,初始值过多int arr[100] = {0} // 0 ...// 字符数组,特殊在最后的空字符char a1[] = {'a', 'b', 'c'} // 最后没有空字符char a2[] = {'a', '\0'} // 最后有显示的空字符char a3[] = "hello"; // 自动添加末尾空字符char a4[5] = "hello word" // 错误,没有空间存放空字符
- 理解复杂数组
int &ref[10] = ptr; // 错误,没有引用数组int *ptr[10]; // ptr是一个数组,包含10个int *类型指针的数组int (*ptr)[10]; // ptr是一个指针,指向含有10个int类型整数的数组int (&ptr_ref)[10]; // ptr_ref是一个引用,绑定的是含有10个int类型整数的数组
- C 风格字符串(安全风险,需要自己管理大小)
C 风格的字符串要求字符串数组要以空字符’\0’结尾。
#include <string.h>strlen(p);strcmp(p1, p2); // 返回比较值,+、-、0strcat(p1, p2); // p2 附加到p1 ,返回p1strcpy(p1, p2); // p2 拷贝给p1,返回p1
3.6 多维数组
严格来说,c++没有多维数组,通常说的多维数组都是数组的数组。因此,初始化、访问时都可以仔细理解一下。
int ia[3][4]; // 默认初始化,大小为3的数组,每个元素是4个整数的数组int arr[100][200] = {0} // 初始化为0int ia[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10 , 11} };// 等价于int ia[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};// 显示初始化每行首元素int ia[3][4] = {{0}, {3}, {4}};// 显示初始化第一行,其他的值初始化int ia[3][4] = {0, 3, 6, 9};
- 指针和多维数组
时刻记住,多维数组实际上是数组的数组。
int ia[3][4];int (*p)[4] = ia; // p 指向第一行的数组p = &ia[2]; // p 指向ia的末尾行 // 值得注意的是,p是一个指向有四个整数的数组的指针,而数组ia就是一个指针,因此p是一个指针的指针// 比如要找ia[1][1]*(*(ia + 1) + 1);*(ia[1] + 1);*(&ia[0][0] + 4 * 1 + 1);a // 等价于a[0],保存的是指向第一行的数组的指针, 也就是a[0][0]a + 1 // 等价于a[1], 保存的是指向第二行的数组的指针, 也就是a[1][0]
- 可以使用typedef和using简化多维数组的指针
using int_array = int[4];typedef int int_array[4];
- 字符串、向量和数组---C++ 基础
- c++primer要点-字符串、向量和数组
- 字符串、向量和数组
- C++ 基础(三) —— 字符串、向量和数组
- 《c++primer》笔记 第3章 字符串、向量和数组
- Java数组、向量和字符串
- 三、字符串、向量和数组
- C++字符串向量和数组
- 待续:字符串、向量和数组
- ch3 字符串、向量和数组
- 3-字符串向量和数组
- Chapter3 字符串、向量和数组
- S03字符串、向量和数组
- C语言基础—数组和字符串
- 第3章 字符串、向量和数组
- 第三章 字符串、向量和数组
- 第三章 字符串、向量和数组
- c++11(2):字符串、向量和数组
- qduoj LC and Prime&&hdu 5104(线性筛)
- HDU3306
- Emacs Error: Invalid function: org-babel-header-args-safe-fn
- java用户登陆窗口
- [STL]IP and QQ (eden)
- 字符串、向量和数组---C++ 基础
- qwb与李主席 状压+二分
- 简单介绍android中什么叫i18n 和L10n
- 使用VAO VBO绘制图形
- 汇编语言 实验12 编写0号中断的处理程序
- 利用网线在两台电脑之间传输文件
- 用SQL Server编写一个存储过程
- 菜鸟学php扩展 之 实战如何在扩展里调第三方函数(标准库/原生/自己写的)(六)
- HDU1002