一、数组
- 序列容器概念
- 代表内存里一组连续的同类型存储区
- 可以用来把多个存储区合并成一个整体
- 数组定义:
int arr[10] = {1,2,3,4,5,6,7,8};
,注意数组里元素个数是不可以改变的 - 数组的访问
#include <iostream>
using namespace std;
int main(void)
{
// 数组访问
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0, 0 };
// 推荐方式
for (int index = 0; index < 10; ++index)
cout << a[index] << " ";
cout << endl;
// 不推荐方式
for (int index = 0; index <= 9; ++index)
cout << a[index] << " ";
}
- 数组的查找
#include <iostream>
using namespace std;
int main(void)
{
// 数组的查找
int a[] = { 1, 2, 3, 4 };
int len = sizeof(a) / sizeof(a[0]);//得到数组容量
for (int index = 0; index < len; ++index)
{
if (a[index] == 3)
{
cout << index << endl;
return 0;
}
}
}
- 二维数组
- 将最长的循环放在最内层,最短的循环放在最外层,这样效率更高,减少CPU跨层循环的次数
#include <iostream>
using namespace std;
int main(void)
{
//二维数组的访问:
int a[2][4] = { { 1, 2, 3, 4 },{ 5,6,7,8 } };
for (int row = 0; row < 2; ++row)
{
for (int col = 0; col < 4; ++col)
{
cout << a[row][col] << " ";
}
cout << endl;
}
}
二、vector
- vector的特点:面向对象、动态数组(动态扩容)
- vector头文件:
#include <iostream>
- vector的使用
- capacity():容量
- size():大小
- begin()、end():起始索引位置、结束索引位置
- push_back:尾部插入元素
- pop_back:尾部移除元素
- insert:任意位置插入元素
- erase:任意位置移除元素
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// 创建动态数组vector
vector<int> vec = { 1,2,3,4 };
cout << "size is " << vec.size() << endl;
cout << "capacity is " << vec.capacity() << endl;
// 遍历所有元素
for (int index = 0; index < vec.size(); ++index)
{
cout << vec[index] << endl;
}
// 在尾部插入一个元素5
vec.push_back(5);
cout << "size is " << vec.size() << endl;
cout << "capacity is " << vec.capacity() << endl;
// 遍历所有元素
for (int index = 0; index < vec.size(); ++index)
{
cout << vec[index] << endl;
}
// 在中间插入一个元素6
vec.insert(--vec.end(), 6);
cout << "size is " << vec.size() << endl;
cout << "capacity is " << vec.capacity() << endl;
// 遍历所有元素
for (int index = 0; index < vec.size(); ++index)
{
cout << vec[index] << endl;
}
// 在尾部移除一个元素
vec.pop_back();
cout << "size is " << vec.size() << endl;
cout << "capacity is " << vec.capacity() << endl;
// 遍历所有元素
for (int index = 0; index < vec.size(); ++index)
{
cout << vec[index] << endl;
}
// 在任意位置移除一个元素
vec.erase(vec.end() - 2);
cout << "size is " << vec.size() << endl;
cout << "capacity is " << vec.capacity() << endl;
// 遍历所有元素
for (int index = 0; index < vec.size(); ++index)
{
cout << vec[index] << endl;
}
return 0;
}
三、字符串简介
- 字符串变量
- 字符串是以空字符(‘\0’)结束的字符数组
- 空字符(‘\0’)自动添加到字符串内部表示中
- 在声明字符串变量时,应该为这个空结束符预留一个额外元素的空间;
- 如:
char strHelloWorld[11] = {"helloworld"};
; - 更简单的方法就是不指定具体长度
char strHelloWorld[] = {"helloworld"};
- 如:
- 字符串常量
- 字符串常量是一对双引号括起来的字符序列
- 字符串中每个字符作为一个数组元素存储
- 例如字符串"helloworld"
- 字符0, ‘\0’, '0’的区别
char c1 = 0;
:0x00char c2 = '\0';
:0x00char c3 = '0';
:0x30
四、Unicode编码
- Unicode编码的目的:为了把世界上的文字都映射到一套字符空间中
- Unicode字符集三种编码方式
- UTF-8:1byte表示1个字符,可以兼容ASCII码;特点是存储效率高,变长(不方便内部随机访问),无字节序问题(可以作为外部编码)
- UTF-16:2byte表示1个字符,分为UTF-16BE(big endian)、UTF-16LE(little endian);特点是定长(方便内部随机访问),有字节序问题(不可以作为外部编码)
- UTF-32:4byte表示1个字符,分为UTF-32BE(big endian)、UTF-32LE(little endian);特点是定长(方便内部随机访问),有字节序问题(不可以作为外部编码)
- Windows平台的BOM:Windows的文件可能有BOM(byte order mark),就是处理字节序问题的;如要在其他平台使用,可以去掉BOM;实际这是微软平台的画蛇添足,因为UTF-8并没有字节序问题
- notpad++的编码
五、字符串的指针表示
- 指针表示法:
char* pStrHelloWrold = "helloworld";
- char[]和char*的区别:
- strHelloWorld不可变,strHelloWorld[index]的值可变
- pStrHelloWrold 可变,但是pStrHelloWrold[index]的值是否可变取决于所指区间的存储区域是否可变;当前所指的区域的字符串常量,不可变,所以编译器报错“表达式必须是可修改的左值”
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// 定义一个数组
char strHelloWorld[11] = { "helloworld" };
const char* pStrHelloWrold = "helloworld";
for (int index = 0; index < strlen(strHelloWorld); ++index)
{
strHelloWorld[index] += 1;
cout << strHelloWorld[index] << endl;
}
for (int index = 0; index < strlen(strHelloWorld); ++index)
{
pStrHelloWrold[index] += 1; // 报错,表达式必须是可修改的左值
cout << pStrHelloWrold[index] << endl;
}
return 0;
}
六、字符串的基本操作
- 字符串长度strlen(s):返回字符串s的长度,注意不包含’\0’的长度
#include <iostream>
using namespace std;
int main()
{
// 定义一个数组
char strHelloWorld[11] = { "helloworld" };
cout << strlen(strHelloWorld) << endl; // 10
cout << sizeof(strHelloWorld) << endl; // 11
return 0;
}
- 字符串比较strcmp(s1,s2):两个字符串自左向右逐个字符相比(按ASCII值大小比较),直到出现不同的字符或遇到’\0’为止
- 如果s1和s2是相同的,则返回0
- 如果s1 < s2 则返回值小于0
- 如果s1 > s2 则返回值大于0
#include <iostream>
using namespace std;
int main()
{
// 定义一个数组
char strHelloWorld1[] = { "helloworld" };
char strHelloWorld2[] = { "helloworld" };
char strHelloWorld3[] = { "hflloworld" };
char strHelloWorld4[] = { "hdlloworld" };
cout << strcmp(strHelloWorld1, strHelloWorld2) << endl; // 0
cout << strcmp(strHelloWorld1, strHelloWorld3) << endl; // -1
cout << strcmp(strHelloWorld1, strHelloWorld4) << endl; // 1
return 0;
}
- 字符串拷贝strcpy(s1,s2):复制字符串s2到字符串s1,s1的空间需要保证能够容纳
- 复制指定长度字符串strncpy(s1,s2,n):将字符串s2中的前n个字符拷贝到s1中,s1的空间需要保证能够容纳
- 字符串拼接strcat(s1,s2):将字符串s2接到s1后面,s1的空间需要保证能够容纳
- 查找字符串strchr(s1,ch):指向字符串s1中字符ch的第一次出现的位置
- 查找字符串strchr(s1,s2):指向字符串s1中字符串s2的第一次出现的位置
注意:请使用strnlen_s,strcpy_s,strncpy_s,strcat_s等API函数,更安全
- 非安全版本示例
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
const unsigned int MAX_LEN_NUM = 16;
int main()
{
char strHelloWorld1[] = { "hello" };
char strHelloWorld2[] = { "world1" };
char strHelloWorld3[MAX_LEN_NUM] = { 0 };
strcpy(strHelloWorld3, strHelloWorld1); // hello
strncpy(strHelloWorld3, strHelloWorld2, 2);// wollo
strcat(strHelloWorld3, strHelloWorld2); //wolloworld1
unsigned int len = strlen(strHelloWorld3);
for (unsigned int index = 0; index < len; ++index)
{
cout << strHelloWorld3[index] << " ";
}
cout << endl;
return 0;
}
- 安全版本示例
#include <iostream>
using namespace std;
const unsigned int MAX_LEN_NUM = 16;
const unsigned int STR_LEN_NUM = 7;
const unsigned int NUM_TO_COPY = 2;
int main()
{
char strHelloWorld1[] = { "hello" };
char strHelloWorld2[STR_LEN_NUM] = { "world1" };
char strHelloWorld3[MAX_LEN_NUM] = { 0 };
strcpy_s(strHelloWorld3, MAX_LEN_NUM, strHelloWorld1); // hello
strncpy_s(strHelloWorld3, MAX_LEN_NUM, strHelloWorld2, NUM_TO_COPY);// wollo
strcat_s(strHelloWorld3, MAX_LEN_NUM, strHelloWorld2); //wolloworld1
unsigned int len = strlen(strHelloWorld3);
for (unsigned int index = 0; index < len; ++index)
{
cout << strHelloWorld3[index] << " ";
}
cout << endl;
// 小心缓冲区溢出
strcat_s(strHelloWorld2, STR_LEN_NUM, "Welcome to C++");
return 0;
}
七、string简介
string使用起来比原始的C风格方法更安全和方便,对性能要求不是特别高的可以使用
所以如果我们对性能要求比较高,还是建议使用C风格的字符串比较好
- string介绍:C++标准库中提供了string类型专门表示字符串
#include <string>
- string的优点:使用string可以更为方便和安全的管理字符串
- 字符串变量的定义
string s;
:定义空字符串string s = "helloworld";
:定义并初始化string s("helloworld");
string s = string("helloworld");
- 获取字符串长度
cout << s1.length() << endl;
cout << s1.size() << endl;
cout << s1.capacity() << endl;
- 字符串比较:==、!=、>、>=、<、<=
string s1 = "hello",s2 = "world";
cout << (s1 == s2) << endl;
cout << (s1 != s2) << endl;
#include <iostream>
#include<string>
using namespace std;
int main()
{
// 字符串定义
string s1;//定义空字符串
string s2 = "helloworld";//定义并初始化
string s3("helloworld");
string s4 = string("helloworld");
// 获取字符串长度
cout << s1.length() << endl;// 0
cout << s1.size() << endl;// 0
cout << s1.capacity() << endl;// 15
// 字符串比较
s1 = "hello", s2 = "world";
cout << (s1 == s2) << endl;// 0
cout << (s1 != s2) << endl;// 1
return 0;
}
- string转换为C风格字符串:
const char* c_str1 = s1.c_str();
- string随机访问某个字符:
s[0] = "h";
- string拷贝:
s1 = s2;'
- string连接:直接使用+,+=
#include <iostream>
#include<string>
using namespace std;
int main()
{
// 字符串定义
string s1;//定义空字符串
string s2 = "helloworld";//定义并初始化
string s3("helloworld");
// 字符串比较
s1 = "hello", s2 = "world";
cout << (s1 == s2) << endl;
cout << (s1 != s2) << endl;
// 转换成C风格的字符串
const char* c_str1 = s1.c_str();
cout << "The C-style string c_str1 is: " << c_str1 << endl;
// 随机访问
for (unsigned int index = 0; index < s1.length(); ++index)
{
cout << c_str1[index] << " ";
}
cout << endl;
for (unsigned int index = 0; index < s1.length(); ++index)
{
cout << s1[index] << " ";
}
cout << endl;
// 字符串拷贝
s1 = "helloworld";
s2 = s1;
// 字符串连接
s1 = "helllo", s2 = "world";
s3 = s1 + s2; //s3: helloworld
s1 += s2; //s1: helloworld
return 0;
}