(P61)io流类库:字符串流
原创
©著作权归作者所有:来自51CTO博客作者喜欢打篮球的普通人的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
- 1.字符串流
- 3.istream_iterator与istreambuf_iterator
- (1)istream_iterator
- (2)istreambuf_iterator
1.字符串流
- istringstream,输入字符串流,由istream派生而来,提供读string的功能
- ostringstream,输出字符串流
- stringstream
- eg:P61\01.cpp
#include <iostream>
#include <sstream>
using namespace std;
int main(void)
{
string line;
string word;
// cin.getline();//参数是char*,不能是string
//使用getline方法,因为他是全局的,可以标准输入流,文件流,字符串流都行
//返回值是cin,读取到流结束时,跳出循环
while (getline(cin, line))//读取一行数据到line
{
istringstream iss(line);//构造字符串输入流对象
//相当于C中的sscanf
//字符串流iss关联了字符串line
//相当于从字符串line提取数据到word变量
while (iss >> word)//提取数据到word,这一行有多个单词
cout << word << "#";
cout << endl;
}
return 0;
}
cin.getine()
istream& getline (char* s, streamsize n );istream& getline (char* s, streamsize n, char delim );
std::getline()
istream& getline (istream& is, string& str, char delim);istream& getline (istream&& is, string& str, char delim);
istream& getline (istream& is, string& str);istream& getline (istream&& is, string& str);
跳出循环输入ctrl z(对应Linux系统是ctrl d),相当于一个EOF
- 其他说明
字符串内部有一个缓冲区类stringbuf
每一个输入,输出流类都有一个缓冲区,
字符串流类的缓冲区就是stringbuf,这里可以提供,也可以不提供(自由分配)
- eg:P61\02.cpp
#include <iostream>
#include <sstream>
using namespace std;
//将double数据转换为字符串
string doubletostr( double val)
{
ostringstream oss;
oss << val;//输出到字符串流中,字符串流中的缓冲区就是分配空间,将val塞到这块空间了
//str()返回内部的空间里的字符串
return oss.str(); // return string copy of character array
}
//字符串转double,C语言是strtod
double strtodouble( const string &str)
{
istringstream iss(str);
double val;
iss >> val;//从字符串流iss提取数据到val,而字符串str与字符串流iss相对应,实际上是从字符串str提取数据到val
return val;
}
int main( void)
{
double val = 55. 55;
string str = doubletostr(val);
cout << str << endl;
str = "123.123";
val = strtodouble(str);
cout << val << endl;
return 0;
}
- 测试:
- eg:P61\03.cpp
#include <iostream>
#include <sstream>
using namespace std;
int main( void)
{
//将192,168,0,100字符串转化为192.168.0.100
//sscanf相当于输入流,sprintf相当于输出流;
//字符串输入流+字符串输出流
//istringstream iss("192,168,0,100");
//int v1;
//int v2;
//int v3;
//int v4;
//char ch;
//iss>>v1>>ch>>v2>>ch>>v3>>ch>>v4;//192提取到v1,逗号,提取到ch。。。以此类推
//ch = '.';
//ostringstream oss;//内部会构造缓冲区,相当于sprintf
//oss<<v1<<ch<<v2<<ch<<v3<<ch<<v4;
//cout<<oss.str()<<endl;
//字符串输入输出流
string buf( "192,168,0,100");
stringstream ss(buf);//stringstream ss("192,168,0,100");
int v1;
int v2;
int v3;
int v4;
char ch;
ss >> v1 >> ch >> v2 >> ch >> v3 >> ch >> v4;//相当于输入流对象
ch = '.';
stringstream ss2;
ss2 << v1 << ch << v2 << ch << v3 << ch << v4;//相当于输出流对象
cout << ss2.str() << endl;
return 0;
}
3.istream_iterator与istreambuf_iterator
(1)istream_iterator
假设我们要把一个文本文件拷贝到一个字符串对象中。似乎可以用一种很有道理的方法完成:
ifstream inputFile("d:\\test.plist");
string fileData((istream_iterator<char>(inputFile)), istream_iterator<char>());
很快你就会发现这种方法无法把文件中的空格拷贝到字符串中。
- 那是因为istream_iterators使用operator<<函数来进行真的读取,而且operator<<函数在默认情况下忽略空格。
假如你想保留空格,你要的做就是覆盖默认情况。只要清除输入流的skipws标志就行了:
ifstream inputFile("d:\\test.plist");
inputFile.unset(ios::skipws); // 关闭inputFile的忽略空格标志
string fileData((istream_iterator<char>(inputFile)), istream_iterator<char>());
现在inputFile中的所有字符都拷贝到fileData中了。
此时,你会发现它们的拷贝速度不像你想象的那么快。
istream_iterators所依靠的operator<<函数进行的是格式化输入,这意味着,每次你调用的时候它们都必须做大量工作。它们必须建立和销毁sentry对象(为每个operator<<调用进行建立和清除活动的特殊的iostream对象),
它们必须检查可能影响它们行为的流标志(比如skipws),它们必须进行全面的读取错误检查,而且如果它们遇到问题,它们必须检查流的异常掩码来决定是否该抛出一个异常。
如果进行格式化输入,这些都是重要的活动,但如果你需要的只是从输入流中抓取下一个字符,这样做就过度了。
(2)istreambuf_iterator
你可以像istream_iterator一样使用istreambuf_iterator。
- istreambuf_iterator对象进入流的缓冲区,并直接读取下一个字符。(更明确地说,一个istreambuf_iterator 对象从一个istream s中读取会调用s.rdbuf()->sgetc()来读s的下一个字符。)
- 把我们的文件读取代码改为使用istreambuf_iterator相当简单:
ifstream inputFile("d:\\test.plist");
string fileData((istreambuf_iterator<char>(inputFile)), istreambuf_iterator<char>());
注意这里不需要“unset”skipws标志,istreambuf_iterator不忽略任何字符。
- 它们只抓取流缓冲区的下一个字符。
- 对于无格式的一个一个字符输入,你总是应该考虑使用istreambuf_iterator。
- eg:
#include <iostream>
#include <fstream>
#include <streambuf>
std::ifstream file(“d:\\test.plist”);
if (!file.is_open())
{
return NULL;
}
std::string content;
content.assign(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
注:另外有的程序员使用 ifstream 读取文件内容,然后直接赋值给std::string对象,肯定是错误的。因为:读取的char*类型赋值给string时,默认遇到 \0 就会结束,会丢弃后面的字符。