如果您想了解golang的strings.TrimLeft有个bug,用strings.TrimPrefix代替的相关知识,那么本文是一篇不可错过的文章,我们将对golangstring方法进行全面详
如果您想了解golang 的 strings.TrimLeft 有个 bug,用strings.TrimPrefix代替的相关知识,那么本文是一篇不可错过的文章,我们将对golang string方法进行全面详尽的解释,并且为您提供关于c++中istringstream及ostringstream超详细说明、c++的输入输出 [三](istringstream,ostringstream,stringstream)、C++:利用stringstream对数字和string互相转换、Codeforces 914F. Substrings in a String(bitset)的有价值的信息。
本文目录一览:- golang 的 strings.TrimLeft 有个 bug,用strings.TrimPrefix代替(golang string方法)
- c++中istringstream及ostringstream超详细说明
- c++的输入输出 [三](istringstream,ostringstream,stringstream)
- C++:利用stringstream对数字和string互相转换
- Codeforces 914F. Substrings in a String(bitset)
golang 的 strings.TrimLeft 有个 bug,用strings.TrimPrefix代替(golang string方法)
https://github.com/golang/go/issues/25328
just for a demo func main() { cfgs := "mongodb://off" cfgs = strings.TrimLeft(cfgs,"mongodb://") fmt.Printf("cfgs:%v\n",cfgs) //output ==> cfgs:ff }
c++中istringstream及ostringstream超详细说明
前文说过,istringstream是继承于istream,ostringstream是继承于ostream,而他们使用的缓冲区类是stringbuf。
关于这些类之间的关系,有兴趣可以去查看我之前的文章:
c++标准输入输出流关系梳理
1. stringbuf类介绍
stringbuf类缓冲区使用一个std::string类作为存储介质,然后根据构造时的读写模式来对string类进行读写。
1.1 stringbuf类构造函数
小贴士:explicit用来防止由构造函数定义的隐式转换。
//根据传入的读写标示构造一个拥有空string的缓冲区,默认可读可写
explicit basic_stringbuf(ios_base::openmode __mode = ios_base::in | ios_base::out)
: __streambuf_type(), _M_mode(__mode), _M_string()
{ }
//复制一个已有的string作为缓冲区内容,且根据__mode来指定可读、可写或者读写,默认可读可写
explicit basic_stringbuf(const __string_type& __str,
ios_base::openmode __mode = ios_base::in | ios_base::out)
: __streambuf_type(), _M_mode(), _M_string(__str.data(), __str.size())
{ _M_stringbuf_init(__mode); }
使用例子如下:
#include <sstream>
using namespace std;
int main()
{
stringbuf *buf = new stringbuf(ios_base::in);//构造一个可写的空stringbuf
string str("my name is haha");
stringbuf *bufStr = new stringbuf(str, ios_base::out);
if ( buf != nullptr )
{
delete buf;
}
if ( bufStr != nullptr )
{
delete bufStr;
}
return 0;
}
1.2 str函数
str函数原型如下:
//获取string内容
__string_type
str() const;
//参数__s中内容初始化为当前缓冲区string
void
str(const __string_type& __s);
使用案例如下:
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
stringbuf *buf = new stringbuf(ios_base::in);
string str("my name is haha");
stringbuf *bufStr = new stringbuf(str, ios_base::out);
cout << bufStr->str() << endl;
buf->str(string("my name is not haha"));
cout << buf->str() << endl;
if ( buf != nullptr )
{
delete buf;
}
if ( bufStr != nullptr )
{
delete bufStr;
}
return 0;
}
还有其他函数这里就不多做介绍了,理论上来讲,我们并不会直接使用stringbuf,因为它只是一个工具人,是藏于暗中滴,大多数时候,我们都是直接使用istringstream和ostringstream。
2. istringstream类
前文说过,实际上istringstream全名应该是basic_istringstream,istringstream只是basic_istringstream的一个char类型实例,下面还是直接使用istringstream来进行代指。
istringstream的构造函数与stringbuf的参数以及类型一模一样,所以直接按照stringbuf的构造函数用法一样使用即可,只是流打开模式上而言,istringstream默认是ios_base::in。
截取构造函数原型如下:
explicit
basic_istringstream(ios_base::openmode __mode = ios_base::in)
: __istream_type(), _M_stringbuf(__mode | ios_base::in)
{ this->init(&_M_stringbuf); }
explicit
basic_istringstream(const __string_type& __str,
ios_base::openmode __mode = ios_base::in)
: __istream_type(), _M_stringbuf(__str, __mode | ios_base::in)
{ this->init(&_M_stringbuf); }
另外istringstream的str函数也是与stringbuf一样,返回了string对象,这里不再多说。
2.1 rdbuf函数
rdbuf函数原型如下:
//返回一个指向stringbuf对象的指针
__stringbuf_type*
rdbuf() const
{ return const_cast<__stringbuf_type*>(&_M_stringbuf); }
rdbuf使用案例如下:
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
istringstream istr("istringstream", ios_base::in);
cout << "string is " << istr.str() << endl;
cout << "string''s len is " << istr.rdbuf()->in_avail() << endl;
return 0;
}
这里也顺便展示了一下str函数的用法,in_avail是streambuf类里面的一个函数,用于返回当前缓冲区长度。
编译后执行结果如下:
[root@mylinux ~]# ./a.out
string is istringstream
string''s len is 13
[root@mylinux ~]#
2.2 swap函数
swap函数原型如下:
//用于交换两个istringstream内容
void swap(basic_istringstream& __rhs);
用法如下:
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
istringstream istr1("lilei");
istringstream istr2("hanmeimei");
istr1.swap(istr2);
cout << "istr1 is " << istr1.str() << endl;
cout << "istr2 is " << istr2.str() << endl;
return 0;
}
编译后输出结果如下:
[root@mylinux ~]# ./a.out
istr1 is hanmeimei
istr2 is lilei
[root@mylinux ~]#
可以看到istr1和istr2两个对象的内容是完全交换了。
3.ostringstream类和stringstream类
ostringstream用于往string写入数据,除了构造的时候,默认的打开模式是ios_base::out,其他所有函数都与istringstream一样,且用法也是一样的,这里不再多说。
截取其中一个构造函数原型如下:
//只是构造函数默认参数不一样,其他与istringstream是一样的
explicit
basic_ostringstream(ios_base::openmode __mode = ios_base::out)
: __ostream_type(), _M_stringbuf(__mode | ios_base::out)
{ this->init(&_M_stringbuf); }
stringstream是继承于iostream类,它除了构造函数默认模式不一样,其他所有函数也与istringstream用法一样
,它的构造函数原型如下:
explicit
basic_stringstream(ios_base::openmode __m = ios_base::out | ios_base::in)
: __iostream_type(), _M_stringbuf(__m)
{ this->init(&_M_stringbuf); }
stringstream可用于同时往string写入和读取数据。
c++的输入输出 [三](istringstream,ostringstream,stringstream)
写在最前面
我这篇博文是根据别人的博文整理而成的,所以出现和别人一样的地方是我摘抄的,我会注明。
这份笔记我分成了三章,分别讲下面的三个部分。
基础介绍
c++的输入输出分为三种:
1.基于控制台的I/O
2.基于文件的I/O
3.基于字符串的I/O
第三种 基于字符串的I/O
这部分参考 istringstream、ostringstream、stringstream 类介绍 . 以及 ostringstream的用法
在过去,我们使用的是原始的<stdio.h>中的接口,但是今天我想讲的是一个新的库<sstream>,这个库拥有拥有类型安全和不会溢出这样抢眼的特性,很有理由让我们使用它。下面我将详述。
头文件
#include<sstream>
作用
istringstream类用于执行C++风格的字符串流的输入操作。
ostringstream类用于执行C++风格的字符串流的输出操作。
strstream类同时可以支持C++风格的串流的输入输出操作。
为什么我们要学
如果你已习惯了<stdio.h>风格的转换,也许你首先会问:为什么要花额外的精力来学习基于<sstream>的类型转换呢?也许对下面一个简单的例子的回顾能够说服你。假设你想用sprintf()函数将一个变量从int类型转换到字符串类型。为了正确地完成这个任务,你必须确保证目标缓冲区有足够大空间以容纳转换完的字符串。此外,还必须使用正确的格式化符。如果使用了不正确的格式化符,会导致非预知的后果。下面是一个例子:
int n=10000;
chars[10];
sprintf(s,”%d”,n);// s中的内容为“10000”
到目前为止看起来还不错。但是,对上面代码的一个微小的改变就会使程序崩溃:
int n=10000;
char s[10];
sprintf(s,”%f”,n);// 看!错误的格式化符
在这种情况下,程序员错误地使用了%f格式化符来替代了%d。因此,s在调用完sprintf()后包含了一个不确定的字符串。要是能自动推导出正确的类型,那不是更好吗?
进入stringstream
由于n和s的类型在编译期就确定了,所以编译器拥有足够的信息来判断需要哪些转换。<sstream>库中声明的标准类就利用了这一点,自动选择所必需的转换。而且,转换结果保存在stringstream对象的内部缓冲中。你不必担心缓冲区溢出,因为这些对象会根据需要自动分配存储空间。
具体分析
istringstream类
描述:从流中提取数据,支持 >> 操作
这里字符串可以包括多个单词,单词之间使用空格分开
istringstream的构造函数原形:
istringstream::istringstream(string str);
初始化:使用字符串进行初始化
istringstream istr("1 56.7");
istr.str("1 56.7");//把字符串"1 56.7"存入字符串流中
使用:我们可以使用分解点获取不同的数据,完成 字符串 到 其他类型 的转换
常用成员函数:
str():使istringstream对象返回一个string字符串
举例:把字符串类型的数据转换为其他类型
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
istringstream istr("1 56.7");
cout<<istr.str()<<endl;//直接输出字符串的数据 "1 56.7"
string str = istr.str();//函数str()返回一个字符串
cout<<str<<endl;
int n;
double d;
//以空格为界,把istringstream中数据取出,应进行类型转换
istr>>n;//第一个数为整型数据,输出1
istr>>d;//第二个数位浮点数,输出56.7
//假设换下存储类型
istr>>d;//istringstream第一个数要自动变成浮点型,输出仍为1
istr>>n;//istringstream第二个数要自动变成整型,有数字的阶段,输出为56
//测试输出
cout<<d<<endl;
cout<<n<<endl;
system("pause");
return 1;
}
举例2:把一行字符串放入流中,单词以空格隔开。之后把一个个单词从流中依次读取到字符串
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
istringstream istr;
string line,str;
while (getline(cin,line))//从终端接收一行字符串,并放入字符串line中
{
istr.str(line);//把line中的字符串存入字符串流中
while(istr >> str)//每次读取一个单词(以空格为界),存入str中
{
cout<<str<<endl;
}
}
system("pause");
return 1;
}
ostringstream类
描述:把其他类型的数据写入流(往流中写入数据),支持<<操作
ostringstream的构造函数原形:
ostringstream::ostringstream(string str);
初始化:使用字符串进行初始化
ostringstream ostr("1234");
ostr.str("1234");//把字符串"1234"存入字符串流中
举例:
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
//初始化输出字符串流ostr
ostringstream ostr("1234");
cout<<ostr.str()<<endl;//输出1234
ostr.put(''5'');//字符5顶替了1的位置
cout<<ostr.str()<<endl;//输出5234
ostr<<"67";//字符串67替代了23的位置,输出5674
string str = ostr.str();
cout<<str<<endl;
system("pause");
return 1;
}
上面这个实例可能看起来有点奇怪,其实是不了解put的使用,看看下面这段代码应该就懂了。
/*----------------------------------------------------------------------------
*** 建议:在用put()方法时,先查看当前put pointer的值,防止误写
----------------------------------------------------------------------------*/
long curPos = ostr2.tellp(); //返回当前插入的索引位置(即put pointer的值),从0开始
cout << "curPos = " << curPos << endl;
ostr2.seekp(2); // 手动设置put pointer的值
ostr2.put(''g''); // 在put pointer的位置上写入''g'',并将put pointer指向下一个字符位置
cout << ostr2.str() << endl;
下面有个很实用很技巧的应用:
在类型转换中使用模板
你可以轻松地定义函数模板来将一个任意的类型转换到特定的目标类型。例如,需要将各种数字值,如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;
}
这样使用convert():
double d;
string salary;
string s=”12.56”;
d=convert<double>(s);//d等于12.56
salary=convert<string>(9000.0);//salary等于”9000”
stringstream类
描述:是对istringstream和ostringstream类的综合,支持<<, >>操作符,可以进行字符串到其它类型的快速转换
stringstream的构造函数原形如下:
stringstream::stringstream(string str);
初始化:使用字符串进行初始化
stringstream str("1234");
str.str("1234");//把字符串"1234"存入字符串流中
作用:
stringstream通常是用来做数据转换的
将文件的所有数据一次性读入内存
举例1:基本数据类型变字符串
/*基本数据类型变字符串*/
#include <fstream>
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
/*整型变字符串*/
int n = 10;
string str;
stringstream stream;
stream << n;
stream >> str;
cout<<str<<endl;
stream.clear();//多次使用stringstream,要先清空下,不能使用stream.str("");否则下面输出10
/*char* 变 string*/
char cStr[10] = "china";
stream << cStr;
stream >> str;
cout<<str<<endl;
system("pause");
return 1;
}
举例2:字符串变基本数据类型
/*字符串变基本数据类型*/
#include <fstream>
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
/*字符串 变 double*/
double n;
string str = "12.5";
stringstream stream;
stream << str;
stream >> n;
cout<<n<<endl;
stream.clear();//多次使用stringstream,要先清空下,不能使用stream.str("");
/*string 变 char* */
string str1 = "china";
char cStr[10];
stream << str1;
stream >> cStr;
cout<<cStr<<endl;//输出china
system("pause");
return 1;
}
注意:
#include <iostream>
#include <sstream>
using namespace std;
int main(int argc,char *argv[])
{
std::stringstream stream;
string str;
while(1)
{
//clear(),这个名字让很多人想当然地认为它会清除流的内容。
//实际上,它并不清空任何内容,它只是重置了流的状态标志而已!
stream.clear();
// 去掉下面这行注释,清空stringstream的缓冲,每次循环内存消耗将不再增加!
//stream.str("");
stream<<"sdfsdfdsfsadfsdafsdfsdgsdgsdgsadgdsgsdagasdgsdagsadgsdgsgdsagsadgs";
stream>>str;
//测试输出每次循环,你的内存消耗增加了多少!
cout<<"Size of stream = "<<stream.str().length()<<endl;
system("PAUSE");
}
system("PAUSE");
return EXIT_SUCCESS;
}
由于stringstream构造函数会特别消耗内存,似乎不打算主动释放内存(或许是为了提高效率),但如果你要在程序中用同一个流,反复读写大量的数据,将会造成大量的内存消耗,因些这时候,需要适时地清除一下缓冲 (用 stream.str("") )。
另外不要企图用 stream.str().resize(0),或 stream.str().clear() 来清除缓冲,使用它们似乎可以让stringstream的内存消耗不要增长得那么快,但仍然不能达到清除stringstream缓冲的效果,内存的消耗还在缓慢的增长!,至于stream.flush(),则根本就起不到任何作用。
C++:利用stringstream对数字和string互相转换
需要#include <sstream>
。
数字转换为string字符串
#include <iostream>
#include <sstream>
int main()
{
std::stringstream ss;
ss << 100;
std::cout << ss << std::endl;
std::cout << ss.str() << std::endl;
std::cout << ss.str().compare("10") << std::endl; // 比较字符串
std::cout << ss.str().compare("100") << std::endl;
std::cout << ss.str().compare("102") << std::endl;
std::string data("100");
std::cout << ss.str().compare(data) << std::endl;
}
编译运行:
$ g++ test.cpp
$ ./a.out
0x7ffea3490478
100
1
0
-2
0
ss.str()
是字符串结果。string类型之间比较可以用compare函数,若相等则返回值为0。注意 ,0在条件判断中代表false,所以必须if (a.compare(b)==0)。
如果只是判断是否相等,可以用==
。看下面的示例:
判断字符串是否相等
#include <iostream>
int main()
{
std::string s1 = "zz";
std::string s2 = "zz";
std::cout << (s1 == s2) << std::endl; // 1
std::cout << ("a" == "a") << std::endl; // 1
std::cout << ("a" == "b") << std::endl; // 0
if(s1.compare(s2) == 0) {
std::cout << "s1 == s2" << std::endl;
}
if(s1 == s2) {
std::cout << "s1 == s2" << std::endl;
}
}
编译运行:
$ g++ test.cpp
$ ./a.out
1
1
0
s1 == s2
s1 == s2
要判断两个变量名是否指向同一个对象,前提是这两个变量为指针。
字符串转换为数字
这里举个将“-1”转换为两种类型(无符号和有符号)数字的错误例子:
// 错误的代码
#include <iostream>
#include <sstream>
int main()
{
std::stringstream ss;
unsigned int ui;
int i;
std::string s("-1");
ss << s;
ss >> ui;
ss >> i; // 出现错误
std::cout << ui << std::endl;
std::cout << i << std::endl;
}
编译运行结果如下:
$ g++ test.cpp
$ ./a.out
4294967295
32698
stringstream必须进一个出一个,进两个就行出两个。而进一个不能出两个。
所以有以下两种正确的思路:
思路1:
#include <iostream>
#include <sstream>
int main()
{
std::stringstream ss;
unsigned int ui;
int i;
std::string s("-1");
ss << s;
ss << s; // 又进了一次
ss >> ui;
ss >> i;
std::cout << ui << std::endl;
std::cout << i << std::endl;
}
编译运行:
$ g++ test.cpp
$ ./a.out
4294967295
-1
思路2:
#include <iostream>
#include <sstream>
int main()
{
std::stringstream ss;
unsigned int ui;
int i;
std::string s("-1");
ss << s;
ss >> ui;
ss >> i;
ss.clear(); // 必须
ss.str(""); // 必须
ss << s;
ss >> i;
std::cout << ui << std::endl;
std::cout << i << std::endl;
}
编译运行:
$ g++ test.cpp
$ ./a.out
4294967295
-1
注意:
ss.clear(); // 必须
ss.str(""); // 必须
是必须的,若没有,会出现下面的错误结果:
$ ./a.out
4294967295
32652
其中第二个结果每次运行后不一定相同。
其他
stringstream clear()的误区
How do you clear a stringstream variable?
Codeforces 914F. Substrings in a String(bitset)
比赛的时候怎么没看这题啊... 血亏 T T
对每种字符建一个 bitset,修改直接改就好了,查询一个区间的时候对查询字符串的每种字符错位 and 一下,然后用 biset 的 count 就可以得到答案了。。。


#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<bitset>
#define ll long long
using namespace std;
const int maxn=100010, inf=1e9;
int n, ty, l, r, x;
bitset<maxn>v[26], ans;
char s[maxn], s2[maxn], c;
inline void read(int &k)
{
int f=1; k=0; char c=getchar();
while(c<''0'' || c>''9'') c==''-''&&(f=-1), c=getchar();
while(c<=''9'' && c>=''0'') k=k*10+c-''0'', c=getchar();
k*=f;
}
int main()
{
scanf("%s", s+1); int len=strlen(s+1);
for(int i=1;i<=len;i++) v[s[i]-''a''][i]=1;
read(n);
for(int i=1;i<=n;i++)
{
read(ty);
if(ty==1)
{
read(x); scanf("%c", &c);
v[s[x]-''a''][x]=0;
v[(s[x]=c)-''a''][x]=1;
}
else
{
read(l); read(r);
scanf("%s", s2); int m=strlen(s2);
if(r-l+1<m) {puts("0"); continue;}
ans.set();
for(int j=0;j<m;j++) ans&=(v[s2[j]-''a'']>>j);
printf("%d\n", (int)(ans>>(l)).count()-(int)(ans>>(r-m+2)).count());
}
}
}
关于golang 的 strings.TrimLeft 有个 bug,用strings.TrimPrefix代替和golang string方法的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于c++中istringstream及ostringstream超详细说明、c++的输入输出 [三](istringstream,ostringstream,stringstream)、C++:利用stringstream对数字和string互相转换、Codeforces 914F. Substrings in a String(bitset)等相关知识的信息别忘了在本站进行查找喔。
本文标签: