网站特效漂亮的网站,中美最新军事新闻最新消息,外国做图网站,赣州新闻联播直播文章目录 1️⃣什么是stringstring的设计以及编码问题 2️⃣string的重要接口#x1f4ab;#x1f4ab;一、string的初始化二、string的赋值三、string的长度四、string元素获取1. char at(size_t pos)2. operaotr []3. front和back 五、迭代器1. 什么是迭代器2. 范围fo… 文章目录 1️⃣什么是stringstring的设计以及编码问题 2️⃣string的重要接口一、string的初始化二、string的赋值三、string的长度四、string元素获取1. char at(size_t pos)2. operaotr []3. front和back 五、迭代器1. 什么是迭代器2. 范围for底层利用迭代器3. 反向迭代器4. const迭代器5. const反向迭代器6. 四种迭代器总结 六、string插入数据1. push_back--尾插字符2. append --尾插字符串3. 运算符的重载4. append的迭代器用法 七、string的容量操作1. max_size2. capacity3. 扩容机制4. reserve -- 容量预定5. resize -- 容量预定初始化6. empty -- 判空7. clear -- 清空有效字符 八、assign赋值九、insert插入十、erase删除十一、replace替换十二、c_str返回C字符串十三、substr取子串十四、find查找1. find -- 正向查找2. rfind -- 反向查找3. substr和find的应用url分割4. find_first_of 十五、compare比较十六、getline输入string十七、string的转换 1️⃣什么是string
关于string的介绍标准文档是这样说的 字符串是表示字符序列的类标准的字符串类提供了对此类对象的支持其接口类似于标准字符容器的接口但添加了专门用于操作单字节字符字符串的设计特性。string类是使用char(即作为它的字符类型使用它的默认char_traits和分配器类型(关于模板的更多信息请参阅basic_string)string类是basic_string模板类的一个实例它使用char来实例化basic_string模板类并用char_traits和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)注意这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列这个类的所有成员(如长度或大小)以及它的迭代器将仍然按照字节(而不是实际编码的字符)来操作 实际上string就是动态增长的char字符数组
但string其实是一个typedef之后的类模板如下图 string实际上是一个 模板参数是char类型
同样有一些少见的其他string
如wstring里面存的就是wchar_t 宽字符应用于unicode编码
u16string里面存的是char16_t
u32string里面存的是char32_t
所以string其实就是basic_string类的针对char 的实例化
string的设计以及编码问题
这里就涉及编码的问题了。计算机中数据只有0和1而如何表示各种文字呢就要用到编码了。
常见的编码表有ASCII,GBKutf-8,utf-16,utf-32等。而编码表实际就是内存中的值 和 文字符号的映射关系,例如字符a对应内存的值就是97
string是一个字符串而字符串表示的是信息所以就涉及到各种文字。我们知道ASCII码是针对于老美的因为英美的文字只包含字母和标点符号而一个char为8位对于二进制可以表示256钟状态每一个字母和标点对应一个状态对于老美绝对够用了。
但是当计算机推广的时候其他国家的问题就不可以只依靠ASCII来编码了比如中文的就远比英美文字复杂得多而且中国汉字多得多所以一个字符根本表示不完。所以中文采用多个字符的编码。常见的是两个字符即16位65536个状态。所以为了支持泛型编程把string设置为一个模板对于不同类型的字符都可以使用
例如:
char str[]你好;此时str的长度就是4个字符,两个字符表示一个汉字
而每一个字符又对应一个编码 -60 和 -29组合起来映射的是 你
-70 和 -61组合起来映射的是 好
//字符的编码值 对应编码表去查找反过来验证
char hello[] { -60,-29,-70,-61,0 };
cout hello endl;如果让hello[3]的元素
char str[] 你好;hello[3];
cout hello endl;
hello[3];
cout hello endl;
hello[3];
cout hello endl;输出结果
发现好的周围都是hao
关于汉字的编码可以推得中文编码是把同音字放在一起的
平时我们打游戏的时候一些出口即国粹的脏话输出机玩家发的消息就会变成***而中国文化博大精深很多谐音字也可以用来发挥作用所以就利用汉字的编码分区把同音字也放到一个国粹词库中了一旦检测到是词库中的内容就会和携成***这就是净网行动的原理。
2️⃣string的重要接口
一、string的初始化
1. string()
string s1; // s1为\0 构造空string对象调用默认构造函数注意为兼容C的字符产标准即使为空也存在一个\0表明这是字符串
2. string(const char* s)
string s2(hello wolrd);//s2为 hello world
string s3 hello world; //先构造 再拷贝构造 - 优化直接构造 这是用C的常量字符串构造一个string对象
这里因为只有const char*s这一个参数对于单参数的构造函数可以支持隐式类型转换即先构造再拷贝构造一般编译器会优化为直接构造
3. string(const string str)
string s1(hello);// s1 hello
string s3(s1);//s3 hello 利用一个string对象构造一个对象拷贝构造
4.string(size_t n, char c)
string s4(5,a); //s4 aaaaa 用 n 个字符c构造一个对象
5.string(const char*s , size_t n)
string s5(hello world,5);//s5 hello 用 常量字符产s的前n个构造一个string对象
6. string(const string str, size_t pos,size_t len npos
string s1(hello wolrd);// s1 hello world
string s2(s1,6,3);// s2 wor
string s3(s1,6,5);// s3 world
string s4(s1,6,10);// s4 world 大于后面的字符数直接拷贝到最后
string s4(s1,6); // s4 world 用一个string对象的pos位置开始向后len个字符来构造一个string
① 如果len大于从pos位置到’\0’的长度那么就拷贝到最后
② 如果不传递len缺省参数为 std::npos是一个std命名空间中的全局变量值为-1.
因为 len为size_t类型正数而-1为负数二进制是32个1赋值给len自动被转变成无符号数约为42亿九千万即大约是4g而4g这么大的字符串基本上是不存在的。所以不传递len默认拷贝到最后有多少拷贝多少
二、string的赋值
1. string operator(const string str)
string s1 hello world;
string s2;
s2 s1;//s2 hello world 用一个string进行赋值
2. string operator(const char*)
string s1;
s1 hello world; 用常量字符串赋值
3. string operator(char c)
string s1;
s1 x;//用一个字符x给s1赋值三、string的长度
string s1 hello world;
cout s1.length() endl; //写法1
cout s1.size() endl; //写法2
注意
size_t size() const 返回size_t类型 计算有效字符个数 — 对于所有容器都有size_t length() const ---- 有的容器没有lengtn对于树这样的叫长度不合适
所以一般统一用 size()
四、string元素获取
1. char at(size_t pos) 顾名思义函数返回pos位置的元素的引用
普通对象调用char at(size_t pos)
const对象调用const char at(size_t pos) const
与operator[]的区别就是如果pos超出string的索引范围越界会抛异常,还可以继续执行后面的程序。operator[]是断言直接终止
2. operaotr [] 两个函数构成函数重载
普通对象调用char operator[] (size_t pos)
const对象调用const char operator[] (size_t pos) const;。
string s1 hello world;//char operator[] (size_t pos);
cout s1[0] endl;//用[]进行访问
s1[0] x;//用[]修改原字符
cout s1 endl;//const char operator[] (size_t pos) const;
const string s2 const string;
//s2[0] d;//const类型不能修改
cout s2[0]: s2[0] endl;
//cout s2[15] endl;; 超出s2的长度报错assertion failed利用[]遍历string
string s3 string;
const string s4 const string;
//遍历s3
for (size_t i 0; i s3.length(); i)
{s3[i];
}
cout s3 endl;//利用[]修改
for (size_t i 0; i s3.length(); i)
{s3[i];
}//const类型只能遍历不能修改
const string s4 const string;
for (size_t i 0; i s4.size();i)
{cout s4[i] ;//cout s4.at(i) ; 两种效果一样
}
cout endl;
3. front和back front是返回第一个字符
back返回最后一个字符不算’\0’ )
五、迭代器
1. 什么是迭代器
迭代器是一个类型iterator
每一个数据结构内部都有定义的这么一个类。如string::iterator就是string的迭代器vector::iterator就是vector的迭代器
迭代器是一个像指针一样的类型可能是指针也可能不是指针但是用法像指针具体细节封装了起来。
对于string和vector其实就是原生指针但是对于list就不是指针了而是一个自定义类型
我们知道可以利用[]遍历string但是[]只针对底层利用数组实现的类型对于其他一些比如链表、树型结构就不能利用[]遍历了。
iterator是对于STL容器的统一遍历方法用法都是类似的不管是顺序表还是链式表使用都是一样的~
对于迭代器iteratorstring中有两个常用的函数返回类型是迭代器类型
begin()和end()分别返回第一个位置的迭代器和最后一个位置的下一个位置的迭代器[begin,end),左闭右开 如图所示类似指针可以利用迭代器去遍历string string s(hello);
//利用迭代器去遍历
//定义一个迭代器类型 it
string::iterator it s.begin();//it为第一个位置的迭代器
while (it ! s.end())//当it迭代到最后一个位置的时候结束
{cout *it ; //类似指针解引用it;
}
cout endl;//const迭代器无法修改类似const指针
string s1 hello world;
string::const_iterator it3 s1.begin();
while (it3 ! s1.end())
{cout *it3 ;it3;//(*it3); 不能修改
}
cout endl;同理迭代器可以进行修改和指针类似的用法(*it)
但是对于string和vector类型很少用迭代器因为底层用数组实现[]使用起来更香对于list、map等容器必须使用迭代器遍历
2. 范围for底层利用迭代器
范围for可以遍历任何容器并具有自动迭代自动判断结束的功能十分智能。
注意范围for只能正向遍历不能反向
string s hello;
for (auto i : s)//依次取s中的每一个元素赋值给i
{cout i ;
}
coutendl;//利用范围for修改元素
for (auto i : s) //依次给s中每一个元素取别名
{i;cout i ;
}其实范围for的底层就是迭代器编译器会自动把范围for替换成迭代器
迭代器遍历的汇编 范围for的汇编 所以从汇编指令的角度可以看到范围for就是去调用了迭代器进行遍历
3. 反向迭代器
类名::reverse_iterator如string::reverse_iterator
反向迭代器就是从后面向前迭代利用两个函数 rbegin()返回反向的第一个位置的迭代器正向的最后一个位置
rend()返回反向的最后一个位置的下一个位置的迭代器正向第一个位置的前一个位置 string s hello;//反向迭代器
string::reverse_iterator r_it s.rbegin();//必须用反向迭代器接受 rbegin()的返回结果
while (r_it ! s.rend())
{cout *r_it ;r_it; //注意这里也是 不是--
}
cout endl;//输出 o l l e h 4. const迭代器
const迭代器const_iterator,如string::const_iterator
const迭代器 – 经常发生在传参过程中(传参经常传const 对象)
一般利用begin()和end()的返回值当然也可以使用cbegin()和cend()
cbegin()和cend()是C11支持的只是为了更规范一些
因为begin()和end()是具有重载的根据是否为const决定是否调用哪一个重载考虑到有些时候可能难以看出调用的是哪一个重载才引入了cbegin()和cend()但其实没有什么必要用begin()和end()就可以了
使用情景
对象是const自定义对象一般传递const 引用
//传参是 const引用 str hello
void PrintString(const string str)
{//这时候打印str// string::iterator c_it str.begin() - 错误str调用begin返回const迭代器要用const迭代器接收//因为str为const类型所以迭代器要用conststring::const_iterator c_it str.begin();//或str.cbegin() C11支持 [然并卵]while (c_it ! str.end()){//(*c_it) x;//const!不能修改cout *c_it ;c_it;}cout endl;
}//输出 h e l l o5. const反向迭代器
类名::const_reverse_iterator
利用函数rbegin()和rend()
或者crbegin()和crend() -C11推出与cbegin(),cend()都是为了规范性没什么使用的必要
//str hello
void PrintString(const string str)
{//反向打印strstring::const_reverse_iterator c_r_it str.rbegin();//调用rbegin()while (c_r_it ! str.rend()){cout *c_r_it ;c_r_it;}cout endl;
}//输出 o l l e h 6. 四种迭代器总结
以string类为例
迭代器函数string::iteratorbegin(),end()string::reverse_iteratorrbegin(),rend()string::const_iteratorbegin(),end() 或cbegin(),cend()string::const_reverse_iteratorrbegin(),rend()或crbegin(),crend()
六、string插入数据
1. push_back–尾插字符
即在字符串的尾部插入一个字符
//void push_back(char c)--(插入字符
string s hello;
s.push_back(-);//s变成hello-2. append --尾插字符串
//append() ----插入字符串
string s hello
s.append(world);//s变成helloworld3. 运算符的重载
string类实现了的运算符重载从而实现字符串的拼接功能
同时有三个函数重载
string operator (const string str)拼接string string operator (const char* s)拼接C字符串 string operator (char c)拼接一个字符
string s1(good);
s1 evening ;// const char*
s1 ;// char
string s2( my friend);
s1 s2;// string对象
cout s1 endl;/************************************/
// s1 : good evening myfriend
其实的底层就是调用了push_back和append
相比C语言C字符串的操作是简单了很多
定义一个字符串要么就是定义字符数组char[]但是数组的容量又是一个问题开大开小都不合适如果是动态开辟还要检查扩容拼接字符串C语言追加的strcat函数效率低并且不管空间必须调用者保证好空间该函数只管追加。而string的重载里有size记录字符串长度并且还会自动判断扩容。
4. append的迭代器用法
使用迭代器可以规定append的范围
主要用处是把某字符串的一部分追加到原字符串的后面
string str hello world;
string s my friend;
str.append(s.begin(),s.end());//等价于strs
//从第二个位置的迭代器开始倒数第二个位置结束不追加第一个字符和最后一个字符
str.append(s.begin(),--s.end());//str hello worldy frien七、string的容量操作
1. max_size
string的最大长度是写死的其值为整形的最大值32个1没啥意义
string s;
string s1(hello world);
cout s.max_size() endl;
cout s1.max_size() endl;//同一环境max_size()是一个定值2. capacity
获取string对象容量大小不包括’\0’
string s;
size_t sz s.capacity();
cout init capacity: sz endl;//输出 15 默认给15大小
// 意思就是 有15个可以存储有效字符的空间
// \0是标识字符不是有效字符3. 扩容机制 Windows Visual Stdio2019下的扩容机制 //测试尾插1000个x会扩容几次
int main()
{string s;size_t sz s.capacity();//初始cout init capacity: sz endl;cout grow endl;for (int i 0; i 1000; i){s.push_back(x);//如果发生扩容就打印改变后的容量if (sz ! s.capacity()){sz s.capacity();cout capacity changed: sz endl;}}return 0;
}结果 可以看到VS下初始容量为15并且刚开始是2倍扩容后面约是1.5倍扩容 Linux下的扩容机制直接看运行截图 可以发现Linux下初始容量为0并且始终是2倍扩容
4. reserve – 容量预定
有时候需要开一定的空间但是如果空间比较大就需要频繁扩容
不过reserve()这个成员函数可以提前开好空间只改变capacity减少频繁扩容如果知道需要多少空间的情况下单位是字节 /* reserve -- 对容量进行预留如有需要可以提前开好减少扩容*/string s1;s1.reserve(1000);//提前开好1000的容量考虑对齐VS下是1007个有效空间Linux下1000size_t sz1 s1.capacity();cout init capacity: sz1 endl;cout grow endl;for (int i 0; i 1000; i){s1.push_back(x);if (sz1 ! s1.capacity()){sz1 s1.capacity();cout capacity changed: sz1 endl;}}5. resize – 容量预定初始化 resize改变的是string的长度如果容量不够也会扩容并且会用字符去初始化。size和capacity会同时改变
string s;
s.resize(100);//开100个空间没给参数用\0初始化
s.resize(100,x);// 给参数为x用x初始化//但是size和capacity都会变成100 所以还会扩容注意如果字符串本身已经有内容了那么resize只是会起到追加的作用不会影响原来的字符串
6. empty – 判空
string str1 hello;
string str2;
coutstr1.empty()endl; // 输出 0
coutstr2.empty()endl; // 输出 17. clear – 清空有效字符
string str welcome to my blog;
str.clear(); // str \0 即变成空字符八、assign赋值
assign类似直接给字符串赋值,不过用的很少
string str;
string temp this is an example;//str.assign (size_t n, char c); 将n个字符c赋值给字符串str
str.assign(10,x); // str xxxxxxxxxx//str.assign(const string s) 将字符串s赋值给str
str.assign(temp); //str this is an example//str.assign(const string s, size_t pos, size_t len) 将字符串的s从pos位置开始的len个字符赋值给字符串str
str.assign(temp,6,2); //str is//assign (const char* s) 将字符数组s赋值给str
str.assign(hello); //str hello//assign(const char*s,size_t n) 将字符数组的前n个字符赋值给str
str.assign(hello,3); //str hel九、insert插入
insert也不是很常用简单了解几个常用的即可
string temp hello world;//insert(size_t pos,const string str) 从pos位置插入字符串str
string s1 xxx;
temp.insert(5,s1); // str helloxxx world//insert(size_t pos,const char* str) 从pos位置插入字符数组str
temp.insert(5,ggg); // str helloggg world//insert(iterator p,charc) 从迭代器p位置插入一个字符c
temp.insert(str.begin(),5); // str 5hello world
十、erase删除
string str welcome to my house;
//erase (pos 0,len npos) 删除pos位置开始的len个字符,pos默认为0len默认为无限大删到结尾
str.erase(14,5); //str welcome to my
str.erase(7); //str welcome
str.erase(); //str ; //空字符串//erase (iterator p); //删除p位置迭代器的字符
str.erase(str.begin()2); //str wecome to my house//erase (iterator first, iterator last) //删除迭代器区间[first,last)的字串
str.erase(str.begin()7,str.end()-5); //str welcomehouse十一、replace替换
替换的部分长度可以不一样类似于先删除原部分然后再插入
效率很低用的不多
//replace (size_t pos, size_t len, const string str); 源字符串从pos位置往后的len个字符用str替换
string s1 hello the world;
string s2 m
s1.replace(6,3,great); // s1 hello great world//replace (size_t pos, size_t len, const char* s) 源字符串从pos位置往后的len个字符用C字符串s替换
s1.replace(105string); // s1 hello the string//replace (size_t pos, size_t len, const char* s, size_t n); 原字符串从pos位置往后len个字符用C字符串s的前n个字符替换
s1.replace(10,5,cpp is good,3); // s1 hello the cpp
十二、c_str返回C字符串
因为C的字符串是char*类型不同于string
并且有些场景是存在需要返回char*类型的不可以返回string类型.因为C兼容C很多底层一些接口是用C写的这样二者都可以使用
比如用C的形式打开文件
const char* c_str() const 函数的作用就是把string类型变成const char*类型来使用底层就是返回了string封装的char*成员
string filename(test.cpp);
//FILE* pf fopen(filename,r); //error 类型不匹配
FILE* pf fopen(filename.c_str(),r); // √
if(pfNULL)
{perror(fopen fail);exit(-1);
}
char c fgetc(pf);
while(c!EOF)
{coutc;c fgetc(pf);
}★★★注意二者打印的原理是不同的★★★
**string是以size() 为结束标志 **
string.c_str是以’\0’为结束标志
string str hello world;
cout str endl; //调用 string的 operator 重载
cout str.c_str() endl; // 调用const char* 的 operator 重载
// 上面输出是一样的str \0;
str welcome;cout str endl; //输出: hello world welcome
cout str.c_str() endl; //输出: hello world//因为c_str以\0为标志就结束了不会打印\0后面的内容
//所以C字符串其实是有bug的C字符串里面不能夹杂着\0 \0是不显示字符所以打印就会显示一个空白
十三、substr取子串 即返回从原字符串的pos位置处向后的len个字符的子串
默认pos为0len默认为整形最大值无限大
string str hello my friend;
string s1 str.substr(6,2); //s1 my
十四、find查找
1. find – 正向查找
find函数如果找到返回第一个位置的下标找不到返回string::npos
string str hello world;
//find (const string str, size_t pos 0) const 从pos位置处查找子串str返回第一个位置
string substr wor;
size_t pos1 str.find(substr); //pos1 6//find(const char* s,size_t pos 0) const 从pos位置查找C字符串s
size_t pos2 str.find(ld); //pos2 9//find(char c,size_t pos 0)const 从pos位置查找字符c
size_t pos3 str.find(e); //pos3 1//find(const char* s,size_t pos,size_t n) 从pos位置查找c字符串s的前n个
size_t pos4 str.find(hello,0,3); //pos4 0 2. rfind – 反向查找
rfind和find 用法相同只是rfind是查找最后一次出现的位置
rfind的应用找文件名后缀Linux下文件名需要是最后一个.后面才是后缀名
string filename test.cpp.tar.zip; //后缀名是.zip
size_t pos filename.rfind(.); //找最后一个.
//如果找到
if(pos ! string::npos)
{coutfilename.substr(pos);//找到就打印pos后面的字串
}//输出.zip3. substr和find的应用url分割
对一个网址进行url分割url一般格式为协议://域名/资源定位符
所以利用find()和substr()找://“和它后面的第一个/就可以了
string url https://legacy.cplusplus.com/reference/string/string/;
size_t pos1 url.find(://);
if (pos1 string::npos)
{cout url不合法 endl;
}
string protocol url.substr(0,pos1);//协议第一个字符到pos1之间 共pos1个字符
size_t pos2 url.find(/, pos1 3);
if (pos2 string::npos)
{cout url不合法 endl;
}
string domain url.substr(pos1 3, pos2 - pos1 - 3);//域名://后面的第一个字符到下一个\之前 pos2-pos1-3个字符 任意pos1,pos2)之间有pos2-pos11个字符//剩下的到最后就是资源定位符
string uri url.substr(pos21); //pos21到最后即可
cout protocol endl;
cout domain endl;
cout uri endl;4. find_first_of
find是找到一个完全匹配的子串
find_first_of是只要找到目标串中的一个字符就返回当前的位置
string str please notice that i am a sentence;
size_t pos str.find_first_of(aeiou); //找出元音字母的字符并改变为*
//只要还能找到就继续循环 // 只要找到aeiou其中的一个就返回
while(pos!string::npos)
{str[pos]*;pos str.find_first_of(aeiou,pos1); //从pos的下一个位置开始继续找
}
cout str endl;//输出pl**s* n*t*c* th*t * *m * s*nt*nc*
find_last_of和find_first_of类似不同的是find_last_of是从后往前找(了解)
十五、compare比较
两个字符串自左向右逐个字符相比按ASCII值大小相比较直到出现不同的字符或遇\0为止。 若是遇到‘\0’结束比较则长的子串大于短的子串如“9856” “985”。 如果两个字符串相等那么返回0调用对象大于参数返回1小于返回-1
string str1 abcdef;
string str2 abcefg;//s.compare(str) 比较当前字符串s和str的大小
cout str1.compare(str2); // -1 (str2 str1)//s.compare(pos,n,str) 比较当前字符串s从pos开始的n个字符与str的大小
cout str1.compare(1,5,str2); // 1 (ba)//string也支持和const char*类型比较十六、getline输入string
我们通常使用的 cin可以获取字符串但是cin遇到空格或者换行就会停止输入
所以如果要输入包含空格的一个句子就不可以用cin来获取输入了
需要用到getline()获取一行只有遇到换行的时候才会停止输入 从 is 中提取字符并将其存储到 str 中直到找到分隔字符 delim如果不给就是换行符“\n”。
如果到达文件的末尾**或者在输入操作期间发生其他错误则提取也会停止。
如果找到分隔符则将其提取并丢弃即不存储它下一个输入操作将在它之后开始
string s;
getline(cin,s); //输入 i am a student
coutsendl; //输出i am a studentstring str;
getline(cin, str,x); //如果不输入x 就一直提示你输入
cout str endl; //输入x之后停止并输出
十七、string的转换
//其他类型转字符串
to_string(val); //val转化为string对象返回类型stringval可以是int、double、float、long等等int a 123456;
string str to_string(a);
cout str endl; // 123456double dd 12.34;
string ddd to_string(dd);
cout ddd endl; //12.340000 默认小数点后6位关于stoi字符串转整形
int stoi(const string str, size_t* idx 0, int base 10 )
第一个参数是要转的字符串
第二个参数是一个size_t类型数据的指针传指针是为了改变实参传进去之后函数会把同时包含数字和字符的字符串中最后一个数字的下一个位置的字符位置给它只能是数字在前面的情况才会给你
第二个参数一般可以不传递
第三个参数是要转换成的进制默认为10进制
//字符串转其他类型
string str 2008,a good year;
size_t pos 0; //用于记录数字后字符的位置
int a stoi(str, pos, 10);
cout a endl; // 2008
cout str.substr(pos)endl; // ,a good yearstring str1 13524ddd;
int b stoi(str1); // 一般使用只需传递字符串即可
coutbendl; // 13524//stod -- 字符串转double
string s 9999.99;
double d stod(s);
coutdendl; //9999.99