感言

自认为不是一个努力的人……虽然这些20年在b站看过黑马的教程,甚至当时在本地也写过md的文件哈哈哈哈但是一段时间不用又落下了许多,也好在没有忘得一干二净吧……看到都能想起来,只是一些内置的方法会记不太清。回看也是两天看一点看一点,加上看视频又得自己做,然后顺便写在博客上,进度确实会慢一些。
而且数据结构这一门快打工了也还没掌握……还是很惭愧的,后面要尽量补齐了。


前言

也回顾了string的一些方法,然后小结一下string


正文

字符串之中除了指针,编码是一个无时不刻不会头疼的问题。
字符从存储:由表面的字符到计算机上的编码表,再到底层转换成二进制
读取字符串的顺序是存储的逆向顺序。

常见的编码表:utf-8、utf-16、GBK、ASCII等


自制能统计带中文的字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
void tjsp(char *ch){
int n = 0;
while (*ch++ != '\0'){
if (*ch < 0){
n++;
*ch++;
}
else{
n++;
}
}
std::cout << n << std::endl;
}

这是之前string回顾的时候做的一个小题目,因为gbk的情况下,中文占用两个字节,所以判断起来不一样。
代码目前不重要,重要的是一点,为什么要*ch < 0

1字节的范围是-128 - 127,如果是无符号就是0-255。
那么现在没有指定是无符号,所以按照-128 - 127算。
而ascii码的范围就是0-127,超过的就代表不是英文字符,且现在是有符号类型,所以是判断这个字符是不是< 0,如果小于0就说明这个字符是中文;如果是无符号类型,就是判断这个字符是不是> 127,如果大于127就说明这个字符是中文。

比如说d5 c5是中文张在gbk下的十六进制表现
d5拆分成二进制1101 0101,按照三码的规范,这其实就是个负数,那么在占用两个字节的前提下,读到一个字节十进制小于0,就可以跳过一个字节读了,也就是上述代码的写法。

当然也可用for循环:

1
2
3
4
5
6
7
8
9
void tjsp(char *ch){
int n = 0;
for(int i = 0; ch[i]; i++){
if(ch[i] < 0)
i++;
n++;
}
std::cout << n << std::endl;
}

拓展

string那会有个把数字转换成字符串的方法std::to_string(number);
对应的也就产生了将字符串转化成数字

作用 语法 用法
str转换成int std::stoi(string) int a = stoi(“123”);
str转换成long std::stol(string) long a = stol(“123”);
str转换成long long std::stoll(string) long long a = stoll(“123”);
str转换成unsigned long std::stoul(string) unsigned long a = stoul(“123”)
str转换成unsigned long long std::stoull(string) unsigned long long a = stoull(“123”);
str转换成float stof(string) float a = stof(“123”);
str转换成double stod(string) double a = stod(“123”);
str转换成long double stold(string) long double a = stold(“123”)

也是有规律的,sto+转换成的类型首字符


stringstream流

在没有声明命名空间的时候,输入输出都是通过std::操作
在头文件sstream中有这么古怪玩意。。std::stringstream
.str()会返回一个string

1
2
3
std::stringstream str;
str << "hello " << "world";
std::string str1 = str.str();

打印str1的结果就是hello world;

这个单独的string流感觉用的也少吧,毕竟代码需要可阅读性,大家都用的会更直观


结语

无感-