番禺网站开发公司电话,河南郑州网站制作公司,WordPress飞不起来,群晖wordpress php 7.0目录
一、字符串流 1.1 字符串流继承体系 1.2 字符串流本质-类模板std::basic_stringstream 1.3 字符串流缓冲-std::stringbuf 1.4 stringbuf与序列缓冲 1.5 字符串流的打开模式
二、字符串流的运用 2.1 格式转换是其拿手好戏 2.2 字符串流仅提供移动赋值 2.3 std::basic_str…目录
一、字符串流 1.1 字符串流继承体系 1.2 字符串流本质-类模板std::basic_stringstream 1.3 字符串流缓冲-std::stringbuf 1.4 stringbuf与序列缓冲 1.5 字符串流的打开模式
二、字符串流的运用 2.1 格式转换是其拿手好戏 2.2 字符串流仅提供移动赋值 2.3 std::basic_stringstream不仅仅是字符串支持 2.4 字符串流在信息拼接上也有独到之处 三、演示源代码补充 一、字符串流 1.1 字符串流继承体系 c的设备抽象层IO流iostream/ostream/istream派生了两个体系一个是文件流(fstream/ofstream/ifstream)另一个则是字符串流即内存流stringstream/ostringstream/istringstream字符串输入输出、字符串输出、字符串输入。另外字符串流的每个类都有一个对应的宽字符集版本。一般情况下使用stringstream就足够因为字符串要频繁的涉及到输入输出。 因此本专栏本专题前面讲述的设备抽象层IO流所具有的能力例如打开标志、流状态管理、缓冲区管理、寻位、格式化、回调等这些就不再本文展开字符串流同样具备并在应用过程中发现和抽象层IO流、文件流很大一部分功能是重合的那么为何还需要一个字符串流呢为何 字符串类string功能不能胜任其应用呢。 stringstream类既然命名为字符串流那么它最大的特点就是流特性了开发者可以向“流水”一样向stringstream对象传递数据。
#include iostream
#include sstreamvoid stringstream_first_test(void)
{std::stringstream ss;ss hello ;ss world!;ss std::endl;ss Im c developer!;std::cout ss.str() std::endl;
}
//out log
D:\workForMy\workspace\io_c_test3test.exe
hello world!
Im c developer! 1.2 字符串流本质-类模板std::basic_stringstream 类似于文本流stringstream类的本质实现来自于类模板std::basic_stringstream的特化即
namespace std {templateclass CharT, class Traits char_traitsCharT,class Allocator allocatorCharTclass basic_stringbuf;using stringbuf basic_stringbufchar;using wstringbuf basic_stringbufwchar_t;templateclass CharT, class Traits char_traitsCharT,class Allocator allocatorCharTclass basic_istringstream;using istringstream basic_istringstreamchar;using wistringstream basic_istringstreamwchar_t;templateclass CharT, class Traits char_traitsCharT,class Allocator allocatorCharTclass basic_ostringstream;using ostringstream basic_ostringstreamchar;using wostringstream basic_ostringstreamwchar_t;templateclass CharT, class Traits char_traitsCharT,class Allocator allocatorCharTclass basic_stringstream;using stringstream basic_stringstreamchar;using wstringstream basic_stringstreamwchar_t;
}; std::basic_stringstream是一个类模板实现基于字符串的流上的输入与输出操作。将前面的例子替换为std::basic_stringstreamchar对象测试看看
void basic_stringstream_test(void)
{std::basic_stringstreamchar ss;ss hello ;ss world!;ss std::endl;ss Im c developer!;std::cout ss.str() std::endl;
}
//main.cppstringstream_first_test();basic_stringstream_test();
//out log 是一致的
D:\workForMy\workspace\io_c_test3test.exe
hello world!
Im c developer!
hello world!
Im c developer! 1.3 字符串流缓冲-std::stringbuf std::basic_stringstream它等效地存储一个 std::basic_stringbasic_stringstreamchar 的实例并在其上进行输入与输出操作。该类实际上在低层包装 std::basic_stringbuf 的原生字符串设备到 std::basic_iostream 的高层接口中。提供到独有 std::basic_stringbuf 成员的完整接口即字符串流的缓冲区及相关处理功能由std::stringbuf(std::basic_stringbufchar)类来完成的。
//定义于头文件 sstream
template class CharT,class Traits std::char_traitsCharT,class Allocator std::allocatorCharTclass basic_stringstream; 类型 定义
stringstream basic_stringstreamchar
wstringstream basic_stringstreamwchar_t 成员类型 定义
char_type CharT
traits_type Traits 若 Traits::char_type 不是 CharT 则程序非良构。
int_type Traits::int_type
pos_type Traits::pos_type
off_type Traits::off_type
allocator_type Allocator 成员函数
(构造函数) 构造字符串流(公开成员函数)
operator (C11)移动字符串流(公开成员函数)
swap (C11)交换两个字符串流(公开成员函数)
rdbuf 返回底层未处理的字符串设备对象(公开成员函数) 字符串操作
str 获取或设置底层字符串设备对象的内容(公开成员函数)
view (C20)获得底层字符串设备的内容上的视图(公开成员函数) 非成员函数
std::swap(std::basic_istringstream) (C11)特化 std::swap 算法(函数模板) //相关父类的成员和设备抽象层IO流、文件流是一致的这里就不详细给出可以参看前面博文
【1】***继承自 std::basic_istream省略
【2】***继承自 std::basic_ostream省略
【3】***继承自 std::basic_ios省略
【4】***继承自 std::ios_base省略 std::basic_stringbuf 是关联字符序列为内存常驻的任意字符序列的 std::basic_streambuf 。能从 std::basic_string 的实例初始化它或将它做成该类的实例。
//定义于头文件 sstream
template class CharT,class Traits std::char_traitsCharT,class Allocator std::allocatorCharTclass basic_stringbuf : public std::basic_streambufCharT, Traits std::basic_stringbuf 的典型实现保有一个 std::basic_string 类型对象或等价的可伸缩序列容器作为数据成员并将它同时用作受控制字符序列为 std::basic_streambuf 的六个指针所指向的数组和关联字符序列所有输入操作的字符源和输出操作的目标。另外典型的实现保有一个 std::ios_base::openmode 类型的数据成员以指示流的状态只读、只写、读写、尾端写等。若 overflow() 使用过分配策略则可存储另外的高水位指针以跟踪最后初始化的字符。 (C11 起)。
公开成员函数
(构造函数) 构造一个 basic_stringbuf 对象(公开成员函数)
operator (C11)赋值 basic_stringbuf 对象(公开成员函数)
swap (C11)交换二个 basic_stringbuf 对象(公开成员函数)
(析构函数) [虚](隐式声明)析构 basic_stringbuf 对象和其所保有的 string(虚公开成员函数)
str 替换或获得关联字符串的副本(公开成员函数)
get_allocator (C20)获得与内部 basic_string 关联的分配器的副本(公开成员函数)
view (C20) 获得底层字符序列上的视图(公开成员函数) 受保护成员函数
underflow [虚] 返回输入序列中可用的下一字符(虚受保护成员函数)
pbackfail [虚] 回放字符到输出序列中(虚受保护成员函数)
overflow [虚] 后附字符到输出序列(虚受保护成员函数)
setbuf [虚] 试图以数组替换受控字符序列(虚受保护成员函数)
seekoff [虚] 用相对寻址重定位输入序列、输出序列或两者中的下一位置指针(虚受保护成员函数)
seekpos [虚] 用绝对寻址重定位输入序列、输出序列或两者中的下一位置指针(虚受保护成员函数) 非成员函数
std::swap(std::basic_stringbuf) (C11)特化std::swap算法(函数模板) //父类streambuf这里就不详细给出可以参看前面博文
【1】***继承自 std::basic_streambuf 1.4 stringbuf与序列缓冲 stringbuf在输入输出序列上的操作大多是受保护的虚函数开发者可以继承stringbuf类然后在派生类重载这些函数以实现与项目开发切合的额外功能。如果stringstream对象想直接调用这些已经实现的这些虚实现例如setbuf需要通过rdbuf函数先获得stringbuf对象指针才能进行调用。
void basic_stringstream_test1(void)
{std::basic_stringstreamchar ss;char c[256] {0};ss.rdbuf()-pubsetbuf(c, 256);ss hello ;ss world!;ss std::endl;ss Im c developer!;std::cout --------1--------\n;std::cout ss.str() std::endl;std::cout --------2--------\n;std::cout c std::endl;
}
//out log
--------1--------
hello world!
Im c developer!
--------2--------
hello world!
Im c developer! 上述代码将一个字符数组设置为stringstream的缓冲序列stringstream对象输入输出的数据均就改换成这个字符数组存储管理可看到通过str函数返回值对象是stringbuf输出stringstream的存储内容和直接输出字符数组内容是一致的。 同一字符数组可以先后与不同字符串流 (str_in 或 str_out) 建立关联分别对用一字符数组进行操作甚至可以对字符数组交叉进行读写。 1.5 字符串流的打开模式 虽然说stringstream不像文件流一样需要打开文件没有提供如open这样的函数但是stringstream可以把缓冲内存块看着是文件它同样具有打开模式的设置主要体现在其构造函数中(istringstream/ostringstream类似)
/*以默认打开模式构造新的底层字符串设备*/
basic_stringstream(): basic_stringstream(std::ios_base::in | std::ios_base::out) { }//(C11 起) /*构造新的底层字符串设备。
*以 basic_stringbufChar,Traits,Allocator(mode) 构造底层 basic_stringbuf 对象*/
explicit basic_stringstream( std::ios_base::openmode mode std::ios_base::in | std::ios_base::out );// (C11 前)
explicit basic_stringstream( std::ios_base::openmode mode );//(C11 起) /*以 str 的副本为底层字符串设备的初始内容。
*以 basic_stringbufChar,Traits,Allocator(str, mode) 构造底层 basic_stringbuf 对象。*/
explicit basic_stringstream( const std::basic_stringCharT,Traits,Allocator str,std::ios_base::openmode mode std::ios_base::in | std::ios_base::out );/*移动构造函数。用移动语义构造拥有 other 的状态的字符串流。*/
basic_stringstream( basic_stringstream other );// (C11 起) /*构造新的底层字符串设备。
*以 basic_stringbufChar,Traits,Allocator(mode, a) 构造底层 basic_stringbuf 对象。*/
basic_stringstream( std::ios_base::openmode mode, const Allocator a );//(C20 起) /*用 str 移动构造底层字符串设备的内容。
*以basic_stringbufChar,Traits,Allocator(std::move(str), mode)构造basic_stringbuf对象*/
explicit basic_stringstream( std::basic_stringCharT,Traits,Allocator str,std::ios_base::openmode mode std::ios_base::in | std::ios_base::out );//(C20 起) /*构造新的底层字符串设备。
*以basic_stringbufChar,Traits,Allocator(str, std::ios_base::in | std::ios_base::out, a)
*构造底层 basic_stringbuf 对象。*/
templateclass SAlloc
basic_stringstream( const std::basic_stringCharT,Traits,SAlloc str,const Allocator a ): basic_stringstream(str, std::ios_base::in | std::ios_base::out, a) { } //(C20 起) /*构造新的底层字符串设备。
*以 basic_stringbufChar,Traits,Allocator(str, mode, a) 构造底层 basic_stringbuf 对象。*/
templateclass SAlloc
basic_stringstream( const std::basic_stringCharT,Traits,SAlloc str,std::ios_base::openmode mode, const Allocator a ); // (C20 起)
/*构造新的底层字符串设备。
*以 basic_stringbufChar,Traits,Allocator(str, mode) 构造底层 basic_stringbuf 对象。
*此重载仅若 SAlloc 与 Allocator 不是同一类型才参与重载决议。*/
templateclass SAlloc
explicit basic_stringstream( const std::basic_stringCharT,Traits,SAlloc str,std::ios_base::openmode mode std::ios_base::in | std::ios_base::out ); // (C20 起) 在构造时可显示指定打开标志这些数值是下列常量的组合‘|’
app 每次写入前寻位到流结尾
binary 以二进制模式打开
in 为读打开
out 为写打开
trunc 在打开时舍弃流的内容
ate 打开后立即寻位到流结尾 字符串流类没有open成员函数, 通过调用构造函数建立字符串流对象。支持传入指向字符数组首元素的指针, 用它来初始化流对象可以设置openmode是上述常量的组合显式指明操作方式。
void basic_stringstream_test2(void)
{char c;std::istringstream in; //std::stringstream in(std::ios_base::in); //实际in.str(a b);in c;std::cout c c , str() \ in.str() \\n;// in c; //error无效不存在该功能std::ostringstream out(a b);//std::ostringstream out(a b,std::ios_base::out);//实际out c;std::cout str() \ out.str() \\n;// out c; //error无效不存在该功能std::stringstream ate1(a b , std::ios_base::ate);ate1 c; //编译正确但无效。std::ios_base::out没开启std::cout ate1.str() \ ate1.str() \\n;std::stringstream ate2(a b , std::ios_base::out | std::ios_base::ate);ate2 c;std::cout ate2.str() \ ate2.str() \\n;
}
二、字符串流的运用 2.1 格式转换是其拿手好戏 stringstream支持有格式输入输出operator/operatorstringstream通常是用来做数据转换的用于字符串与其他变量类型的转换它是安全自动和直接的。通过字符串流从字符数组或字符串读数据就如同从键盘读数据一样, 可以从字符数组读入字符数据, 也可以读入整数, 浮点数或其他类型数据。
//类似的可以写出其他类型的转换或采用模板函数实现各种类型转换
int strToInt(const char* str)
{int ret 0;std::stringstream strBufer(str);if(!(strBuferret))std::cout strToInt error std::endl;return ret;
}void stringstream_user_test1(void)
{std::string str1(hello 1234 0 4.368);std::stringstream ss(str1);//构造函数初始化std::coutss.str()std::endl;std::string str2;if(ssstr2){std::cout str2 str2 std::endl;}int a;if(ssa){std::cout a a std::endl;}bool b;// ssstd::boolalpha;if(ssb){std::cout b b std::endl;}float c;if(ssc){std::cout c c std::endl;}ss.clear();ss.str( I am learning c stringstream!);//重新赋值while(ssstr2)//不断读取{ std::coutstr2 ;} std::cout std::endl;const char *pi 1314;std::cout strToInt(pi) strToInt(pi) std::endl;
}
//out log
hello 1234 0 4.368
str2 hello
a 1234
b 0
c 4.368
I am learning c stringstream!
strToInt(pi) 1314 在实际开发过程中对于那些悬而未决的混合字段信息采用stringstream系列来存储等到具体数据处理实现时再添加确切类型支持是个不错的选择。 2.2 字符串流仅提供移动赋值 stringstream系列类型支持移动赋值但不支持复制赋值它是通过stringbuf来熟悉的
//std::basic_stringbufCharT,Traits,Allocator::operator
/*
*移动赋值运算符移动 rhs 的内容到 *this 中。
*移动后 *this 拥有 rhs 之前保有的关联 string 、打开模式、本地环境和所有其他状态。
*保证 *this 中 std::basic_streambuf 的六个指针有别于被移动的 rhs 的对应指针除非它们为空。
*/
std::basic_stringbuf operator( std::basic_stringbuf rhs );// (C11 起) /*复制赋值运算符被删除basic_stringbuf 不可复制赋值 (CopyAssignable) 。*/
std::basic_stringbuf operator( const std::basic_stringbuf rhs ) delete;//std::basic_stringstream::operator
/*
*移动赋值字符串流 other 给 *this 。
*/
basic_stringstream operator( basic_stringstream other );//(C11 起) stringstream对象的移动赋值等效的移动赋值 std::basic_iostream 基类和关联的 std::basic_stringbuf基类移动赋值交换 *this 与 other 间的所有流状态变量除了 rdbuf other 的内容被清除流状态被重置。
void stringstream_user_test2(void)
{std::stringstream in(in);std::stringstream out(out);std::cout Before move, int \ in.str() out \ out.str() \\n;*in.rdbuf() std::move(*out.rdbuf());std::cout After move, in \ in.str() out \ out.str() \\n;std::stringstream ss;ss std::move(in);std::cout After move again, in \ in.str() ss \ ss.str() \\n;
}
//out log
Before move, int in out out
After move, in out out
After move again, in ss out 如果想与other的字符串流交换它们的内容及流状态就采用交换函数swap。
//std::basic_stringstream::swap
//交换流与 other 的状态。
void swap( basic_stringstream other );//(C11 起) stringstream对象的交换实现本质上是通过调用 basic_iostreamCharT, Traits::swap(other) 和 rdbuf()-swap(*other.rdbuf()) 进行。
void stringstream_user_test3(void)
{std::stringstream in(in);std::stringstream out(out);std::cout Before swap, int \ in.str() out \ out.str() \\n;in.swap(out);//out.swap(in);std::cout After swap, in \ in.str() out \ out.str() \\n;
}
//out log
Before swap, int in out out
After swap, in out out in 2.3 std::basic_stringstream不仅仅是字符串支持 需要记住的是std::basic_stringstream是一个类模板stringstream是其特化类而已采用std::basic_stringstream支持其他类型也可以实现类似流效果
void stringstream_user_test4(void)
{int a[10] {1,2,3,4,5,6};std::basic_stringstreamint ss(a);// std::basic_stringstreamint ss; // ss.rdbuf()-pubsetbuf(a, 10);int n 0;int index 0;while(index6 ss.read(n,1)){std::cout a[index] n \n;index;}
}
//out loga[0] 1a[1] 2a[2] 3a[3] 4a[4] 5a[5] 6 2.4 字符串流在信息拼接上也有独到之处 相对于用stringstream将字段信息拆分获得不同数据类型的信息也可以采用stringstream类将不同类型的数据信息进行混合拼接获得所需的字段信息这在词汇组织处理上有独到之处。
void stringstream_user_test5(void)
{std::stringstream ss;int a 34;int b 27;ss now we count a multiply b the val is a*b;std::cout ss \ ss.str() \\n;
}
//out log
ss now we count 34 multiply 27 the val is 918 关于字符串流IO的主要内容介绍到此结束 感谢读友能耐心看到最后本人文章都很长知识点很细可能会有所遗漏和失误如果有不妥之处烦请指出。如果内容对您有所触动请点赞关注一下防止不迷路。 三、演示源代码补充 编译指令g main.cpp test*.cpp -o test.exe -stdc11 main.cpp
#include test1.hint main(int argc, char* argv[])
{stringstream_first_test();basic_stringstream_test();basic_stringstream_test1();basic_stringstream_test2();stringstream_user_test1();stringstream_user_test2();stringstream_user_test3();stringstream_user_test4();stringstream_user_test5();return 0;
} test1.h
#ifndef _TEST_1_H_
#define _TEST_1_H_void stringstream_first_test(void);
void basic_stringstream_test(void);
void basic_stringstream_test1(void);
void basic_stringstream_test2(void);
void stringstream_user_test1(void);
void stringstream_user_test2(void);
void stringstream_user_test3(void);
void stringstream_user_test4(void);
void stringstream_user_test5(void);
#endif //_TEST_1_H_ test1.cpp
#include test1.h#include iostream
#include sstreamvoid stringstream_first_test(void)
{std::stringstream ss;ss hello ;ss world!;ss std::endl;ss Im c developer!;std::cout ss.str() std::endl;
}void basic_stringstream_test(void)
{std::basic_stringstreamchar ss;ss hello ;ss world!;ss std::endl;ss Im c developer!;std::cout ss.str() std::endl;
}void basic_stringstream_test1(void)
{std::basic_stringstreamchar ss;char c[256] {0};ss.rdbuf()-pubsetbuf(c, 256);ss hello ;ss world!;ss std::endl;ss Im c developer!;std::cout --------1--------\n;std::cout ss.str() std::endl;std::cout --------2--------\n;std::cout c std::endl;
}void basic_stringstream_test2(void)
{char c;std::istringstream in; //std::stringstream in(std::ios_base::in); //实际in.str(a b);in c;std::cout c c , str() \ in.str() \\n;// in c; //error无效不存在该功能std::ostringstream out(a b);//std::ostringstream out(a b,std::ios_base::out);//实际out c;std::cout str() \ out.str() \\n;// out c; //error无效不存在该功能std::stringstream ate1(a b , std::ios_base::ate);ate1 c; //编译正确但无效。std::ios_base::out没开启std::cout ate1.str() \ ate1.str() \\n;std::stringstream ate2(a b , std::ios_base::out | std::ios_base::ate);ate2 c;std::cout ate2.str() \ ate2.str() \\n;
}
//类似的可以写出其他类型的转换或采用模板函数实现各种类型转换
int strToInt(const char* str)
{int ret 0;std::stringstream strBufer(str);if(!(strBuferret))std::cout strToInt error std::endl;return ret;
}void stringstream_user_test1(void)
{std::string str1(hello 1234 0 4.368);std::stringstream ss(str1);//构造函数初始化std::coutss.str()std::endl;std::string str2;if(ssstr2){std::cout str2 str2 std::endl;}int a;if(ssa){std::cout a a std::endl;}bool b;// ssstd::boolalpha;if(ssb){std::cout b b std::endl;}float c;if(ssc){std::cout c c std::endl;}ss.clear();ss.str( I am learning c stringstream!);//重新赋值while(ssstr2)//不断读取{ std::coutstr2 ;} std::cout std::endl;const char *pi 1314;std::cout strToInt(pi) strToInt(pi) std::endl;
}void stringstream_user_test2(void)
{std::stringstream in(in);std::stringstream out(out);std::cout Before move, int \ in.str() out \ out.str() \\n;*in.rdbuf() std::move(*out.rdbuf());std::cout After move, in \ in.str() out \ out.str() \\n;std::stringstream ss;ss std::move(in);std::cout After move again, in \ in.str() ss \ ss.str() \\n;
}void stringstream_user_test3(void)
{std::stringstream in(in);std::stringstream out(out);std::cout Before swap, int \ in.str() out \ out.str() \\n;in.swap(out);//out.swap(in);std::cout After swap, in \ in.str() out \ out.str() \\n;
}void stringstream_user_test4(void)
{int a[10] {1,2,3,4,5,6};std::basic_stringstreamint ss(a);// std::basic_stringstreamint ss; // ss.rdbuf()-pubsetbuf(a, 10);int n 0;int index 0;while(index6 ss.read(n,1)){std::cout a[index] n \n;index;}
}void stringstream_user_test5(void)
{std::stringstream ss;int a 34;int b 27;ss now we count a multiply b the val is a*b;std::cout ss \ ss.str() \\n;
}