文件流是以外存文件为输入输出对象的数据流,字符串流不是以外存文件为输入输出的对象,而以内存中用户定义的字符数组(字符串)为输入输出的对象,即将数据输出到内存中的字符数组,或者从字符数组(字符串)将数据读入。字符串流也称为内存流。

字符串流也有相应的缓冲区,开始时流缓冲区是空的。如果向字符数组存入数据,随着向流插入数据,流缓冲区中的数据不断增加,待缓冲区满了(或遇换行符),一起存入字符数组。如果是从字符数组读数据,先将字符数组中的数据送到流缓冲区,然后从缓冲区中提取数据赋给有关变量。

在字符数组中可以存放字符,也可以存放整数、浮点数以及其他类型的数据。在向字符数组存入数据之前,要先将数据从二进制形式转换为ASCII代码,然后存放在缓冲区, 再从缓冲区送到字符数组。从字符数组读数据时,先将字符数组中的数据送到缓冲区,在赋给变量前要先将ASCII代码转换为二进制形式。总之,流缓冲区中的数据格式与字符数组相同。这种情况与以标准设备(键盘和显示器)为对象的输入输出是类似的,键盘和显示器都是按字符形式输入输出的设备,内存中的数据在输出到显示器之前,先要转换为 ASCII码形式,并送到输出缓冲区中。从键盘输入的数据以ASCII码形式输入到输入缓冲区,在赋给变量前转换为相应变量类型的二进制形式,然后赋给变量。对于字符串流的输入输出的情况,如不清楚,可以从对标准设备的输入输出中得到启发。

文件流类有ifstream,ofstream和fstream,而字符串流类有istrstream,ostrstream和strstream。文件流类和字符串流类都是ostream,istream和iostream类的派生类,因此对它们的操作方法是基本相同的。向内存中的一个字符数组写数据就如同向文件写数据一样,但有3点不同:

1.输出时数据不是流向外存文件,而是流向内存中的一个存储空间。输入时从内存中的存储空间读取数据。在严格的意义上说,这不属于输入输出,称为读写比较合适。 因为输入输出一般指的是在计算机内存与计算机外的文件(外部设备也视为文件)之间 的数据传送。但由于C++的字符串流采用了 C++的流输入输出机制,因此往往也用输入和输出来表述读写操作。

2.字符串流对象关联的不是文件,而是内存中的一个字符数组,因此不需要打开和关闭文件。

3.每个文件的最后都有一个文件结束符,表示文件的结束。而字符串流所关联的字符数组中没有相应的结束标志,用户要指定一个特殊字符作为结束符,在向字符数组写入全部数据后要写入此字符。

字符串流类没有open成员函数,因此要在建立字符串流对象时通过给定参数来确立字符串流与字符数组的关联。即通过调用构造函数来解决此问题。建立字符串流对象的方法与含义如下。

建立输出字符串流对象

ostrstream类提供的构造函数的原型为:
   ostrstream::ostrstream(char *buffer,int n,int mode=ios::out);
buffer是指向字符数组首元素的指针,n为指定的流缓冲区的大小(一般选与字符数组的大小相同,也可以不同),第3个参数是可选的,默认为ios::out方式。可以用以下语句建立输出字符串流对象并与字符数组建立关联:
    ostrstream strout(ch1,20);
作用是建立输出字符串流对象strout,并使strout与字符数组ch1关联(通过字符串流将数据输出到字符数组ch1),流缓冲区大小为20。

建立输入字符串流对象

istrstream类提供了两个带参的构造函数,原型为:
    istrstream::istrstream(char *buffer);
    istrstream::istrstream(char *buffer,int n);
buffer是指向字符数组首元素的指针,用它来初始化流对象(使流对象与字符数组建立关联)。可以用以下语句建立输入字符串流对象:
    istrstream strin(ch2);
作用是建立输入字符串流对象strin,将字符数组ch2中的全部数据作为输入字符串流的内容。
    istrstream strin(ch2,20);
流缓冲区大小为20,因此只将字符数组ch2中的,20个字符作为输入字符串流的内容。

建立输入输出字符串流对象

strstream类提供的构造函数的原型为:
    strstream::strstream(char *buffer,int n,int mode);
可以用以下语句建立输入输出字符串流对象:
    strstream strio(ch3,sizeof(ch3),ios::in|ios::out);
作用是建立输入输出字符串流对象,以字符数组ch3为输入输出对象,流缓冲区大小与数组ch3相同。

以上个字符串流类是在头文件strstream中定义的,因此程序中在用到istrstream、ostrstream和strstream类时应包含头文件strstream(在GCC中,用头文件strstream)。

[例13.17] 将一组数据保存在字符数组中。

#include <strstream>
using namespace std;
struct student
{
int num;
char name[];
float score;
};
int main( )
{
student stud[]={,"Li",,,"Wang",89.5,,"Fun",};
char c[]; //用户定义的字符数组
ostrstream strout(c,); //建立输出字符串流,与数组c建立关联,缓冲区长
for(int i=;i<;i++) //向字符数组c写个学生的数据
strout<<stud[i].num<<stud[i].name<<stud[i].score;
strout<<ends; //ends是C++的I/O操作符,插入一个'\\0'
cout<<"array c:"<<c<<endl; //显示字符数组c中的字符
}

运行时在显示器上的输出如下:
array c:
1001Li781002Wang89.51004Fun90

以上就是字符数组c中的字符。可以看到:

以上就是字符数组c中的字符。可以看到:
1) 字符数组c中的数据全部是以ASCII代码形式存放的字符,而不是以二进制形式表示的数据。

2) 在建立字符串流strout时指定流缓冲区大小为30字节,与字符数组c的大小不同,这是允许的,这时字符串流最多可以传送30个字符给字符数组c。请思考:如果将流 缓冲区大小改为10字节,即:
    ostrstream.strout( c ,10);
运行情况会怎样?流缓冲区只能存放10个字符,将这10个字符写到字符数组c中。运行时显示的结果是:
    1001Li7810

字符数组c中只有10个有效字符。一般都把流缓冲区的大小指定与字符数组的大小 相同。

3) 字符数组c中的数据之间没有空格,连成一片,这是由输出的方式决定的。如果以后想将这些数据读回赋给程序中相应的变量,就会出现问题,因为无法分隔两个相邻的数据。为解决此问题,可在输出时人为地加入空格。如
    for(int i=0;i<3;i++)
        strout<<" "<<stud[i].num<<" "<<stud[i].name<<" "<<stud[i].score;
同时应修改流缓冲区的大小,以便能容纳全部内容,今改为字节。这样,运行时将输出:
    1001 Li 78 1002 Wang 89.5 1004 Fun 90
再读入时就能清楚地将数据分隔开。

[例13.18] 在一个字符数组c中存放了个整数,以空格相间隔,要求将它们放到整型数组中,再按大小排序,然后再存放回字符数组c中。

#include <strstream>
using namespace std;
int main( )
{
char c[]="12 34 65 -23 -32 33 61 99 321 32";
int a[],i,j,t;
cout<<"array c:"<<c<<endl; //显示字符数组中的字符串
istrstream strin(c,sizeof(c)); //建立输入串流对象strin并与字符数组c关联
for(i=;i<;i++)
strin>>a[i]; //从字符数组c读入个整数赋给整型数组a
cout<<"array a:";
for(i=;i<;i++)
cout<<a[i]<<" "; //显示整型数组a各元素
cout<<endl;
for(i=;i<;i++) //用起泡法对数组a排序
for(j=;j<-i;j++)
if(a[j]>a[j+])
{t=a[j];a[j]=a[j+];a[j+]=t;}
ostrstream strout(c,sizeof(c)); //建立输出串流对象strout并与字符数组c关联
for(i=;i<;i++)
strout<<a[i]<<" "; //将个整数存放在字符数组c
strout<<ends; //加入'\\0'
cout<<"array c:"<<c<<endl; //显示字符数组c
return ;
}

对字符串流的几点说明:
1) 用字符串流时不需要打开和关闭文件。

2) 通过字符串流从字符数组读数据就如同从键盘读数据一样,可以从字符数组读入字符数据,也可以读入整数、浮点数或其他类型数据。如果不用字符串流,只能从字符数组逐个访问字符,而不能按其他类型的数据形式读取数据。这是用字符串流访问字符数组的优点,使用方便灵活。

3) 程序中先后建立了两个字符串流strin和strout,与字符数组c关联。strin从字符数组c中获取数据,strout将数据传送给字符数组。分别对同一字符数组进行操作。甚至可以对字符数组交叉进行读写,输入字符串流和输出字符串流分别有流指针指示当前位 置,互不干扰。

4) 用输出字符串流向字符数组c写数据时,是从数组的首地址开始的,因此更新了 数组的内容。

5) 字符串流关联的字符数组并不一定是专为字符串流而定义的数组,它与一般的字符数组无异,可以对该数组进行其他各种操作。

通过以上对字符串流的介绍,大家可以看到:与字符串流关联的字符数组相当于内存中的临时仓库,可以用来存放各种类型的数据(以ASCII形式存放),在需要时再从中读回来。它的用法相当于标准设备(显示器与键盘),但标准设备不能保存数据,而字符数组中的内容可以随时用ASCII字符输出。它比外存文件使用方便,不必建立文件(不 需打开与关闭),存取速度快。但它的生命周期与其所在的模块(如主函数)相同,该模块的生命周期结束后,字符数组也不存在了。因此只能作为临时的存储空间。

C++学习50 对字符串流的读写的更多相关文章

  1. 字符串流sstream[part2/使用同一个字符串流反复读写数据]

    stringstream构造函数会特别消耗内存,似乎不打算主动释放内存(或许是为了提高效率),如果你要在程序中使用同一个流反复读写大量数据,将会造成大量的内部消耗,因此建议:    1:调用clear ...

  2. C++ 学习笔记之——字符串和字符串流

    1. 字符数组 字符数组,也就是存放字符类型数据的数组,只不过字符数组的结尾必须是 '\0'.C++ 已经提供了一些字符串处理函数,这些函数被封装在头文件 和 <string.h> 中. ...

  3. Java字符串流学习

    字符串流 定义:字符串流,以一个字符为数据源,来构造一个字符流. 作用:在Web开发中,我们经常要从服务器上获取数据,数据返回的格式通过一个字符串(XML.JSON),我们需要把这个字符串构造为一个字 ...

  4. [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇

    目录 [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇 格式化输出函数 printf函数族功能介绍 printf参数 type(类型) flags(标志) number(宽度) precisi ...

  5. PWN学习之格式化字符串漏洞

    目录 PWN学习之格式化字符串漏洞 格式化输出函数 格式化字符串漏洞 漏洞利用 使程序崩溃 栈数据泄露 任意地址内存泄漏 栈数据覆盖 任意地址内存覆盖 PWN学习之格式化字符串漏洞 格式化输出函数 可 ...

  6. Java学习日记之 Java-IO流

    Java中的IO流在处理上分为字节流和字符流.字节流和字符流的区别 : 1.字节流读取的时候,读到一个字节就返回一个字节:  字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8 ...

  7. 重新想象 Windows 8 Store Apps (23) - 文件系统: 文本的读写, 二进制的读写, 流的读写, 最近访问列表和未来访问列表

    原文:重新想象 Windows 8 Store Apps (23) - 文件系统: 文本的读写, 二进制的读写, 流的读写, 最近访问列表和未来访问列表 [源码下载] 重新想象 Windows 8 S ...

  8. 流类库继承体系(IO流,文件流,串流)和 字符串流的基本操作

    一.IO.流 数据的输入和输出(input/output简写为I/O) 对标准输入设备和标准输出设备的输入输出简称为标准I/O 对在外存磁盘上文件的输入输出简称为文件I/O 对内存中指定的字符串存储空 ...

  9. stringstream类操作字符串流

     C++ Code  12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 ...

随机推荐

  1. 经典ASP.NET MVC3.0入门详解

    http://blog.csdn.net/csh624366188/article/details/7064269 :由于本文原在word文档里编写,写本文章时运用了大量截图,直接复制到博客里,没有显 ...

  2. Axure母版

    1.生成母版: 在左侧窗口的最下方有母版管理窗口,可以在该管理窗口中直接新建母版.也可以在某个页面中将某些部件转换为母版.如图: ----------------------------------- ...

  3. asp.net脚本获取不到id,服务器控件id生成html页面id控制

    在配置文件里修改id的生成方式.经过搜索发现是因为使用Sharpmap而在Web.config中加入的一句配置造成的影响. <pages controlRenderingCompatibilit ...

  4. JSP 相关试题(一)

    选择题 1.当用户请求jsp页面时,JSP引擎就会执行该页面的字节码文件响应客户的请求,执行字节码文件的结果是(C) A)发送一个JSP源文件到客户端    B)发送一个Java文件到客户端 C)发送 ...

  5. poj 1597 Uniform Generator【生成指定范围内所有随机数】

    本文参考资料:http://hi.baidu.com/bnjyjncwbdbjnzr/item/1f997cfdd225d5d143c36a58 题意:一个生成随机数的函数, Seed[x+1] =  ...

  6. (转帖)BootStrap入门教程 (一)

      2011年,twitter的“一小撮”工程师为了提高他们内部的分析和管理能力,用业余时间为他们的产品构建了一套易用.优雅.灵活.可扩展的前端工具集--BootStrap.Bootstrap由MAR ...

  7. mootools里选择器$,$$,$E,$ES等的区别

    区别就是 $和$$都是1个参数, $适用于ID,或者ID代表的对象 $$适用于CSS选择器 $E和$ES,有2个参数,第二个参数是可选参数代表(filter,即某个ID范围里的元素) $E('inpu ...

  8. CentOS下的网络配置文件说明

    CentOS网络配置主要涉及到以下四个文件: 1./etc/sysconfig/network 在CentOS官方网站上给出了如下说明: The/etc/sysconfig/networkfile i ...

  9. WEB用户访问控制方法

    分享到 一键分享 QQ空间 新浪微博 百度云收藏 人人网 腾讯微博 百度相册 开心网 腾讯朋友 百度贴吧 豆瓣网 搜狐微博 百度新首页 QQ好友 和讯微博 更多... 百度分享 一直以来,我对用户/权 ...

  10. C/C++中产生随机数(rand,srand用法)

    计算机的随机数都是由伪随机数,即是由小M多项式序列生成的,其中产生每个小序列都有一个初始值,即随机种子.(注意: 小M多项式序列的周期是65535,即每次利用一个随机种子生成的随机数的周期是65535 ...