C++输入输出流

cin和cout充当了scanf和printf的功能,但是他们不是函数,而是类对象,那么我们有必要了解一下,他们是哪些类的对象。

关于输入输出流有下图这么一个整套的东西,这整套东西很复杂,我们一般来说不去研究,但是呢,我们可以从继承关系看出它属于哪个流类的对象,首先有一个叫ios_base,ios继承ios_base,这个箭头画的不对,真正的继承体系中,箭头应该指向父类。ios又派生了istream和ostream,然后cin又属于istream,cout、cerr、clog又属于ostream,然后istream和ostream又多继承出来一个iostream。这个图很复杂,我们看下面一个



所以我们用cin和cout要包含iostream,然后这里有一个ifstream,ofstream,还有一个fstream,我们今天先学istream,和ostream,然后再学其他的。


流类综述:

1.对象不可复制或赋值

什么意思呢

#include<iostream>
#include<fstream>

using namespace std;
//我们前面写过一个这个,这里为什么要传入引用呢,并且你除了传引用之外没有别的当时可以传,除非传指针。为什么呢,我们举个例子,我们fstream fs;一下,你编译一下是没有问题的,那你在fstream fs2(fs),这是拷贝构造把。然后你就会发现编译都编译不过去了,你可以发现他会报错,新版的是把这个函数给delete掉了,老版本的会说这个函数是私有的。所以这个东西是不可用的,赋值是一样的情况。所以说流类的赋值和拷贝都是不能用的。所以传递的时候只能传递指针或者引用。
//friend ostream & operator<<(ostream &)

int main()
{
#if 0
    fstream fs;
    fstream fs2(fs);
#endif 
    fstream fs;
    fstream fs2;
    fs2=fs;
    return 0;
}


2.流类对象是有缓冲的。

#include<iostream>

using namespace std;

int main()
{
    //你随便写入一点东西,他不会一下子就写到屏幕上去的,它首先要写到缓冲里面去,等缓冲区满了再刷到屏幕上去。屏幕其实是个文件,你这样他就不会输出到屏幕上。
#if 0    
    cout<<"sadfaewfrwea";
    while(1);
#endif
//刷缓冲有如下几种方式:
//1.就是加endl;
//2.就是flush,这里有一点,他不会引入回车(换行)。这里的目的本来也就是不引入回车
//3.unitbuf
  //cout<<"sdfasdfsaf"<<flush;
  cout<<unitbuf<<"sdfasdfsfsa";
}



#include<iostream>
#include<fstream>
using namespace std;

int main()
{
#if 0
    int a;
    //cin 背后是键盘
    //cout 背后是屏幕
    //cin>>a;
    //cout<<a<<endl;
    //fs背后是abc.txt 这里就重载了,重载了cin cout 和fs,
    fstream fs("abc.txt",ios::in|ios::out|ios::trunc);
    //放进去的时候有一点,放一个标志位,这里会输出123
    fs<<1<<" "<<2<<" "<<3<<endl;
    fs.seekp(0,ios::beg);
    int x,y,z;
    fs>>x>>y>>z;
    cout<<x<<y<<z<<endl;
#endif
    //这里输入一个a,会得到一个a,
    //你在这里用cin>>val和cout>>val是一样的,只不过这里是个函数
    char val;
    val=cin.get();
    cout.put(val);

}



#include<iostream>
#include<iomanip>
#include<fstream>
#include<string.h>
using namespace std;


/*
 *cout:输出基本类型数据时,不必考虑数据是什么类型,系统会自动判断
 *     选择相应的重载函数;输出用户自己定义的类型数据时,要重载<<
 *     运算符。
 *cerr:是在屏幕上显示出错信息,与cout用法类似,不同的是只能在屏幕上,而不能
 *     在磁盘文件上输出错误信息。
 *clog:用法与cerr类似,不同点是它带有缓冲区。
 *这里用会cout其他的都一样的。
 */

int main()
{
#if 0
    //输出16进制
    int a=0x12345678;
    //关闭10进制
    cout.unsetf(ios::dec);
    //打开16进制
    cout.setf(ios::hex);
    cout<<a<<endl;

    //你如果又想输出10进制了,你就要把16进制给关了,然后把10进制给打开
    cout.unsetf(ios::hex);
    cout.setf(ios::dec);
    //八进制是ios::oct
    cout<<a<<endl;
#endif 
    
#if 0
但是这个太麻烦了,这个系统函数格式化并不好用,所以就引入了流算子
要用<iomanip>这个头文件,

    int x=0x123456;
    //输出16进制
    cout<<hex<<x<<endl;
    //输出10进制
    cout<<dec<<x<<endl;
    //输出八进制
    cout<<oct<<x<<endl;
#endif


#if 0
    //强制显示小数点和尾和数符 setiosflags(ios::showpoint)
    //强制显示符号:setiosflags(ios::showpos)
    double d1=10/5,d2=22.0/7;
    cout<<"显示小数点、尾和数符: "<<endl;
    //这里输出2,2的话默认是不显示小数
    cout<<d1<<endl;
    //这里输出2.000,加个shwopoint就显示小数了。显示五位小数
    cout<<setiosflags(ios::showpoint)<<d1<<endl;
    //这里输出+3.14286 pos是正负的意思。
    cout<<setiosflags(ios::showpos)<<d2<<endl;
#endif 


#if 0    
    //设置精度(有效数字个数)
    //setpreciion(n)自动四舍五入
    
    double ddd=123.4567;
    cout<<setprecision(2)<<ddd<<endl;
    cout<<setprecision(3)<<ddd<<endl;
    cout<<setprecision(4)<<ddd<<endl;
    cout<<setprecision(5)<<ddd<<endl;
#endif 


#if 0
    //设置浮点数的输出是以科学记数法还是定点数
    //setiosflags(ios::scientific)(科学技术法),此时精度域表示小数位数
    //setiosflags(ios::fixed)(定点数),此时精度域表示小数位数
    //setprecision(2)<<setiosflags(ios::fixed)设置小数的精度
    double dd=123.4567;
    //这里是用科学技术法
    cout<<setiosflags(ios::scientific)<<dd<<endl;
    //因为上面用了科学技术法,不想用了,所以这里就去掉
    cout<<resetiosflags(ios::scientific);
    //6位小数
    cout<<setiosflags(ios::fixed)<<dd<<endl;
    //4舍5入。两位小数
    cout<<setprecision(2)<<setiosflags(ios::fixed)<<dd<<endl;
#endif 

#if 0
uppercase:小写变大写
在16进制中大写和小写,比如说
int a=0xabcd;
int a=0xABCD是一样的
但是有的时候显示不一样
如下
int num=0xabcd;这里是小写的。
#endif    

#if 0
    int num=0xabcd;
//正常输出如下: 这里就是输出abcd
    cout<<hex<<num<<endl;
//以大写方式输出 这里输出ABCD
    cout<<setiosflags(ios::uppercase)<<hex<<num<<endl;
//你上面大写方式输出,要恢复小写输出用下面这个
    cout<<resetiosflags(ios::uppercase)<<hex<<num<<endl;
#endif
//格式化输出就讲这么多

#if  0
//下面是成员函数    
//成员函数

1.ostream put(char)
功能:输出一个 字符
#endif

#if 0
    char str[]="Programing with C++";
    cout<<sizeof(str)<<endl;
    for(int i=sizeof(str)/sizeof(str[0])-2;i>=0;i--)
    cout.put(*(str+i));

    cout.put('\n');
#endif 

#if 0
在来看看cin

#endif

#if 0
    int a;
    double b;
    char buf[1024];
//你在这里输出如下
//12
//34.5
//ad  wer
//会输出12 34.5 ad;
//最后这个遇到空格就结束了。
//这是这个东西的一个弊端
//你比如说我现在就想读一整行,怎么办呢
//不方便的事情就由成员函数来弥补
    cin>>a>>b>>buf;
    cout<<"a = "<<a<<endl;
    cout<<"b = "<<b<<endl;
    cout<<"buf ="<<buf<<endl;
#endif 

//我们再来看一个
//这里a读出来是123,b读出来是0 c读出来是0,这里就说明你123写进去,它就是123
//然后有个\n,它第一次读是123,然后遇到\n,遇到结束标记了,你再往后就没有了,所以我们上次就是fs<<a>>" "<<b<<" "<<c<<endl;
#if 0
    fstream fs("abc.txt",ios::in|ios::out|ios::trunc);
    fs<<1<<2<<3<<endl;
    fs.seekg(0,ios::beg);

    int a,b,c;
    fs>>a>>b>>c;
    cout<<"a = "<<a<<endl;
    cout<<"b = "<<b<<endl;
    cout<<"c = "<<c<<endl;
#endif

#if 0
    为了弥补这个不足,就提供了以下的不可或缺的成员函数
    char get()
    读入一个字符并返回(包括回车 tab 空格等空白字符)


    char ch;
    while((ch=cin.get())!=EOF)
    {
        cout.put(ch);
    }
#endif

#if 0
    istream & get(char &)
功能:读入一个字符,如果读取成功则返回非0值(真),如失败(遇到文件结束符),则函数返回0值(假)

    char ch;
    //这是个逗号表达式,逗号表达式的结果以后面那个为准
    //这里就是说不是EOF就打印
    while((cin.get(ch)),!cin.eof())
    {
        cout.put(ch);
    }
    return 0;
#endif

#if 0
istream &get(char *,int,char)
格式:istream &get(字符数组,字符个数n,终止字符)
    或者istream &cin.get(字符指针,字符个数,终止字符)
功能:
从输入流中读取n-1字符,赋给字符数组或者字符指针指向的数组,如果在读取n-1个字符之前遇到终止字符,则提前结束。如果成功则返回非0,失败,则返回0,会清空char *指向的空间,未读到n-1个字符或终止符,则会阻塞。不能越过终止符号
#endif
//你这里输入1234i5678i,只能读到1234i,本来是可以读到5678i的,但是它跨不过终止符号

#if 0
char buf[1024];
cin.get(buf,1024,'i');
cout<<buf<<"xxx"<<endl;
//想过去就cin.ignore(1),忽略一个就可以了,这里就忽略了i,你这里
//输入1234i5678i就会输出1234xxx 5678ooo
cin.ignore(1);
memset(buf,0,1024);
cin.get(buf,1024,'i');
cout<<buf<<"ooo"<<endl;
#endif

#if 0
cin.getline(字符数组或字符指针,字符个数n[,终止字符])
与带三个参数的get()功能类似,从输入流中读取n-1字符,赋给字符数组或字符指针所指向的空间。如果在读取n-1个字符之前遇到终止字符(如果不写,默认为'\n'),则提前结束。失败会返回0情况char *,未读到n-1个字符或终止符。则会阻塞。能越过终止符号
#endif
//这里你输入1234i5678i会输出1234  5678
#if 0
char buf[1024];
cin.getline(buf,1024,'i');
cout<<buf<<endl;
cin.getline(buf,1024,'i');
cout<<buf<<endl;
#endif

#if 0
我们前面有提到ignore,可以忽略字符
当我们有 I like C/     I like C++/的时候,中间空了巨多字符
我这里其实是想打印I like C 紧接着打印I like C++
所以可以用ignore(100,i) 这里的意思是忽略100个,但是中间有i的话,到i为止
但是要注意的是他会把i也给忽略掉。那怎么办呢,我们可以用putback给推回去。
#endif 

#if 0
char buf[1024];
cin.getline(buf,1024,'/');
cout<<buf<<endl;
cin.ignore(100,'I');
//这里其实就是回推一个字节,然后往那个地址写东西,比如你这里就是在原来被忽略I 的地方写个I,也可以写其他的。
cin.putback('I');
cin.getline(buf,1024,'/');
cout<<buf<<endl;
#endif 

#if 0
peek 中文意思窥探的意思,这个怎么用的,这个表示我去看一眼,但是我不去取里面的数据。一旦你去取或者忽略都会涉及内部指针的移动,这个就是取看一看不动手
不去动它的指针。
#endif
char buf[1024];
cin.getline(buf,1024,'/');
cout<<buf<<endl;
cin.ignore(100,'I');
cin.putback('I');
//这里会输出I,就是你回推的那个I 暂时只发现这个函数是这么玩的
char peek=cin.peek();
cout<<peek<<endl;
cout<<buf<<endl;




}

阅读更多
个人分类: C++学习
想对作者说点什么? 我来说一句

C++ 输入输出流及本地化

2010年01月08日 10.59MB 下载

C++输入输出流及本地化

2008年12月08日 10.67MB 下载

没有更多推荐了,返回首页

不良信息举报

C++输入输出流

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭