一、编码的基础介绍
编码:是信息从一种形式或格式转换为另一种形式的过程。
ASCLL 编码表:主要表示的是英文的编码表
Unicode:是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码二进制编码二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求
GBK:可以说是为中文量身定做的一种编码
二、String 类的介绍
在C 语言中,字符串是以 '\0' 结尾的一些字符的集合,为了操作方便, C 标准库中提供了一些 str 系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP(即面向对象程序设计 )的思想,而且底层空间需要用户自己管理,稍不留神可 能还会越界访问。而在C++中的string是表示字符串的字符串类,该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;并且不能操作多字节或者变长字符的序列。String类可以管理字符串,大大减少了人工管理所存在的问题。
但需要注意的是:在使用string类时,必须包含#include头文件以及using namespace std;
三、string类的常用接口
3.1 构造函数
String类的构造函数有7个,主要是以下三个,分别是默认构造,拷贝构造以及带参的构造
“首先cin的输入有一个特点,在遇到‘ ’(空格)或换行时,会结束输入,因为cin以空格和换行为间隔,区分前后的输入,而cin.get()则将‘ ’也作为了一个字符放到输入里。”
然而上面的三个构造函数是非常重要的,需要着重掌握,其次我们也可以了解一下
这个构造函数的作用是用str对象从第pos个位置开始npos个长度去构造新的对象
其中npos为缺省值,默认为-1,又因为是size_t类型,所以是整形的最大值,即表示如果你没有给长度的时候,会使用这个缺省值,又因为size_t类型,所以从第pos位置开始有多少拷贝多少
npos是静态成员变量也是size_t类型,即表示整形的最大值
作用:拷贝s的前三个字符
需要与上面
区别的是:一个是const char* 指针,一个是const string& str对象
作用:用n个c字符去初始化
3.2 析构函数
系统会自动调用析构函数
3.3 string 的容量操作
size 用于返回字符串有效字符长度,不包含'\0',作为下标是最后一个数据的下一个位置
length 用于返回字符串有效字符长度,不包含'\0'
max_size 返回字符串最大长度
capacity 返回空间的分配大小
clear 清理空间数据
empty 检测字符串释放为空串,是返回true,否则返回false
3.4 string类对象的访问及遍历操作
遍历string方式一 : char&返回不是为了减少拷贝,是为了支持修改返回对象,返回的是pos位置的字符的引用,
即可以对pos位置的值进行修改
遍历string 方式2 :迭代器 可以把it理解成指针
方式3:范围for:每次自动识别每个字符赋值给e,自动往后迭代,自动判断结束
可读可写:
迭代器:
对于string,[ ]+下标的方式已经很好来访问和修改了,为什么还要用正向迭代器和反向迭代器呢?
对于string,下标和[ ]是足够好用,可以不同迭代器,但是对于其他的容器呢?
所以使用迭代器的原因是所有的容器都可以用迭代器去访问和修改。
除了3.4第二种方式里面使用的正向迭代器外还有反向迭代器
带有const 的正向和反向迭代器
at 与operator[]的作用差不多,但是他们的区别在于当发生错误的时候,at是进行抛异常,operator[]是进行断言
back : 用于返回字符串尾上的字符
front:用于返回字符串头上的字符
3.5 string类对象的修改操作
push_back 在字符串后尾插字符 cappend 在字符串后追加一个字符串operator+= ( 重点 ) 在字符串后追加字符串 str(可以直接适用上面俩个情况,推荐)
牛刀小试:
力扣https://leetcode.cn/problems/reverse-only-letters/
思路:与快排相似,设置头和尾的俩个下标,头和尾下标都是字母则进行交换,如果有一个不是则再while循环中进行寻找,直到是字母,然后再进行交换,然后继续迭代
运行今日学习的方方:比如string类中的swap模板,size等等
class Solution {
public:
string reverseOnlyLetters(string s)
{
int begin = 0;
int end = s.size()-1;
while(begin < end)
{
//如果不是字母就跳过,都是字母就交换,如果一直都不是字母呢?不就一直++了吗,所以也要进行begin<end判断
while(begin < end && !isalpha(s[begin]))
{
begin++;//直到找到是字母,然后交换
}
while(begin < end && !isalpha(s[end]))
{
end--;
}
//交换
swap(s[begin],s[end]);
//交换之后继续迭代
++begin;
--end;
}
return s;
}
};
力扣https://leetcode.cn/problems/first-unique-character-in-a-string/submissions/
思路:相当于计数排序,用数组的方式,时间复杂度为o(n)
因为只有26个小写字母,可以设置大小为26的整形数组(因为里面存放的是每个字母出现的次数),对字符串中的字母进行统计,从'a'为0下标开始,依次将每个字母出现的次数放在对应的下标下,然后再对字符串进行遍历即对应带对应的数组里面的次数,出现第一次次数为1的即为不重复的字母,返回它的下标,否则返回-1
class Solution {
public:
int firstUniqChar(string s)
{
//用数组的方式,相似与计数排序
int array[26] = {0};//因为只有小写字母
for(int i = 0; i < s.size();i++)
{
array[s[i] - 'a']++;//从a为0下标开始,依次对应的字母次数放在对应的下标下
}
for( int j= 0; j< s.size();j++)
{
if(array[s[j] - 'a'] == 1)//s[j]-'a'是按照字符串中的顺序,先出现1的就是不重复的
{
return j;
}
}
return -1;
}
};
利用reserve(直接开好空间)提高插入数据的效率,避免增容带来的开销 :
reserve和resize的区别
reverse和resize,如果string s1("hello world");s1有元素,那么都相当于扩容
resize如果申请的个数比s1里面的数少,那么会多余的数会删除
c_str:返回C格式字符串
查找:
find: size_type find (charT c, size_type pos = 0) const;
查找什么字符,从pos开始找,默认pos下标为0,从左往右找第一次出现的
如果想找最后一次出现的后缀,则可以从右往左找,rfind
size_type rfind (charT c, size_type pos = npos) const;取url中的各个段
插入
删除
牛刀小试:
字符串最后一个单词的长度_牛客题霸_牛客网
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1;
//因为cin遇到空格和换行结束,所以获取整个字符串的方式一:
char ch = cin.get();//每次获取一个字符
while(ch != '\n')//整个字符串以换行结束
{
s1 += ch;
ch = cin.get();
}
//方式二:
getline(cin,s1);//cin的字符串放到s1中去
size_t pos = s1.rfind(' ');//从后往前找,最后一个单词
if(pos == string::npos)
{
cout << s1.size()<< endl;
}
else
{
size_t length = s1.size() - (pos+1);
cout << length << endl;
}
return 0;
}
string的比较重载函数: