跳转至

一维

字符串可以用 string 表示,也可以用一维字符数组表示。

前者是 C++ 风格的字符串,后者是 C 风格的字符串。

用 string 表示字符串

在标准模板库 STL 中,建立了有关字符串操作的 string 类。

定义

string s;

初始化

string s; // 默认是空串,即"", 一个双引号,中间什么都没有,空串
string s = "zq";

输入输出

int main() {
    string s;
    cin >> s;

    cout << s;

    return 0;
}

访问

s[0] 访问第0位字符
s[i] 访问第i位字符

遍历

for (int i = 0, len = s.size(); i < len; i++) 
    cout << s[i];

// 这个地方,要把s.size()提到len中使用,
// 而不是放在 i < s.size()
// 因为.size()函数是有执行时间的,多次调用,会因此超时
for (auto c : s) cout << c;

// 这是C++11的写法,auto 表示自动识别变量类型

用 string 的基础操作

赋值

// 赋值操作、复制操作
s1 = s; 

拼接

// 拼接
s += "def";       // 拼接字符串
s += 'g';         // 拼接字符

判断相等

// 判断相等
if (s == "zq")    // 判断是否相等
if (s < "ab")     // 按字典序比大小关系

截取子串

// 截取子串
cout << s.substr(1, 2);  // 从下标为1那个位置,截取长度为2的子串
cout << s.substr(1);     // 从下标为1那个位置,截取右边的所有内容

插入子串

// 插入子串
s.insert(1, "xxx");      // 在下标为1那个位置,插入一个字符串"xxx" 

替换子串

// 替换子串
s.replace(1, 2, "xxx");  // 将从下标1开始,长度为2的子串,替换为"xxx"

翻转字符串

// 翻转字符串
reverse(s.begin(), s.end());

.find() 查找函数

// 查找子串、查找字符,返回第一次出现的位置,不存在返回 string::npos(一般理解为-1)
// 常用于判断一个字符串是否为另一个字符串的子串
s.find("zq");    // 查找子串zq第一次出现的位置
s.find('q');     // 查找字符q第一次出现的位置
if (s.find("zq") == string::npos) cout << "Not find"; // 如果没找到

s.find("zq", p); // 从下标p那个位置往后找"zq"第一次出现的位置

.find() 函数,向后找一个,替换一个

// 这个操作通常用来向右,找到一个替换一个,循环迭代向右替换
// 直到都替换完了,结束
string s = "zqoizqoizqoizqoizqoizqoizqoi";
int p = 0;
while (s.find("zq", p) != string::npos) {
    p = s.find("zq", p);
    s.replace(p, 2, "NB");
}
cout << s;
String的长度和占用存储空间的问题

从下面三个实例中,我们可以得到这样的结论:

.size() 表示字符串的长度,sizeof 表示占用存储空间都是 32 字节。

image-202509121606161 23

image-20250912160637175

image-20250912160755894

用一维字符数组表示字符串

定义

char s[110]; 

初始化

char s[110] = {'z', 'q'};
char s[110] = "zq";

这两种初始化的方法,存储到字符数组中的格式是完全一致的。

下面是数组中的存储内容

s[0] = 'z'
s[1] = 'q'
s[2] = '\0'

字符数组存入相应的字符后,自动在末尾添加一个特殊字符 '\0',作为字符串的结束标记。

'\0' 对应的 ASCII 码为 0。

输入输出

使用 cin, cout

char s[110];

int main() {
    cin >> s;
    cout << s;

    return 0;
}

使用 scanf(), printf()

char s[110];

int main() {
    scanf("%s", s);
    printf("%s", s);

    return 0;
}

访问

s[0] 访问第0位字符
s[i] 访问第i位字符

遍历

for (int i = 0, len = strlen(s); i < len; i++) 
    cout << s[i];

用一维字符数组的基本操作

长度

int len = strlen(s); // 获取字符串的长度

判断相等

int p = strcmp(s1, s2); // 判断 s1, s2 是否相等。相等是 0,小于是负数,大于是正数

拼接

strcat(s1, s2); // s1 后面拼接上 s2

复制

strcpy(s1, s2); // s2 复制给 s1,s1 存的东西变成和 s2 一样
memcpy(s1, s2, sizeof s1); // 把 s2 的值赋值给 s1
Strcpy与memcpy的区别

strcpy 是“拷贝字符串”用的,memcpy 是“拷贝内存块”用的。

strcpy

  • 必须依赖 '\0'
  • 遇到 '\0' 才停止

memcpy

  • 完全不依赖 '\0'
  • 你让它拷多少字节,它就拷多少字节

关于以 '\0' 结尾的讨论

从下面两个计算机实验中,我们可以得到这样的结论:

\0 不占字符串的长度,但占用字符串的存储空间。

image-20250912154541600

image-20250912154629178