string和stringstream用法「建议收藏」

string和stringstream用法「建议收藏」string和stringstream用法总结

大家好,又见面了,我是你们的朋友全栈君。

一、string

string 是 C++ 提供的字符串类型,和 C 的字串相比,除了有不限长度的优点外,还有其他许多方便的功能。要使用 string, 必须先加入这一行:

#include <string>

接下來要定义一个字串变量,可以写成:

string s;

我们也可以在定义的同时初始化字串:

string s = "you";

而要取得其中某一个字元,和传统C 的字串一样是用 s[i] 的方式取得。比较不一样的是如果 s 有三个字元,传統 C 的字串的 s[3] 是’\0′ 字符,但是 C++ 的 string 则是只到 s[2] 这个字符而已。


做一个对照:

操作 string 字符数组
定义字符串
string s; char s[100];
取得第i个字符 s[i] s[i]
字符串长度 s.length()
或 s.size()
strlen(s)
读入一行 getline(cin, s); gets(s);
赋值 s = “you”; strcpy(s, “you”);
字符串连接 s = s + “you”;
s += “you”;
strcat(s, “you”);
字符串比较 s == “you” strcmp(s, “you”);

两个string常用的方法是find和substr。在下面的代码当中:find函数从str的第3个位置查起,找到ssdf这个子串后,返回子串的位置。而substr函数从pos位置开始,截取5个字符,赋值给str2。也就是说,str2之后的内容将是ssdfs。

string str = "aaaaddddssdfsasdf"; size_t pos = str.find("ssdf", 3); //可以用if(pos == string::npos) 用来判断是否找到子串。 //传送门: http://blog.csdn.net/sunshineacm/article/details/78075135  string str2 = str.substr(pos, 5);

二、stringstream

stringstream是 C++ 提供的另一个字串型的串流(stream)物件,和之前学过的iostreamfstream有类似的操作方式。要使用stringstream, 必须先加入这一行:

#include <sstream>

stringstream主要是用在將一个字符串分割,可以先用.clear( )以及.str( )將指定字串设定成一开始的內容,再用>>把个別的资料输出。


举个例子:

題目:输入的第一行有一个数字 N 代表接下來有 N 行资料,每一行资料里有不固定个数的整数(最多20个,每行最大200个字元),编程將每行的总和打印出來。

输入:

3
1 2 3
20 17 23 54 77 60
111 222 333 444 555 666 777 888 999

输出:

6
251
4995


代码:

#include <iostream> #include <string> #include <sstream> using namespace std; int main() {     string s;     stringstream ss;     int n;     cin >> n;     getline(cin, s);  //读取换行     for (int i = 0; i < n; i++)     {         getline(cin, s);         ss.clear();         ss.str(s);         int sum = 0;         while (1)         {             int a;             ss >> a;             if(ss.fail())                 break;             sum += a;         }         cout << sum << endl;     }     return 0; }

三、使用stringstream简化类型转换

C++标准库中的<sstream>提供了比ANSI C的<stdio.h>更高级的一些功能,即单纯性、类型安全和可扩展性。接下来,我将举例说明怎样使用这些库来实现安全和自动的类型转换。

一个例子:

#include <stdio.h> int main() { int n = 10000; char s[10]; sprintf(s, "%d", n); //s中的内容为“10000” //到目前为止看起来还不错。但是,对上面代码的一个微小的改变就会使程序发生错误 printf("%s\n", s); sprintf(s, "%f", n); //错误的格式化符 printf("%s\n", s); return 0; }

输出:

string和stringstream用法「建议收藏」

在这种情况下,由于错误地使用了 %f 格式化符来替代了%d。因此,s在调用完sprintf()后包含了一个不确定的字符串。要是能自动推导出正确的类型,那不是更好吗?

进入stringstream:

由于ns的类型在编译期就确定了,所以编译器拥有足够的信息来判断需要哪些转换。<sstream>库中声明的标准类就利用了这一点,自动选择所必需的转换。而且,转换结果保存在stringstream对象的内部缓冲中。你不必担心缓冲区溢出,因为这些对象会根据需要自动分配存储空间。

<sstream>库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。另外,每个类都有一个对应的宽字符集版本。简单起见,我主要以stringstream为中心,因为每个转换都要涉及到输入和输出操作。

注意,<sstream>使用string对象来代替字符数组。这样可以避免缓冲区溢出的危险。而且,传入参数和目标对象的类型被自动推导出来,即使使用了不正确的格式化符也没有危险。

1、string到int的转换

string result = "10000"; int n = 0; stream << result; stream >> n; //n等于10000 


2.重复利用stringstream对象

如果你打算在多次转换中使用同一个stringstream对象,记住在每次转换前要使用clear()方法。

在多次转换中重复使用同一个stringstream(而不是每次都创建一个新的对象)对象最大的好处在于效率。stringstream对象的构造和析构函数通常是非常耗费CPU时间的。


3.在类型转换中使用模板

你可以轻松地定义函数模板来将一个任意的类型转换到特定的目标类型。例如,需要将各种数字值,如int、long、double等等转换成字符串,要使用以一个string类型和一个任意值t为参数的to_string()函数。to_string()函数将t转换为字符串并写入result中。使用str()成员函数来获取流内部缓冲的一份拷贝。

template<class T> void to_string(string &result, const T &t) { ostringstream oss; //创建一个流 oss << t; //把值传递入流中 result = oss.str(); //获取转换后的字符并将其写入result } //这样,你就可以轻松地将多种数值转换成字符串了 to_string(s1, 10.5); //double到string to_string(s2, 123); //int到string to_string(s3, true); //bool到string //可以更进一步定义一个通用的转换模板,用于任意类型之间的转换。函数模板convert()含有两个模板参数out_type和in_value,功能是将in_value值转换成out_type类型: template<class out_type, class in_value> out_type convert(const in_value & t) { stringstream stream; stream << t; //向流中传值 out_type result; //这里存储转换结果 stream >> result; //向result中写入值 return result; } 

测试代码:

#include <iostream> #include <string> #include <sstream> using namespace std; template<class T> void to_string(string &result, const T &t) { ostringstream oss; oss << t; result = oss.str(); } template<class out_type, class in_value> out_type convert(const in_value & t) { stringstream stream; stream << t; out_type result; stream >> result; return result; } int main() { //to_string实例 string s1, s2, s3; to_string(s1, 10.5); //double到string to_string(s2, 123); //int到string to_string(s3, true); //bool到string cout << s1 << endl << s2 << endl << s3 << endl << endl; //convert()例子 double d; string salary; string s = "12.56"; d = convert <double> (s); //d等于12.56 salary = convert <string> (9000.0); //salary等于"9000" cout << d << endl << salary << endl; return 0; }

输出:

string和stringstream用法「建议收藏」

4.结论

在过去留下来的程序代码和纯粹的C程序中,传统的<stdio.h>形式的转换伴随了我们很长的一段时间。但是,如文中所述,基于stringstream的转换拥有类型安全和不会溢出这样的特性,使我们有充足得理由去使用<sstream>。<sstream>库还提供了另外一个特性—可扩展性。你可以通过重载来支持自定义类型间的转换。


5.一些实例

stringstream通常是用来做数据转换的。相比c库的转换,它更加安全,自动和直接。

例子一: 基本数据类型转换例子 int 转 string

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main()
{
	stringstream ss;
	string s;
	int i = 1000;

	ss << i;
	ss >> s;
	cout << s << endl;

	return 0;
}

运行结果:

string和stringstream用法「建议收藏」


例子二: 除了基本类型的转换,也支持char *的转换

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main()
{
	stringstream ss;
	char s[10];

	ss << 8888;
	ss >> s;
	cout << s << endl;

	return 0;
}

运行结果:

string和stringstream用法「建议收藏」


例子三: 再进行多次转换的时候,必须调用stringstream的成员函数.clear()

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main()
{
	stringstream ss;
	int first = 0, second = 0;

	ss << "456";  // 插入字符串
	ss >> first;  //转换成int
	cout << first << endl;

	ss.clear();  //在进行多次转换前, 必须清除ss
	ss << true;
	ss >> second;
	cout << second << endl;

	return 0;
}

运行结果:

运行.clear()结果

string和stringstream用法「建议收藏」

没有运行.clear()结果

string和stringstream用法「建议收藏」


6.使用误区

如果stringstream使用不当,当心内存出问题。试试下面的代码,运行程序前打开任务管理器,看看内存变化。

复制代码,把 stream.str(“”);  那一行的注释去掉,再运行程序,内存就正常了。


看来stringstream似乎不打算主动释放内存( 或许是为了提高效率 ),但如果你要在程序中用同一个流,反复读写大量的数据,将会造成大量的内存消耗,因此这时候,需要适时地清除一下缓冲 ( 用 stream.str(“”)  )。

另外不要企图用  stream.str().resize(0) 或  stream.str().clear()  来清除缓冲,使用它们似乎可以让stringstream的内存消耗不要增长得那么快,但仍然不能达到清除stringstream缓冲的效果(做个实验就知道了,内存的消耗还在缓慢的增长)

#include <iostream> #include <sstream> using namespace std; int main() { std::stringstream stream; string str; while(1) { //clear()这个名字让很多人想当然地认为它会清除流的内容。 //实际上它并不清空任何内容,它只是重置了流的状态标志。 stream.clear(); //去掉下面这行注释,清空stringstream的缓冲,每次循环内存消耗将不再增加。 //stream.str(""); stream << "you see see you"; stream >> str; // 去掉下面这行注释,看看每次循环,你的内存消耗会增加多少 //cout << "Size of stream = " << stream.str().length() << endl; } return 0; }


参考链接:

http://blog.csdn.net/zhang_xueping/article/details/47846807

http://blog.csdn.net/u014097230/article/details/52089530


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/130495.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 黑客初学者刷屏技巧_初学者,这些技巧将加速您的编码

    黑客初学者刷屏技巧_初学者,这些技巧将加速您的编码黑客初学者刷屏技巧Whenyoujuststartoutyourprogrammingjourney,therearesomanyshinytoolsandtechnologiestoexplore,youalmostdon’tknowwheretostart.Fortunately,therearenumerousguidesonho…

  • 服务器 IIS服务器防盗链具体设置方法

    服务器 IIS服务器防盗链具体设置方法IIS主机的Rewrite伪静态组件下载与配置之前已经讲过,如果你的apache服务器,请看&lt;Apache服务器设置防盗链的方法&gt;,今天主要说下IIS服务器防盗链的设置方法。isapi_rewrite利用正则表达式进行替换规则的表示。进行正则表达式的编写的时候,可以利用isapi_rewrite提供的正则表达式测试工具(默认安装提供),进行调试。做好了匹配表达式和格式化表达式,我们可…

  • js中倒计时_js倒计时特效

    js中倒计时_js倒计时特效利用setInterval制作简单的js倒计时,点击按钮将触发定时器且按钮不可用html:获取校验码JS: vari; functiongetCode(){ $(“#code”).attr({“disabled”:”disabled”}); i=self.setInterval(“countdown()”,1000); } varint=1

  • 脑科学磁共振成像(MRI)初学者必看——功能脑网络、小世界网络、FDR校正、脑电信号频率变换、模板、假设检验、广义线性模型、独立成分分析、影像组学、任务态和静息态方法汇总「建议收藏」

    脑科学磁共振成像(MRI)初学者必看——功能脑网络、小世界网络、FDR校正、脑电信号频率变换、模板、假设检验、广义线性模型、独立成分分析、影像组学、任务态和静息态方法汇总「建议收藏」磁共振成像初学者必看一、浅谈功能脑网络二、不同模态脑网络的构建功能脑网络结构脑网络白质纤维束脑网络加权网络二值网络三、趣谈散点图与相关系数四、脑电信号频域变换五、fMRI中的FDR校正六、模板(mask)1、模板(mask)往往是与ROI联系在一起的2、mask作用的原理3、常见的mask七、假设检验和效果量八、组水平标准化九、由ALFF说开去十、计算机存取MRI影像的那些事十二、Linux基础命令十三、浅谈标准空间模板和空间变换一:标准空间模板二:空间变换十四、功能连接十五、大脑激活与功能连接的

  • java语言打印出菱形_java怎么打印菱形

    java语言打印出菱形_java怎么打印菱形Java典型例题(打印菱形)题目:利用*号打印出一个菱形图样分析:下面逐步分析菱形打印的推演过程推演过程利用单独的方法演示,使用时直接在主方法中调用对应的方法即可。第一步,打印一行*号/**打印出如下图形: ********/publicstaticvoidprint01(){//每次打印一个星星for(inti=1;i<=7;i++){…

  • 微信模拟地理位置_伪装微信地理位置

    微信模拟地理位置_伪装微信地理位置1.允许应用程序打开系统窗口,显示其他应用程序2.允许应用程序访问GMail账户列表3.允许应用程序请求从AccountManager验证4.允许应用程序管理AccountManager中的账户列表5.允许应用程序通过账户验证方式访问账户管理ACCOUNT_MANAGER相关信息6.允许应用程序获取网络信息状态7.允许应用程序访问网络连接8.允许应用程序获取模拟定位信息用于开发者调试应用9.允许应…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号