一、string为什么使用模板
string 是 typedef 后的模板,也就相当于是这样:
template<class T>
class basic_string
{
public:
//...
private:
T* _str;
// ...
};
// typedef basic_string<char> string;
int main()
{
string s("hello world");
return 0;
}
那 string 不就是字符串,管理字符不就是 char类型吗 ?为什么使用模板?因为编码问题
计算机是 USA 发明的,一开始对于计算机只需要显示英文就可以,编码简单,因为表示简单;通过计算机编码,将数据翻译为二进制序列,将其组合,一个字节表示一个 char ,将英文和符号进行一个映射,通过建立映射关系(编码表)完成编码。例如 ascii编码表 – 表示英文字符
字符根据 ascii 码表中的 ascii 值,以二进制存储在计算机内的就是对应的数值,根据这些,就可以表示出英文。
例如 “helllo world” 存储在内存中就是每个字符的 ascii 表对应的数组
早期计算机使用的是ASCII编码,它只能表示英文字符和一些基本的符号,无法表示其他语言的字符。为了解决这个问题,Unicode被提出并逐渐流行起来。
Unicode是一个用于字符编码的标准,它为全球大部分字符(包括字母、数字、标点符号、符号、汉字等)分配了一个唯一的数字码点。这个码点可以被转换为不同的编码方式,比如UTF-8、UTF-16、UTF-32等。
UTF-8是一种对Unicode进行编码的可变长度字符编码方案。它使用1到4个字节来表示不同的字符,其中常见的字符(如英文字母、数字、常用符号)只需要1个字节,而较少使用的字符(如中文、日文、德文等)可能需要多个字节。这样可以节省存储空间并且兼容ASCII编码,因为所有ASCII字符的UTF-8编码与ASCII编码完全相同。
总结起来,Unicode是一个全球性的字符编码标准,它可以表示世界各国的字符;而UTF-8是Unicode的一种编码方式,它通过可变长度的方案来节省存储空间并实现兼容性。在计算机应用中,UTF-8成为了最常用的字符编码方式之一。
比如:“开往屯街团的列车即将到站…”
两个字节存储一个中文字符,根据编码表查阅字符。
编译器中也可以更改编码方式:
如果编码对应不上就是所谓的乱码。
中文自己量身定做的编码表 gbk ,windows 下默认 gbk ,linux 下 utf-8,例如 GB2312 就是 gbk .
二、string的用法
1. 字符串的表示方式:
在C++中,字符串可以通过以下几种方式来表示:
- C-Style字符串:使用字符数组来表示,以空字符(‘\0’)结尾。例如:
char str[] = "Hello";
std::string
类:使用std::string
类对象来表示,这是C++标准库提供的字符串类。例如:std::string str = "Hello";
2. 字符串的基本操作:
- 字符串连接:可以使用加号(+)操作符或
append()
函数将两个字符串连接起来。
string str1 = "Hello";
string str2 = " World";
string result1 = str1 + str2; // 使用加号操作符
string result2 = str1.append(str2); // 使用append()函数
- 字符串下标访问:string重载了[ ],可以直接用[ ]访问
string s="abdef";
for(int i=0;i<s.size();i++)
{
s[i]='a';
}
- 字符串长度:可以使用
length()
成员函数或size()
成员函数获取字符串的长度。
std::string str = "Hello, World!";
int length = str.length(); // 或者使用 str.size();
- 字符串比较:可以使用
compare()
函数或==
操作符来比较两个字符串是否相等。
string str1 = "Hello";
string str2 = "World";
int result1 = str1.compare(str2); // 比较字符串的大小,结果为负数、零或正数
bool result2 = (str1 == str2); // 判断两个字符串是否相等
-
字符串子串:可以使用
substr()
函数获取原字符串的子串。std::string str = "Hello, World!"; std::string subStr = str.substr(7, 5); // 获取从下标为7开始的5个字符,即"World"
-
字符串查找和替换:可以使用
find()
函数在字符串中查找指定的子串,并使用replace()
函数将指定的子串替换为新的字符串。
string str = "Hello, World!";
size_t foundIndex = str.find("World"); // 查找子串"World"的位置
string replacedStr = str.replace(foundIndex, 5, "Universe"); // 将子串替换为"Universe"
- 字符串的追加
string s = "hello ";
s += "world";
s.append(" hello");
s.push_back('!');
- 字符串插入和删除:可以使用
insert()
函数在指定位置插入新字符或字符串,使用erase()
函数删除指定位置的字符或一段字符。
string str = "Hello";
str.insert(5, ", World"); // 在第5个字符后插入", World"
str.erase(5, 6); // 删除从第5个字符开始的6个字符
- 字符的查询:从指定位置pos开始查找字符串str,并返回第一次出现的位置
string s="abcda";
s.find(0,'a');
- 字符串转换:可以使用
std::to_string()
函数将数值类型转换为字符串,也可以使用std::stoi()
、std::stof()
等函数将字符串转换为数值类型。
- 字符串指针:返回以null结尾的C风格字符串(const char*)
string s="123456";
const char* s.c_str();
int num = 123;
string strNum = std::to_string(num);
std::string str = "3.14";
float floatNum = std::stof(str);
- 字符串迭代器:可以使用字符串的迭代器遍历字符串中的每个字符。
string str = "Hello";
for (auto it = str.begin(); it != str.end(); ++it) {
char ch = *it; // 获取当前字符
3. 输入空格不换行
- C语言当中scanf默认是读取到空格之前的和回车之前的内容
- 但是可以使用如下来读取一行内容
scanf("%[^\n]", str);
- C++当中的cin也是默认是读取到空格之前的和回车之前的内容
*但是可以使用如下来读取一行内容
getline(cin, str);
三、总结+练习OJ
string 非常方便,提供了丰富的操作和功能
class Solution {
public:
string addStrings(string& num1, string& num2) {
string sum;
int r = 0;
int alen = num1.length();
int blen = num2.length();
int k = 0;
for (int i = alen - 1, j = blen - 1; i >= 0 || j >= 0; i--, j--)
{
if (i >= 0)
r += num1[i] - '0';
if (j >= 0)
r += num2[j] - '0';
sum.push_back('0' + (r % 10));
r /= 10;
}
if (r > 0)
sum.push_back('0' + 1);
reverse(sum.begin(), sum.end());
return sum;
}
string multiply(string num1, string num2) {
if (num1 == "0" || num2 == "0")
return "0";
int r = 0;
string ret;
int max = num1.length();
int min = num2.length();
string Max = num1;
string Min = num2;
if (max < min)
{
swap(max, min);
Max.swap(Min);
}
for (int i = min - 1; i >= 0; i--)
{
string mul;
for (int k = min - 1 - i; k > 0; k--)
mul.push_back('0');
for (int j = max - 1; j >= 0||r; j--)
{
if (j >= 0)
r += (Max[j] - '0') * (Min[i] - '0');
mul.push_back('0' + r % 10);
r /= 10;
}
reverse(mul.begin(), mul.end());
ret = addStrings(ret, mul);
}
return ret;
}
};
- 主要思路就是一位一位相乘,并且需要进位,然后再相加每一位相乘的结果