字符串的存储方式
在程序中想要存储字符串,需要知道字符串从什么地方开始,到什么地方结束。也就是我们需要知道字符串的长度。
因此,存储字符串有两种方式,一种是设置一个结束标志,从开始一直往后寻找,等到寻找到结束标志的时候,则字符串结束。
另外一种存储字符串的方式,是在存储字符串的同时,用一个值去记录字符串的大小,也即是记录从开始到哪里字符串结束。
C风格字符串
c风格的字符串来源于c语言,在c++中仍然保留了,但是并不建议使用。c风格字符串也即是按照第一种方式进行的字符存储,通过寻找结束标志\0,来确定字符串何时结束。
老式的c风格字符串存储于字符数组之中,一般通过char *类型的指针操纵。如果要完成一些字符串的基础操作,则必须要依靠标准库中的一些函数(这部分的内容最早是c库提供的),而且需要引入<cstring>的头文件。
常用函数
int strlen(const char *); // 计算长度
int strcmp(const char *, const char *); // 比较是否相同
char * strcpy(char *, const char *); // 复制第二个字符串到第一个字符串中
1,使用strlen计算长度
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
const char * str1 = "欢迎收看c++教程";
const char * str2 = "作者是程程之光";
cout << "str1: " << strlen(str1) << endl;
cout << "str2: " << strlen(str2) << endl;
}
此时,两个语句输出的结果均为21,原因是,1个中文字,是按照3个字符来计算的。所以最终就变成了这个奇怪的结果。
也就是说,使用strlen根本就没有办法正确的统计中文字,那怎么办呢?此时,就需要用到我们之前提到的宽字符了,也就是wchar_t
#include <iostream>
#include <cwchar> // wcslen()函数放置于cwchar头文件中
using namespace std;
int main()
{
// 注意:使用cout无法直接输出wchar_t类型
const wchar_t * str1 = L"欢迎收看c++教程";
const wchar_t * str2 = L"作者是程程之光";
// 使用wcslen函数,就可以正确的统计文字个数了
cout << "str1: " << wcslen(str1) << endl;
cout << "str2: " << wcslen(str2) << endl;
}
2,使用strcmp比较
如果结果为负,说明第一个字符串小于第二个字符串
如果结果为0,说明两个字符串相等
如果结果为正,说明第二个字符串大于第一个字符串
注:此处的大于小于是指在字典序中,出现的先后顺序
注意:c风格的字符串比较大小的时候,不能使用==,必须要使用strcmp
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
const char * str1 = "欢迎收看c++教程";
const char * str2 = "作者是程程之光";
cout << strcmp(str1, str2) << endl;
cout << strcmp(str2, "作者是程程之光") << endl;
// 注意:如果你不用strcmp,非要直接通过==进行比较
// 由于编译器的优化的缘故,可能确实是可以正常运行的
// 但是,这种行为是不可行的,一定要改为使用strcmp
cout << (str2 == "作者是程程之光") << endl;
}
3,使用strcpy拷贝字符串
注意:c风格字符串的拷贝,不可以直接使用=赋值运算符,必须要使用strcpy
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char str1[] = {'1', '2', '3', '4', '5', '6', '7', '\0'};
const char * str2 = "c++";
cout << "str1: " << str1 << endl;
strcpy(str1, str2);
cout << "str1: " << str1 << endl;
}
补充:c风格的字符串,也可以写成字符数组的形式,如果你还不知道什么是数组,可以跳过这段,或者学习数组类型。
#include <iostream>
using namespace std;
int main()
{
// 没有为c风格字符串设置结束符,这种行为是不可以的
// const char a[3] = {'c', '+', '+'};
// 需要像这样为c风格字符串设置结束符
// 声明字符数组个数的时候,也至少要比你需要保存的字符数多加1
const char a[4] = {'c', '+', '+', '\0'};
cout << a << endl;
}
string字符串
因为这个c风格的字符串不好用,因此,c++提供的字符串,包含在了<string>之中,使用前需要#include <string>
常用的方法
1,通过.size()可以获取字符串的长度。
2,通过.empty()可以查看字符串是否为空。
3,通过=可以直接赋值。
4,通过==可以比较是否相等。
5,通过+可以拼接字符串。
注:原本还有<=,!=,>=等运算符,但在c++20中取消了,改为使用三路运算符<=>代替了。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1 = "程程之光";
string str2;
// 计算字符串长度
cout << "str1的长度: " << str1.size() << endl;
// 判断字符串是否为空
cout << "str1是否为空: " << str1.empty() << endl;
cout << "str2是否为空: " << str2.empty() << endl;
// 赋值
str2 = str1;
cout << "str2: " << str2 << endl;
// 比较是否相等
cout << "str1和str2是否相等: " << (str1 == str2) << endl;
// 拼接字符串
cout << "我是" + str1 << endl;
}
注:通过.size()计算字符长度的时候,仍然按照1个中文字3个字符来算的。
c字符串与string字符串的转换
1,如果你有一个老式c风格字符串,你需要把它变成string字符串,那么直接通过赋值即可。
#include <iostream>
#include <string>
using namespace std;
int main()
{
const char * c_str = "这是一个字符串";
string cpp_str = c_str;
cout << cpp_str << endl;
}
2,如果你有一个string的字符串,你需要把它变为c风格的字符串,则不能直接赋值,需要使用c_str()。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string cpp_str = "这是一个字符串";
// 直接赋值是不可以的
// const char * c_str = cpp_str;
// 需要使用c_str()
const char * c_str = cpp_str.c_str();
cout << c_str << endl;
}
字符串与数字之间的相互转换
不熟悉c++的人使用c++的一个困难在于,有的时候一些很简单的功能,却不知道被放置在了哪里。字符串与数字之间的转换也是这样,方法有很多种,转换函数也在很多地方上都有出现。为了简化操作,c++11以后,将全部的转换函数都在string中放置了一份,因此,直接使用string中定义的函数进行类型转换即可。
数字转字符串
to_string()
字符串转数字
stoi() string to int
stol() string to long
stoll() string to long long
stof() string to float
stod() string to double
stold() string to long double
因此,现在进行字符串与数字之间的相互转换,使用string中的函数即可,当然如果你习惯于使用其他的方法,比如使用cstdlib中定义的函数,自然也是可以的。