cout 输出控制

cout输出格式控制

如果要在输出流中加入格式控制符则要加载头文件:#include <iomanip>
  这里面iomanip的作用比较多:
  主要是对cin,cout之类的一些操纵运算子,比如setfill,setw,setbase,setprecision等等。它是I/O流控制头文件,就像C里面的格式化输出一样.以下是一些常见的控制函数的:

dec 置基数为10 相当于"%d"

hex 置基数为16 相当于"%X"


oct 置基数为8 相当于"%o"      //作用永久

sample:

cout<<12<<hex<<12<<oct<<12<<12;output 12c1414


setprecision(n) 设显示小数精度为n位 //作用永久

sample:

setf(ios:fixed);

cout<<setprecision(2)<<2.345<<endl; ouput 2.34 //注意先用setf(ios::fixed);否则结果自己测试下
     

setw(n) 设域宽为n个字符 //作用临时
  这个控制符的意思是保证输出宽度为n。如:
  cout<<setw(3)<<1<<setw(3)<<10<<setw(3)<<100; 输出结果为
  1 10100 (默认是右对齐)当输出长度大于3时(<<1000),setw(3)不起作用。

setfill(c) 设填充字符为c

  setioflags(ios::fixed) 固定的浮点显示
  setioflags(ios::scientific) 指数表示 

sample cout<<setiosflags(ios::fixed)<<setprecision(2)<<2.345<<endl; output 2.34
  setiosflags(ios::left) 左对齐
  setiosflags(ios::right) 右对齐
  setiosflags(ios::skipws) 忽略前导空白
  setiosflags(ios::uppercase) 16进制数大写输出
  setiosflags(ios::lowercase) 16进制小写输出
  setiosflags(ios::showpoint) 强制显示小数点
  setiosflags(ios::showpos) 强制显示符号

sample: cout<<setiosflags(ios::uppercase)<<hex<<12<<15<<endl; output CF

cout<<setioflags(ios::showpoint)<<x<<endl;若float x=1,则output 1.000000 不使用直接输出1

cout<<setiosflags(ios::showpos)<<1<<endl;output +1

//使用标准C++编写
#include <iostream>
#include <iomanip>//
精度设置必须包括的头文件

using namespace std;

int main()
{
double a=3.5;
int b=10;
//
方法一:操作符函数的格式控制
//cout.precision(2),
设置精度为2
//right:
设置左对齐;fixed:控制浮点型输出格式;
//setw(5):
设置输出位宽为5

cout<<right<<fixed<<setw(5)<<setfill('0')
<<setprecision(2)<<a<<endl; //
输出结果为03.50

//
方法二:IOS类成员函数的格式控制
cout.precision(4); //setprecision(4),
设置精度为4
cout<<a<<endl; //
输出结果为3.5000

//setfill('0')
:设置填充字符为'0'
//static_cast<double>(b):
将整型的b,
//
生成一个双精度浮点型副本进行操作,而不改变其值和类型
cout<<fixed<<setfill('0')<<setprecision(2)
<<fixed<<static_cast<double>(b)<<endl;//
输出10.00
return 0;
}


方法很多种啦,我们可以这样写: 
/*
一个使用填充,宽度,对齐方式的例子*/ 
#include <iostream.h> 
void main() 

    cout<<"
第一章"<<endl; 
    cout<<"    "; 
    cout.setf(ios::left);        //
设置对齐方式为left 
    cout.width(7);              //
设置宽度为7,不足用空格填充 
    cout<<"1.1"; 
    cout<<"
什么是C语言"; 
    cout.unsetf(ios::left);      //
取消对齐方式,用缺省right方式 
    cout.fill(’.’);              //
设置填充方式 
    cout.width(30);              //
设置宽度,只对下条输出有用 
    cout<<1<<endl; 
    cout<<"    ";               
    cout.width(7);              //
设置宽度 
    cout.setf(ios::left);        //
设置对齐方式为left 
    cout.fill(’ ’);              //
设置填充,缺省为空格 
    cout<<"1.11"; 
    cout<<"C
语言的历史"; 
    cout.unsetf(ios::left);      //
取消对齐方式 
    cout.fill(’.’); 
    cout.width(30); 
    cout<<58<<endl; 
    cout.fill(’ ’); 
    cout<<"
第二章"<<endl; 

   
我们多次设置了宽度,为的是使我们的间距能一致,也使用了对齐方式,为的是使我们的数据能对齐显示,看起来美观。我们还使用了填充方式。我们下面用操纵算子来实现也是可以的。 
/*
一个使用填充,宽度,对齐方式的例子*/ 
#include <iomanip.h> 
void main() 

    cout<<"
第一章"<<endl; 
    cout<<"    "; 
    cout<<setiosflags(ios::left)<<setw(7);        //
设置宽度为7left对齐方式 
    cout<<"1.1"; 
    cout<<"
什么是C语言"; 
    cout<<resetiosflags(ios::left);                //
取消对齐方式 
    cout<<setfill(’.’)<<setw(30)<<1<<endl;        //
宽度为30,填充为’.’输出 
    cout<<setfill(’ ’);                            //
恢复填充为空格 
    cout<<"    "; 
    cout<<setw(7)<<setiosflags(ios::left);        //
设置宽度为7left对齐方式 
    cout<<"1.11"; 
    cout<<"C
语言的历史"; 
    cout<<resetiosflags(ios::left);                //
取消对齐方式 
    cout<<setfill(’.’)<<setw(30)<<58<<endl;        //
宽度为30,填充为’.’输出     
    cout<<setfill(’ ’)<<"
第二章"<<endl; 

   
我们输出了同样的效果,不过依我的性格,我更喜欢用操纵算子来进行格式化输出。最后我们看看浮点数的格式输出,如下例: 
/*
关于浮点数的格式*/ 
#include <iostream.h> 
void main() 

    float f=2.0/3.0,f1=0.000000001,f2=-9.9; 
    cout<<f<<’ ’<<f1<<’ ’<<f2<<endl;      //
正常输出 
    cout.setf(ios::showpos);              //
强制在正数前加+ 
    cout<<f<<’ ’<<f1<<’ ’<<f2<<endl; 
    cout.unsetf(ios::showpos);            //
取消正数前加+ 
    cout.setf(ios::showpoint);            //
强制显示小数点后的无效
    cout<<f<<’ ’<<f1<<’ ’<<f2<<endl; 
    cout.unsetf(ios::showpoint);          //
取消显示小数点后的无效
    cout.setf(ios::scientific);          //
科学记数法 
    cout<<f<<’ ’<<f1<<’ ’<<f2<<endl; 
    cout.unsetf(ios::scientific);        //
取消科学记数法 
    cout.setf(ios::fixed);                //
按点输出显示 
    cout<<f<<’ ’<<f1<<’ ’<<f2<<endl; 
    cout.unsetf(ios::fixed);              //
取消按点输出显示 
    cout.precision(18);                  //
精度为18,正常为
    cout<<f<<’ ’<<f1<<’ ’<<f2<<endl; 
    cout.precision(6);                    //
精度恢复为

   
同样,我们也一样能用操纵算子实现同样的功能: 
/*
关于浮点数的格式*/ 
#include <iomanip.h> 
void main() 

    float f=2.0/3.0,f1=0.000000001,f2=-9.9; 
    cout<<f<<’ ’<<f1<<’ ’<<f2<<endl;      //
正常输出 
    cout<<setiosflags(ios::showpos);      //
强制在正数前加+ 
    cout<<f<<’ ’<<f1<<’ ’<<f2<<endl; 
    cout<<resetiosflags(ios::showpos);    //
取消正数前加+ 
    cout<<setiosflags(ios::showpoint);    //
强制显示小数点后的无效
    cout<<f<<’ ’<<f1<<’ ’<<f2<<endl; 
    cout<<resetiosflags(ios::showpoint); //
取消显示小数点后的无效
    cout<<setiosflags(ios::scientific);  //
科学记数法 
    cout<<f<<’ ’<<f1<<’ ’<<f2<<endl; 
    cout<<resetiosflags(ios::scientific); //
取消科学记数法 
    cout<<setiosflags(ios::fixed);        //
按点输出显示 
    cout<<f<<’ ’<<f1<<’ ’<<f2<<endl; 
    cout<<resetiosflags(ios::fixed);      //
取消按点输出显示 
    cout<<setprecision(18);              //
精度为18,正常为
    cout<<f<<’ ’<<f1<<’ ’<<f2<<endl; 
    cout<<setprecision(6);                //
精度恢复为

 
c/c++系统中除了标准的输入输出外,还提供了更多的输入函数。这写函数主要有getch(),getche(), 
getchar
(),cin.get(),putch(),putchar(),cout.put(),gets(),cin.getline(),puts()
。另外
还有些为了让缓冲区不影响程序的正确操作的缓冲去的操作,如:cin.putback(),fflush(stdin),cout.flush().我们
做一下简单的说明。 
    1
getch()getche(),非缓冲式输入,从键盘读入一个字符。getch()读入字符不显示。有conio.h支持。 
    2
cin.get(),getchar(),缓冲式输入,从键盘读入一个字符,并显示。getchar()stdio.h支持,cin.get()iostream.h支持。 
    3
putch()putchar(),非缓冲式输出,输出一个字符到显示器。putch()conio.h支持,putchar()stdio.h支持。 
    4
cout.put(),缓冲式输出,输出一个字符到显示器。由iostream.h支持。 
    5
gets()cin.geline(),缓冲式输入,读入一字符串(包括空格,不包括最后的回车),gets()stdio.h支持,cin.getline()iostream.h支持。 
    6
puts(),非缓冲输出,输出一个字符串,由stdio.h支持。 
    7
cin.putback(),把一个字符送回输入缓冲区。 
    8
fflush(stdin),清除输入缓冲区操作。无法清除cin.get()等带来的操作。 
    9
cout.flush(),清楚输出缓冲区。 
   
在这里我们稍微说一下输入/输出缓冲区,这是为了减少程序访问io带来中断而设的一段空间。当程序满足某个刷新条件时,那就将清理缓冲区。具体条件为: 
    1
、输入缓冲区 
a
,程序要求输入时,按下了回车键。 
b
,遇到程序结束。 
c
,遇到下一条输入语句。 
d
,遇到清除缓冲区操作 
e
,缓冲区溢出 
    2
、输出缓冲区 
a
,输出缓冲区溢出 
b
,遇到下一条输入语句 
c
,使用刷新缓冲区迫使清除 
d
,程序结束。 
   
缓冲区操作有时会带来程序的不正确的输入,如前面说的scanf(),在连续输入的时候,会把一个回车赋给下一个字符变量。我们操作的时候一定要注意。

使用标记进行格式设置的setf()函数

格式化的各个方面,
要使用各种格式只需把该位设置为1 即可,setf 函数就是用来设置标记的成员函数,使用该函数需要一个或两个在c++
中定义的位的常量值作为参数,这些位的常量值在下面介绍。

1、c++在ios类中定义了位的常量值,这些值如下:
a、ios::boolalpha使布尔值用字符表示
b、iso::showbase显示进制的基数表示即16进位以0x开始,8进制以0开始,
c、ios::showpoint显示末尾的小数点,
d、、ios::uppercase使16进制的a~f用大写表示,同时0x还有科学计数的字母e都用大写表示,
e、ios::showpos在十进制的正数前面显示符号+

注意这些常量都是ios 类中定义的,所以使用他们时需要加上ios::限定符

比如:cout.setf(ios::showbase);注意使用
setf函数时需要用对象来调用,因为它是流类的成员函数。

2、使用带两个参数的setf()函数:setf()函数不但可以带有一个参数,还可以带有两个参数。带两个参数的setf()函数的
第一个参数为要设置的位的值,第二个参数为要清除的位的值。

参数说明如图所示
在C++中有一个受保护的数据成员,其中的各位分别控制着
3、用setf()函数设置的格式需要使用对应的unsetf()函数来恢复以前的设置,比如setf(ios::boolalpha)将使布尔值以字
符的形式使用,如再使用unsetf(ios::boolapha)则又将使布尔值以数字的形式使用。
带两个参数的setf函数可以使用第1 个参数为0 的unsetf 函数来恢复其默认值,比如unsetf(0,ios::basefield)或直接使用unsetf(ios::basefield),注
意在visual C++中不能使用第一个参数为0 的unsetf 函数,只能使用第二种形式。

 

格式输出

在输出数据时,为简便起见,往往不指定输出的格式,由系统根据数据的类型采取默认的格式,但有时希望数据按指定的格式输出,如要求以下六进制或八进制形式输出一个整数,对输出的小数只保留两位小数等;有两种方法可以达到此目的。一种是使用控制符;另一种是使用流对象的有关成员函数。分别叙述如下:

1、 用控制符控制输出格式







应当注意:

这些控制符是在头文件iomanip中定义的,因而程序中应当包含头文件iomanip。通过下面的例子可以了解使用它们的方法,

[indent]例2 用控制符控制输出格式


#include <iostream>
#include <iomanip> //不要忘记包含此头文件


using namespace std;
int main()
{
int a;
cout<<"input a:";
cin>>a;
cout<<"dec:"<<dec<<a<<endl; //以上进制形式输出整数
cout<<"hex:"<<hex<<a<<endl; //以十六进制形式输出整数a
cout<<"oct:"<<setbase(8)<<a<<endl;//以八进制形式输出整数a
char *pt="China";
//pt指向字符串”China”
cout<<setw(10)<<pt<<endl; //指定域宽为10,输出字符串
cout<<setfill('*')<<setw(10)<<pt<<endl;//指定域宽10,输出字符串,空白处以“*”填充
double pi=22.0/7.0; //计算pi
cout<<setiosflags(ios::scientific)<<setprecision(8);//按指数形式输出,8位小数
cout<<"pi="<<pi<<endl; //输出pi
cout<<"pi="<<setprecision(4)<<pi<<endl;//改为4位小数
cout<<"pi="<<setiosflags(ios::fixed)<<pi<<endl;//改为小数形式输出
return 0; }

运行结果如下



inputa:34 (输入a的值)
dec:34 (十进制形式)
hex:22 (十六进制形)
oct:42 (八进制形式)
China (域宽为10)
***** China (域宽为10,空白处以'*'填充)
pi=3.14285714e+00 (指数形式输出,8位小数)
pi=3.1429e+00) (指数形式输小,4位小数)
pi=3.143 (小数形式输出,梢度仍为4)


2.用流对象的成员函数控制输出格式




除了可以用控制符来控制输出格式外,还可以通过调用流对象COUt中用于控制输出格式的成员函数来控制输出格式。用于控制输出格式的常用的成员函数见表4。



流成员函数setf和控制符setiosflags括号中的参数表示格式状态,它是通过格式标志来指定的。格式标志在类ios中被定义为枚举值。因此在引用这些格式标志时要在前面加上类名ios和域运算符“::”。格式标志见表5。





[/indent][indent]例3 用流控制成员函数输出数据。


#include <iostream>
using namespace std;
int main()

{
int a=21;
cout.setf(ios::showbase); //设置输出时的基数符号
cout<<"dec:"<<a<<endl; //默认以十进制形式输出a
cout.unsetf(ios::dec); //终止十进制的格式设置
cout.setf(ios::hex); //设置以十六进制输出的状态
cout<<"hex:"<<a<<endl; //以十六进制形式输出a
cout.unsetf(ios::hex); //终止十六进制的格式设置
cout.setf(ios::oct); //设置以八进制输出的状态
cout<<"oct:"<<a<<endl; //以八进制形式输出a
cout.unsetf(ios::oct); //终止以八进制的输出格式设置
char *pt="China"; //pt指向字符串”china”
cout.width(10); //指定域宽为10
cout<<pt<<endl; //输出字符串
cout.width(10); //指定域宽为10
cout.fill('*'); //指定空白处以'*'填充
cout<<pt<<endl; //输出字符串
double pi=22.0/7.0; //计算pi
cout.setf(ios::scientific);//指定用科学记数法输出
cout<<"pi="; //输出"pi="
cout.width(14); //指定域宽为14
cout<<pi<<endl; //输出"pi
cout.unsetf(ios::scientific); //终止科学记数法状态
cout.setf(ios::fixed); //指定用定点形式输出
cout.width(12); //指定域宽为12
cout.setf(ios::showpos); //在输出正数时显示“+”
cout.setf(ios::internal); //数符出现在左侧
cout.precision(6); //保留6位小数
cout<<pi<<endl; //输出pi,注意数符“+”的位置
return 0;}

运行情况如下:



dec:21 (十进制形式)
hex:Oxl5 (十六进制形式,以0x开头)
oct:025 (八进制形式,以O开头)
China (域宽为10)
*****china (域宽为10,空白处以'*'填充)
pi=**3.142857e+00 (指数形式输出,域宽14,默认6位小数)
****3.142857 (小数形式输㈩,精度为6,最左侧输出数符“+”)


说明:




1、成员函数width(n)和控制符setw(n)只对其后的第一个输出项有效。如果要求在输出数据时都按指定的同一域宽n输出,不能只调用一次width(n),而必须在输出每一项前都调用一次width(n)。


2、在表5中的输出格式状态分为5组,每一组中同时只能选用一种(例如,dec,hex和oct中只能选一,它们是互相排斥的),在用成员函数setf和控制符setiosflags设置输出格式状态后,如果想改设置为同组的另一状态,应当调用成员函数unsetf(对应于成员函数setf)或resetiosflags(对应于控制符setiosflags),先终止原来设置的状态。然后再设置其他状态。

同理,程序倒数第8行的unsetf函数的调用也是不可缺少的。读者不妨上机试一试。


3、用setf函数设置格式状态时,可以包含两个或多个格式标志,由于这些格式标志在iOS类中被定义为枚举值,每一个格式标志以一个二进位代表,因此可以用“位或”运算符“I”组合多个格式标志


4、可以看到:对输出格式的控制,既可以用控制符(如例2),也可以用cout流的有关成员函数(如例3),二者的作用是相同的。控制符是在头文件iomanip中定义的,因此用控制符时,必须包含iomanip头文件。cout流的成员函数是在头文件iostream中定义的,因此只需包含头文件iostream,不必包含iomanip。许多程序人员感到使用控制符方便简单,可以在一个cout输出语句中连续使用多种控制符。


5、关于输山格式的控制,在使用中还会遇到一些细节问题,不可能在这里全部涉及。在遇到问题时,请查阅专门手册或上机试验一下即可解决。

用于char类型的字符数组的输入流类的成员函数

使用输入流类的成员函数进行输入:
注意:以下这些成员函数都只能用于char类型的字符数组,而不能用于string类型的对象。


1、使用get()函数输入单个字符:输入单个字符的get()函数都是类istream 中的成员函数,调用他们需要使用类的对象
来调用,该函数有两个原型,即get(char &ch)和get(void)。
a、get(char &ch)函数:该函数返回调用对象的引用,这里要注意该函数的参数类型必须要是char类型的,不能是int
型变量,比如cin.get(a)其中参数a 只能是char 类型,不能是int 型,如果是int 型则会出现错误。该函数可以连
续输入,即cin.get(a).get(a);
b、get(void)函数:该函数反回int型的值,调用该get函数时不需要使用参数。该函数不能连续输入,比如cin.get().get()
就是错误的。
c、两个get函数都接收输入的单个字符,且不跳过空白符号和回车换行符。如果输入了2个以上的字符,则以后的
字符保存在输入流中,留给下一次输入。比如有char a; cin.get(a);cout<<a; cin.get(a); cout<<a;如果输入a并按回车
的话,则第二次的get调用将不会再提示输入字符,而是接受了第一次输入的单个字符a后面的回车换行了,所
以最后只输入一次,并输出a 再换行。同样如果连续输入两个字符比如ad 则第一个字符a 赋给第一个变量,第
二个字符d赋给第二个变量,同样不会出现提示两次输入的情况,这不是我们所预期希望的效果。同样get()函数
有同样的笑果,即char a; a=cin.get(); cout<<a; a=cin.get(); cout<<a;如果输入a并按回车,有和get(char &ch)同样的
笑果。注意使用>>操作符输入时将忽略掉空格和回车换行符等符号,而get函数则不会。解决上述问题的方法是
在第二次输入前使用ignore()函数读取并丢弃剩下的字符,这样就会提示两次输入。


2、使用get和getline函数输入字符串:
a、字符串输入的get和getline函数原型如下:get(char *, int ,char); get(char* ,int); getline(char*,int ,char); getline(char*,int);
其反回类型都为istream &也就是说这几个函数都可以拼接输出。其中两个参数的函数输入指定长度的字符串,第二
个参数的数目要比将要输入的字符数目大1,因为最后一个字符将作为字符串结尾的字符。带有三个参数的函数的
第三个参数是分界符字符,也就是说当输入时遇到第三个字符就不会再输入后面的字符了,即使输入的字符串没有
达到指定的长度。
b、get 与getline 的区别是get 函数将分界符留在输入流中,这样下次再输入时将输入的是这个分界符。而getline 则是
读取并丢弃这个分界符。比如cin.get(a,3,’z’)如果输入abz 则字符z 将留在输入流中,等待下一次输入,比如在get
函数后接着有cin>>b;则字符z将赋给变量b,而不会再次提示输入。
c、输入的字符数超过了指定数量长度时的处理情况:对于getline函数来说,如果输入的字符数大于指定的字符数的长
度,且最后一个字符不是分界符时,将设置failbit 位。比如cin.getline(a,3,’z’)如果输入abdc,则会设置failbit 位,而
如果输入abzde则不会设置failbit位,因为虽然输入超过了指定的长度,但是最后一个字符是分界符z,所以不会设
置failbit位,而会将分界字符z后面的字符留在输入流中,留给下一次输入。而对于get函数当输入的字符数超过了
指定的长度时则不会设置failbit位,对于get函数可以使用peek()函数来检查是否程序是正常结束输入。如果使用get
函数输入超出指定数目的字符时,多于的字符将作为下一次输入的字符,而对于getline函数而言则会关闭下一次输
入,因为getline 函数在输入的字符数超过了指定的数量时将设置状态位failbit,在状态位被清除前输入会被关闭,
除非被重设。对于这两个函数而言,当达到文件尾时都将设置eofbit位,流被破坏时设置badbit位。
d、输入是空字符时的处理情况:对于get 函数而言,如果输入的是一个空字符则会设置failbit 位,但对于getline 函数
来说则不会设置该位。比如cin.get(a,3);这时如果输入时直接按下回车的话将使get函数设置failbit位,而对于getline
函数而言则不会设置该位。
e、对于以上的get 和getline 函数,不管是输入的是单个字符还是字符串,都需要使用ignore 函数来读取并丢弃多余的
输入字符,以使后面的输入程序能正常的工作。


3、read()函数:函数原型为iostream& read(const char* addr,streamsize n)。调用方法为cin.read(a,144);表示输入144个
字符放到地址从a 开始的内存中,如果还未读取144 个字符就到达了文件末尾,就设置ios::failbit。read 函数与get
和getline不同的是read函数不会在输入后加上空值字符,与就是说输入的数目不必比指定的数目少1,也就是不能
将输入的字符转换为字符串了。read函数可以拼接。


4、readsome()函数:原型为iostream& readsome(char* addr,streamsize n)。表示把n个字符放到地址从addr开始的内存中,
该函数和read函数差不多,区别在于,如果没有读取n个字符,则设置文件结束状态位ios::eofbit。


5、write()函数:原型为iostream& write(const char* addr,streamsize n);表示把从地址addr开始的n个字符写入到流中。


6、peek()函数:peek 函数反回输入流中的下一个字符,但不抽取输入流中的字符,也就是说他使得能够查看下一个输
入字符。


7、gcount()函数:反回最后一个非格式化抽取方法读取的字符数。非格式化抽取方法即get 和getline 这样的函数,>>
这个运算符是格式化抽取方法。


8、strlen()函数:计算数组中的字符数,这种方法比使用gcount函数计算字符数要快。


9、注意:以上的函数都是输入流类的成员函数,使用他们时需要使用输入流类的对象来调用,比如cin.get()等。


再次提醒:以上的函数只适合于char类型的数组,不适用于string类型的对象。比如string a; cin.get(a,3);则将发生错
误,因类string类型的对象a无法转换为char类型的数组。

 

 

  • 23
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值