string类函数--深入浅出了解

目录

  • 1.为什么学习string类
    • 1.1C语言中的字符串
    • 1.2OJ题中的优势
  • 2.标准库中的string类
  • 3.string类的常用接口函数
    • 3.1string类对象的常见构造
    • 3.2string类对象的容量操作
    • 3.3string类对象的访问及遍历操作
    • 3.4string类的修改操作
    • 3.5string类的非成员函数
  • 总结

1.为什么学习string类

1.1C语言中的字符串

C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。

1.2OJ题中的优势

OJ中,有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本都使用string类,很少有人去使用C库中的字符串操作函数。

2.标准库中的string类

  1. 字符串是表示字符序列的类
  2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
  3. string类是使用char作为它的字符类型,即使用它的默认char_traits和分配器类型(关于模板的更多信息,请参阅basic_string)。
  4. string类basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traitsallocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
  5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码字符)来操作。

总结:

string是表示字符串的字符串类 ② 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
string在底层实际是:basic_string模板类别名,typedefbasic_string<charchar_traits,
allocator>string; ④不能操作多字节或者变长字符的序列。
⑤在使用string类时,必须包含#include头文件以及using namespace std

3.string类的常用接口函数

3.1string类对象的常见构造

string类的构造函数如下:
在这里插入图片描述
介绍经常使用的构造函数:

string();//用空字符串构造一个空string类对象,长度为0
string (const char* s);//用C语言字符串构造string类对象
string (size_t n, char c);//用n个字符c构造string类对象
string (const string& str);//用一个string类str拷贝构造string类对象
string (const string& str, size_t pos, size_t len = npos);
//从str对象pos位置拷贝len字节内容构造string类对象,如果str对象很短或len=npos,则拷贝str对象末尾
static const size_t npos = -1;
//npos为静态成员变量,-1存储在无符号整型中会发生整型提升,为整型的最大值

栗子:

void Test1()
{string str1;cout << str1 << endl;string str2("hello world");cout << str2 << endl;string str3(10, 'x');cout << str3 << endl;string str4(str2);cout << str4 << endl;string str5(str2, 6);cout << str5 << endl;
}

代码编译运行的结果为:
在这里插入图片描述
string类赋值运算符重载

和内置类型赋值运算符一样,string类赋值运算符重载,会将赋值对象原有的数据进行覆盖赋值!

string (1)	
string& operator= (const string& str);
//用string类str对象进行赋值
c-string (2)	
string& operator= (const char* s);
//用C字符串进行赋值
character (3)	
string& operator= (char c);
//用C字符进行赋值

eg:

void Test2()
{string str1("hello world");cout << str1 << endl;string str2;str2 = str1;cout << str2 << endl;str2 = "xxxxx";cout << str2 << endl;str2 = 'y';cout << str2 << endl;
}

代码编译运行的结果为:
在这里插入图片描述

3.2string类对象的容量操作

size_t size() const;//以字节为单位返回字符串的有效长度
size_t length() const;//以字节为单位返回字符串的有效长度
size_t capacity() const;//以字节形式返回string类存储的容量大小
bool empty() const;//检测字符串是否为空串,是返回true,否则返回false

eg1:

void Test3()
{string str1("hello world");printf("string类的大小为:");cout << str1.size() << endl;printf("string类的大小为:");cout << str1.length() << endl;printf("string类的存储容量为:");cout << str1.capacity() << endl;printf("string类的判空值为:");cout << str1.empty() << endl;
}

代码编译运行的结果为:
在这里插入图片描述

  1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()
void clear();//清空有效字符串的内容,使string类对象变为空字符串
void resize (size_t n);
void resize (size_t n, char c);
//将string类有效字符数调整为n,多出的空间为用指定的字符c进行初始化,如果不指定则用'\0'进行初始化
void reserve (size_t n = 0);//为string类预留n字节存储空间大小

eg2:

void Test4()
{string str1("hello world");printf("string对象的内容为:");cout << str1 << endl;printf("string类的字符串大小为:");cout << str1.size() << endl;printf("string类当前的存储容量为:");cout << str1.capacity() << endl;cout << endl;str1.resize(20, 'x');//调整有效字符的个数--调大printf("string对象的内容为:");cout << str1 << endl;printf("string类的字符串大小为:");cout << str1.size() << endl;printf("string类当前的存储容量为:");cout << str1.capacity() << endl;cout << endl;str1.reserve(50);//调整存储空间的大小--调大printf("string对象的内容为:");cout << str1 << endl;printf("string类的字符串大小为:");cout << str1.size() << endl;printf("string类当前的存储容量为:");cout << str1.capacity() << endl;cout << endl;str1.clear();//清除有效字符大小printf("string对象的内容为:");cout << str1 << endl;printf("string类的字符串大小为:");cout << str1.size() << endl;printf("string类当前的存储容量为:");cout << str1.capacity() << endl;
}

代码编译运行的结果为:
在这里插入图片描述

  1. clear()只是将string中有效字符清空,不改变底层空间大小。
  2. resize(size_t n)resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)'\0'来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。

eg3:

void Test5()
{string str1("hello world");printf("string对象的内容为:");cout << str1 << endl;printf("string类的字符串大小为:");cout << str1.size() << endl;printf("string类当前的存储容量为:");cout << str1.capacity() << endl;cout << endl;str1.resize(6);//调整有效字符的个数--调小printf("string对象的内容为:");cout << str1 << endl;printf("string类的字符串大小为:");cout << str1.size() << endl;printf("string类当前的存储容量为:");cout << str1.capacity() << endl;cout << endl;str1.reserve(6);//调整存储空间的大小--调小printf("string对象的内容为:");cout << str1 << endl;printf("string类的字符串大小为:");cout << str1.size() << endl;printf("string类当前的存储容量为:");cout << str1.capacity() << endl;cout << endl;
}

代码编译运行的结果为:
加粗样式
注意:

4.resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
5. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好
6. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserve不会改变容量大小

eg4:

void Test6()
{string str1("hello world");size_t old = str1.capacity();cout << "初始容量为:" << str1.capacity() << endl;for (int i = 0; i <= 100; i++){str1 += 'x';if (old != str1.capacity()){cout << "扩容:" << str1.capacity() << endl;old = str1.capacity();}}
}

代码编译运行的结果为:
在这里插入图片描述

6.在VS2019编译器下,string类以原有容量的1.5倍进行扩容。

3.3string类对象的访问及遍历操作

函数名称:

char& operator[] (size_t pos);
//可以对返回string类对象pos位置的字符进行读写
const char& operator[] (size_t pos) const;
//只能对const string类对象pos位置的字符读取操作,不饿进行修改

eg1:

void Test8()
{string str1("hello world");//对修改前的str1对象进行读取操作for (int i = 0; i < str1.size(); i++){cout << str1[i];}cout << endl;//对str1对象进行修改操作for (int i = 0; i < str1.size(); i++){str1[i]++;//等价于str.operator[i]++cout << str1[i];}cout << endl;
}

代码编译运行的结果为:
在这里插入图片描述
函数名称:

char& at (size_t pos);
//可以对返回string类对象pos位置的字符进行读写
const char& at (size_t pos) const;
//只能对const string类对象pos位置的字符读取操作,不饿进行修改

eg2:

void Test9()
{string str1("hello world");//对修改前的str1对象进行读取操作for (int i = 0; i < str1.size(); i++){cout << str1.at(i);}cout << endl;//对str1对象进行修改操作for (int i = 0; i < str1.size(); i++){str1.at(i)++;cout << str1.at(i);}cout << endl;
}

代码编译运行的结果为:
在这里插入图片描述
函数operator[]与函数at的区别:
eg3:

void Test10()
{//operator[]越界访问string str1("hello world");str1[12]++;
}

代码编译运行的结果为:
在这里插入图片描述
eg4:

void Test11()
{//函数at越界访问string str1("hello world");try//捕获异常{str1.at(12)++;}catch (const exception& e){cout << e.what() << endl;}
}

代码编译运行的结果为:
在这里插入图片描述

string类对象越界访问的时候,函数operator[]通过断言assert报错,函数at通过抛异常报错误。

函数名称:

iterator begin();
const_iterator begin() const;
//begin获取string类第一个字符的迭代器(从左到右)
iterator end();
const_iterator end() const;
//end为获取最后一个字符下一个位置的迭代器(从左到右)

图形理解:
在这里插入图片描述
eg5:

void Test12()
{string str1("hello world");string::iterator it = str1.begin();while (it != str1.end()){cout << (*it);it++;}cout << endl;
}

代码编译运行的结果为:
在这里插入图片描述
汇编代码:
在这里插入图片描述
eg6:

void Test13()
{string str1("hello world");for (auto& ch:str1){cout << ch;}cout << endl;
}

代码编译运行的结果为:
在这里插入图片描述
汇编代码:
在这里插入图片描述

①迭代器是像指针一样的类型,可能是指针;②iterator(迭代器)提供一种统一的方式访问和修改容器的数据,使算法可以通过迭代器去处理容器中的数据;③范围for的底层是通过迭代器实现的。

eg7:

void Test14()
{//string类使用迭代器string str1("hello world");cout << "string类使用迭代器遍历的结果:" << endl;string::iterator it = str1.begin();while (it != str1.end()){cout << *it;it++;}cout << endl;vector<int> v;v.push_back(10);v.push_back(20);v.push_back(30);v.push_back(40);v.push_back(50);cout << "vector使用迭代器遍历的结果:" << endl;vector<int>::iterator vit = v.begin();while (vit != v.end()){cout << *vit << " ";++vit;}cout << endl;list<int> lt;lt.push_back(10);lt.push_back(20);lt.push_back(30);lt.push_back(40);lt.push_back(50);cout << "list使用迭代器遍历的结果:" << endl;list<int>::iterator lit = lt.begin();while (lit != lt.end()){cout << *lit << " ";++lit;}cout << endl;
}

代码编译运行的结果为:
在这里插入图片描述

①任何容器都支持迭代器,并且用法类似;②迭代器跟算法进行配合。

函数名称:

reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
//string类逆置字符串的第一个字符的迭代器(即指向string类从右向左的第一个字符)
reverse_iterator rend();
const_reverse_iterator rend() const;
//string类逆置字符串的最后一个字符下一个位置的迭代器(即指向string类从右向左的最后一个字符的下一个位置)

图形理解
eg8:

void Test15()
{string str1("hello world");string::reverse_iterator it = str1.rbegin();while (it != str1.rend()){cout << *it;it++;}cout << endl;
}

代码编译运行的结果为:
在这里插入图片描述

①使用反向迭代器,从string类后面向前遍历;②范围for不支持反向迭代器。

3.4string类的修改操作

函数名称:

void push_back (char c);//在字符串后尾插字符c
string (1)	
string& operator+= (const string& str);
//在字符串后追加类对象str
c-string (2)	
string& operator+= (const char* s);
//在字符串后追加一个字符串s
character (3)	
string& operator+= (char c);
//在字符串后追加一个字符c

eg1:

void Test16()
{string str1("hello world");str1.push_back('x');printf("使用push_back追加一个字符后:\n");cout << str1 << endl;string str2("yyyyy");str1 += str2;printf("使用operator+=追加str类对象:\n");cout << str1 << endl;str1 += "abcdef";printf("使用operator+=追加字符串:\n");cout << str1 << endl;str1 += 'u';printf("使用operator+=追加一个字符:\n");cout << str1 << endl;
}

代码编译运行的结果为:
在这里插入图片描述
函数名称:

string (1)	
string& append (const string& str);
//string类对象追加string类对象的字符串
substring (2)	
string& append (const string& str, size_t subpos, size_t sublen);
//string类对象追加string类subpos位置sublen长度的字符串
c-string (3)	
string& append (const char* s);
//string类对象追加一个常量字符串
buffer (4)	
string& append (const char* s, size_t n);
//string类对象追加常量字符串的前n个字符
fill (5)	
string& append (size_t n, char c);
//string类对象追加n个字符
range (6)	
template <class InputIterator>string& append (InputIterator first, InputIterator last);
//string类对象追加一个string类[first,last)区间的字符串

eg2:

void Test17()
{string str1("hello world");string str2(" fighting");str1.append(str2);cout << str1 << endl;
}

代码编译运行的结果为:
在这里插入图片描述
注意:

  1. string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。

函数名称:

size_t find (const string& str, size_t pos = 0) const;
size_t find (const char* s, size_t pos = 0) const;
//从stringpos位置往后查找str对象(字符串),并返回第一次出现的位置

eg3:

void Test18()
{string str1("hello world");size_t ret=str1.find("world");cout << ret << endl;
}

代码编译运行的结果为:
在这里插入图片描述
函数名称:

size_t rfind (const string& str, size_t pos = npos) const;
size_t rfind (const char* s, size_t pos = npos) const;
//从stringpos位置往前查找str对象(字符串),并返回第一次出现的位置
//返回的下标是string类的正向下标(从前往后数),而不是逆向的下标(从后往前数)

eg4:

void Test19()
{string str1("hello world");size_t ret = str1.rfind("world");cout << ret << endl;
}

代码编译运行的结果为:
在这里插入图片描述
函数名称:

string substr (size_t pos = 0, size_t len = npos) const;
//返回string类从pos位置len长度的字符串构造的对象

eg5:

void Test20()
{string str1("hello world");string str2 = str1.substr(6);cout << str2 << endl;
}

代码编译运行的结果为:
在这里插入图片描述
函数名称:

const char* c_str() const;
//返回指向string类C语言字符串

eg6:

void Test21()
{string str1("hello world");cout << str1.c_str() << endl;
}

代码编译运行的结果为:
在这里插入图片描述

3.5string类的非成员函数

函数名称:

string operator+ (const string& lhs, const string& rhs);
string operator+ (const string& lhs, const char*   rhs);
//string类+运算符重载,使用传值返回,深拷贝效率低

eg1:

void Test22()
{string str1("hello world");string str2(" fighting");string str3 = str1 + str2;cout << str3 << endl;str3 = str1 + " abc";cout << str3 << endl;
}

代码编译运行的结果为:
在这里插入图片描述
函数名称:

istream& operator>> (istream& is, string& str);//string类输入运算符重载,遇到空格、'\n',停止读取
ostream& operator<< (ostream& os, const string& str);//string类输出运算符重载

eg2:

void Test23()
{string str1;cin >> str1;//使用operator>>运算符重载读取(遇到空格、'\n'停止读取)cout << str1 << endl;//使用operator<<运算符重载写入
}

代码编译运行的结果为:
在这里插入图片描述
函数名称:

istream& getline (istream& is, string& str, char delim);
istream& getline (istream& is, string& str);
//获取一行字符串给string类对象,可以指定delim终止符,不指定则默认以'\n'为终止符

eg3:

void Test24()
{string str1;getline(cin, str1);cout << str1 << endl;
}

代码编译运行的结果为:
在这里插入图片描述

总结

本章节我们一起学习了string类常用接口函数,希望对大家了解string类有些许帮助,感谢大家阅读,若有不对欢迎纠正!🎠🎠🎠

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/79725.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JMeter命令行执行+生成HTML报告

1、为什么用命令行模式 使用GUI方式启动jmeter&#xff0c;运行线程较多的测试时&#xff0c;会造成内存和CPU的大量消耗&#xff0c;导致客户机卡死&#xff1b; 所以一般采用的方式是在GUI模式下调整测试脚本&#xff0c;再用命令行模式执行&#xff1b; 命令行方式支持在…

Connection reset原因分析及解决思路

Connection reset原因分析及解决思路 我们在开发过程中经常会出现Connection reset问题&#xff0c;包括http调用&#xff0c;数据库连接等场景。出现Connection reset的原因很多&#xff0c;本文从tcp层面简单介绍下Connection reset出现的原因和问题&#xff0c;以及在实际开…

Golang 包详解以及go mod

Golang 中包的介绍和定义 包(package)是多个 Go 源码的集合,是一种高级的代码复用方案,Go 语言为我们提供了 很多内置包,如 fmt、strconv、strings、sort、errors、time、encoding/json、os、io 等。 Golang 中的包可以分为三种:1、系统内置包 2、自定义包 3、第三方包…

指令重排相关

指令流水线所带来的一些问题 结构冒险 流水线中出现硬件资源竞争 数据冒险 流水线中后面的指令需要等待前面指令完成数据的读写 控制冒险 流水线需要个怒前面指令的执行结果来决定下一步去哪儿之行 为了解决指令流水线的数据冒险所带来的停顿、CPU 搞了个乱序执行。 在遇到数…

Permute 3 for mac音视频格式转换

Permute是一款Mac平台上的媒体格式转换软件&#xff0c;由Chaotic Software开发。它可以帮助用户快速地将各种音频、视频和图像文件转换成所需格式&#xff0c;并提供了一些常用工具以便于用户进行编辑和处理。 Permute的主要特点包括&#xff1a; - 支持大量格式&#xff1a;支…

通过cpolar内网穿透发布网页测试

通过内网穿透发布网页测试 文章目录 通过内网穿透发布网页测试 对于网站开发者来说&#xff0c;对完成的网页进行测试十分必要&#xff0c;同时还要在测试过程中充分采纳委托制作方的意见&#xff0c;及时根据甲方意见进行修改&#xff0c;但在传统的测试方式中&#xff0c;必须…

以太网帧格式与吞吐量计算

以太网帧结构 帧大小的定义 以太网单个最大帧 6&#xff08;目的MAC地址&#xff09; 6&#xff08;源MAC地址&#xff09; 2&#xff08;帧类型&#xff09; 1500{IP数据包[IP头&#xff08;20&#xff09;DATA&#xff08;1480&#xff09;]} 4&#xff08;CRC校验&#xff…

认识FFMPEG框架

FFMPEG全称: Fast Forward Moving Picture Experts Group (MPEG:动态图像专家组) ffmpeg相关网站: git://source.ffmpeg.org/ffmpeg.git http://git.videolan.org/?pffmpeg.git https://github.com/FFmpeg/FFmpeg FFMPEG框架基本组件: AVFormat , AVCodec, AVDevice, AVFil…

MaxCompute发布按量付费闲时版,计算成本最高节省66.66%!

在大数据不断在追求计算效率和成本优化的背景下&#xff0c;阿里云云原生大数据计算服务 MaxCompute宣布推出按量付费闲时版&#xff0c;用户可选择用此版本完成时间不敏感的作业&#xff0c;从而降低计算成本&#xff0c;同等作业类型的计算费用与按量付费标准版相比&#xff…

【云原生】Docker中容器管理常用所有命令

1.docker 容器创建流程 2.容器运行本质 docker run [OPTIONS] IMAGE [COMMAND] [ARG...] 创建容器基本选项&#xff1a;--name&#xff1a;为容器命名 -i&#xff1a;交互式创建容器 -d&#xff1a;后台创建容器 -t&#xff1a;为容器分配伪终端 Docker 容器存在的意义就是为…

vscode自动添加注释说明

1. 安装vscode 双击安装程序,默认安装即可(如:VSCodeSetup-x64-1.70.2.exe) 2. 安装doxygen文档生成插件 1> 打开vscode软件,点击左侧插件管理菜单 2> 点击右上角’…‘按钮,选择’Install from VSIX’(联网状态可以直接搜索doxygen下载安装) 3> 选择doxygen离线安装…

Golang之路---03 面向对象——接口与多态

接口与多态 何为接口 在面向对象的领域里&#xff0c;接口一般这样定义&#xff1a;接口定义一个对象的行为。接口只指定了对象应该做什么&#xff0c;至于如何实现这个行为&#xff08;即实现细节&#xff09;&#xff0c;则由对象本身去确定。   在 Go 语言中&#xff0c;…

华为harmonyos4.0鸿蒙4.0安装谷歌服务框架Play商店,解决从服务器检索信息时出错

8月4号华为手机发布了全新的harmonyos4.0鸿蒙4.0系统&#xff0c;很多人需要问还是不是支持谷歌服务框架&#xff1f;那么答案是肯定的&#xff0c;它和鸿蒙3是一样的&#xff0c;一样的操作&#xff0c;一样的支持安装谷歌服务框架&#xff0c;安装Google play商店。测试机型&…

Flink State 和 Fault Tolerance详解

有状态操作或者操作算子在处理DataStream的元素或者事件的时候需要存储计算的中间状态&#xff0c;这就使得状态在整个Flink的精细化计算中有着非常重要的地位&#xff1a; 记录数据从某一个过去时间点到当前时间的状态信息。以每分钟/小时/天汇总事件时&#xff0c;状态将保留…

opencv-34 图像平滑处理-2D 卷积 cv2.filter2D()

2D卷积是一种图像处理和计算机视觉中常用的操作&#xff0c;用于在图像上应用滤波器或卷积核&#xff0c;从而对图像进行特征提取、平滑处理或边缘检测等操作。 在2D卷积中&#xff0c;图像和卷积核都是二维的矩阵或数组。卷积操作将卷积核在图像上滑动&#xff0c;对每个局部区…

CASAIM与迈普医学合作,基于CT数据三维重建和设计,在医疗辅具研究开发中实现高精度三维建模和偏差比对

近期&#xff0c;CASAIM与广州迈普再生医学科技股份有限公司&#xff08;简称&#xff1a;迈普医学&#xff09;合作&#xff0c;基于CT数据三维重建和设计&#xff0c;在医疗辅具研究开发中实现高精度三维建模和偏差比对&#xff0c;实现与缺损区域的精确匹配。 迈普医学&…

Zhang-Suen骨架提取算法

前言 本专栏针对的目标物体为物体裂缝量化&#xff0c;提取裂缝的骨架有助于裂缝长度的求解&#xff0c;故这一篇也是本专栏的开篇。 细化算法选择与分析 裂缝骨架的提取是十分有必要&#xff0c;如果我们能够得到裂缝的骨架图那么就很容易获得整条裂缝的长度。在当前经典的…

政府大数据资源中心建设总体方案[56页PPT]

导读&#xff1a;原文《政府大数据资源中心建设总体方案[56页PPT]》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 完整版领取方式 完整版领取方式&#xff1a; 如需…

decimal类型在MySQL中的正确使用 (长度和小数点)

1. MySQL(decimal) 对应 Java(BigDecimal) 2. decimal(16,2) MySQL中类型的设置, 长度16, 保留2位小数 3. 如果长度小于14, 则会出现没小数位的情况

数据采集的方法有哪些?

近年来&#xff0c;国家和各大企业都在部署大数据战略。“大数据”这个词也越来越频繁地出现在我们的生活中。当我们在进行网上冲浪时&#xff0c;页面总会跳出我们想要搜索的相关产品或关联事物。大数据&#xff0c;似乎总是能够“算”出我们“心中所想”。那么&#xff0c;大…