[C++_11] IO_1

16 IO


16.1 格式化IO

C++提供了两种格式控制的方法:一种方法是使用ios类中有关格式控制的成员函数;另一种方法是使用称为可是控制符的特殊类型的函数

16.1.1 用ios类的成员函数进行格式控制

ios类中有几个成员函数可以用来对输入输出进行格式控制,进行格式控制主要是通过对格式状态字,域宽,填充字符以及输出精度的操作来完成的。

16.1.2 格式状态字

输入输出格式由一个long int类型的格式状态字确定,状态字的各位都控制一定的输入输出特征,例如格式状态子的最右以为为1,则表示在输入时跳过空白字符。在ios类的public部分定义了一个枚举,它的每个成员可以跟别定义格式状态字的每一位。
enum{
skipws =0x0001, //输入时,跳过开头的空白字符(空格,制表,换行)
left =0x0002, //
right =0x0004, //
internal = 0x0008 //数值符号左对齐,数值右对齐
dec,oct,hex //10 8 16进制
showbase //显示“基指示符”如设置hex和showbase,则显示“0x”
showpoint //强制显示float和double型数据的小数点及后的无效0
uppercase //数值中的字母(指数符“e”.16禁制数字)大写显示
showpos //正数前加“+”
scientific fixed //scientific:浮点数科学计数法,fixed:浮点数常规
unitbuf //输出操作后立即刷新所有流,刷新流意味着把输出写到与流相连的设备
stdio //每次输出,刷新stdout和stderr

}

16.1.3 ios类中用于控制输入输出格式的成员函数

long ios::flags(); //返回当前格式状态字
long ios::flags(long); //设置格式状态字并返回
long ios::setf(long); //设置指定的标志位
long ios::unsetf(long); //清除指定的标志位
int ios::width(); //返回当前显示数据的域宽
int ios::width(int); //设置当前显示数据域宽并返回原域宽
char ios::fill(); //返回当前填充字符
char ios::fill(char); //设置填充字符并返回原填充字符
int ios::precision(); //返回当前浮点数的精度
int ios::precision(int); //设置浮点数精度并返回原精度

16.1.4 使用IO操作符进行格式控制

C++预定义的操作符分为带参数的操作符和不带参数的操作符。通常,不带参数的操作符在iostream文件中定义,而带参数的操作符在iomanip文件中定义。
#include<iostream>:
endl //输入时插入换行符并刷新流
ends //输出时在字符串后插入空字符(NULL)最为尾符
flush //刷新,把流从缓冲区输出到目标设备
ws //输入时略去空白字符
dec hex oct //10 16 8进制

#include<iomanip>:
setbase(int n) //设置转换基数为n(0,8,10,16),默认为0,表示10进制输出
resetiosflags(long f) //清除由参数f指定的标志位,用于输入输出
setiosflags(long f) //设置参数f指定的标志位
setfill(char c) //设置填充字符
setprecision(int n) //设置浮点数精度(默认6)
setw(int n) //设置数据宽度

#include<iostream>
#include<iomanip>
#include<string>
#include<typeinfo>

using namespace std;
int main()
{
  //成员函数&格式状态字控制
  cout << "当前默认状态字:"<< cout.flags() << endl;
  cout.flags(ios::skipws|ios::left|ios::hex|ios::showbase|
  ios::uppercase|ios::showpos|ios::unitbuf);
  cout << "修改后状态字:"<< cout.flags() << dec << "(" << cout.flags()<< ")"<< endl;
  cout.fill('#');
  cout <<"输出数字65536:" << endl<<setw(8) << 65536 << endl;
  cout << "设置填充和域宽:"<< endl;
  cout.width(12);  //只对下一句起作用
  cout << 65536 << endl <<"注:填充不影响关键字,但保持有效性直到更改"<< endl;
  cout << "  关键字一旦修改就不会自动恢复,区别于操作符控制"<< endl;
  cout << "****************************" << endl;
  
  //操作符格式控制
  cout<< dec << 256 << endl <<  oct << 256 << endl << hex << 256 <<endl;
  cout<< setw(15) << setfill('^') << setprecision(8) << 123.456789 << endl;
  cout << endl;
  return 0;
}
输出结果:


自定义输出格式:

#include<iostream>
using namespace std;

//方法一:无参:类-对象
class HexUpBas
{
public:
  friend ostream&  operator<<(ostream &o,const HexUpBas hub)
  {
	return o<< hex << uppercase << showbase ;
  }
};

const HexUpBas hub = HexUpBas();

//方法二:有参 类
class wf
{
  int w;
  unsigned char fill;
public:
  wf(int w, unsigned char f=' '):w(w),fill(f){}
  friend ostream& operator<<(ostream& o,const wf& x) //临时对象
  {
	o.width(x.w);
	o.fill(x.fill);
	return o;
  }
};
//方法三:函数
ostream& func(ostream& o)
{
  return o<< dec << showpos;
}
// 工作原理:ostream类中
// 	ostream& operator<<(ostream& (*f)(ostream& o))
// 	{  return f(*this);  }


int main()
{
  cout << hub << 12346<<endl;
  cout << wf(10,'*') <<"hello"<< endl;
  cout << func<< 589 << endl;
  return 0;
}


16.2 控制台的输入输出


16.2.1格式化的输入输出

cout<< cin>>跳过空白字符,格式自动转换完成的,重载的<< >>来实现的

cerr 无缓冲,也不允许重定向
cout可缓冲,可重定向
clog理论上可缓冲,不可重定向,实际上无缓冲不可重定向

//输出缓冲区遇到换行、有输入、满、程序结束、flush会刷新
cout<<"hello";
cerr<<"world";
clog<<"tarena";
输出结果是cerr东西先出来,然后是clog,最后是cout
如果重定向的话a.out>file cat file结果只有cout的东西重定向了



16.2.2 非格式化的输入输出

.get()读取一个字符,类似C中getchar(),不会跳过空白字符
.put()写一个字符 //ostream& put( char ch );

.getline(char数组,数组大小) //如果不能读完一整行会设置错误状态
getline(i对象,string对象引用) //不是成员函数而是全局函数
这两个版本都可以添加第三个参数,指定结束字符,默认是读到换行,为读到什么字符为止

.ignore() //istream& ignore( int nCount = 1, int delim = EOF );
.putback()
.peek()查看输入缓冲区第一个字符

io对象要求能转换成bool类型,对处于正常状态的io对象转成true,对处于错误状态的io对象转成false
io对象如果正常就是真,错误为假,io对象如果处于错误状态就拒绝io,纠正办法是cin.clear()(清除错误状态,不清缓冲区)

string s;
s.c_str(); //转成C风格字符串
printf("%s\n",s.c_str());

#include<iostream>
using namespace std;

int main()
{
  int i;
  cout << "请输入一个数字:"<< endl;
  cin >> i;
   while(!cin)
  {
	cout << "输入错误字符!" << endl;
	cin.clear();
	cin.ignore(200,'\n');//cin.clear()重置了cin的状态,没有清空缓存
	cin >> i;  //cin.get()不会改变cin的状态,无论成功与否cin都是true
  }  
  cout << "输入缓冲区中第一个字符:" << cin.peek() << endl;  //查看缓冲区第一个字符(根据上面:回车)
  cin.ignore(200,'\n');
  cout << "cin.get()可以读取回车,制表,空格,区别于cin >> "<< endl;
  cin.get();   //读取一个字符,可以当做程序停顿使用,并不忽略回车,制表,空格
  cout <<"停顿完成!" << endl;
  cout << "输入字符串以'*'结尾:" << endl;
  char str[100];
  cin.getline(str,100,'*');//最后一个参数为读到此字符为止,默认为'\n'
  cout <<"查看字符串内容:" <<  str << endl;
  char c;
  cout <<"输入缓冲区中第一个字符:" << cin.peek() << endl; 
  c=cin.get();
  cout<<"读取之后,输入缓冲区中第一个字符:" << cin.peek()<< endl;  
  cin.putback(c);
  cout << "还回之后,输入缓冲区中第一个字符:" <<cin.peek()<<endl;
  
  
  
  return 0;
}

输出结果:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值