流的使用之一:清空输入缓冲区、string类型转换

参考:http://www.programfan.com/club/showbbs.asp?id=176827

清空输入缓冲区的方法

在获取用户输入时,如果发生类型不匹配的错误,输入设备对象将处在出错状态,不能继续输入信息。例如,cin >> i; 输入一个字幕'a',就会出现错误。这时,需要清空输入缓冲区,以继续输入信息。

fflush (stdin)在c++标准中,未定义其返回,vc对其进行了扩充,但其他编译器不一定能通过编译。要写可移植的代码,可用以下方法来清空输入缓冲区。只需要在scanf函数后面加上几句简单的代码就可以了。

/*C版本*/
int main(void)
{
 int i,c;
 for(;;) {
  fputs ("Pleaseinputaninteger:", stdout); 
  if(scanf("%d",&i)!=EOF) { /*如果用户输入的不是EOF*/

  /*while循环会把输入缓冲中的残留字符清空*/
  /*读者可以根据需要把它改成宏或者内联函数*/
  /*注:C99中也定义了内联函数,gcc3.2支持*/

  while ((c=getchar()) != '/n'&&c!=EOF) {
   ;
  }
/*endofwhile*/
 }
 printf ("%d/n", i);
 return 0;
}

//C++版本
usingstd::cout;
usingstd::endl;
usingstd::cin;

int main()
{
 int value;

 for (; ;){
  cout << "Enteraninteger:";
  cin >> value;

  /*读到非法字符后,输入流将处于出错状态,
  *为了继续获取输入,首先要调用clear函数
  *来清除输入流的错误标记,然后才能调用
  *ignore函数来清除输入缓冲区中的数据。*/

  cin.clear();

  /*numeric_limits::max()返回缓冲区的大小。
  *ignore函数在此将把输入缓冲区中的数据清空。
  *这两个函数的具体用法请读者自行查询。*/

  cin.ignore (std::numeric_limits::max(), '/n');
  cout<
 }
 return0;
}

对c版本做法的争议:

if (scanf ("%d", &i) != EOF) {
 while ((c=getchar()) != '/n' && c != EOF) {
  ;
 }
}

并没有完全解决了问题,存在重大的漏洞。主要问题在于,使用getchar()这种方法并没有清除EOF标志。如果用tc2.0、tc2.01、tc3.0、tc3.1等等编译器运行上述代码,输入时用ctrl+z结尾或者直接输入ctrl+z,程序肯定会进入一个死循环!

原因就是getchar()方式并没有清除EOF标志,我在这里所说的EOF标志并非指函数返回的EOF,而是指当I/O函数遇到EOF时在其内部产生的EOF标志。

偶推荐用rewind (stdin)这个方法,rewind不仅清除了stdin中的内容,还清除EOF标志,用下列语句:

scanf ("%d", &i);
rewind (stdin);

代替上述if语句,无论你如何输入ctrl+z,都不会进入死循环,同时也简单得多,是比较完美的解决方法。 

string类型转换

char*型的字符串可以用c++的 sprintf ,还有MFC的 CString::Format 也不错进行numberTostring的转换。

atof, atoi, atol, _ecvt, _fcvt, _itoa, _i64toa, _itow, _i64tow 这些也是用于char*型的转换numberTostring/stringTonumber。

对于标准c++的string型字符串,可以用以下方法进行类型转换。

stringTonumber

用istringstream,这里给个例子:
template<class T>
T& toValue(const string& s, T& value) {
 istringstream is(s);
 is >> value;
 if (is.fail()) {
  value = 0;
 }
 return value;
}

///
#include <sstream.h>
string s = "12345";
int n = 0;
toValue(s, n);

附加一个例子:

        istringstream iss("#123 1.23 aaa ,zzz kk,k oo.jjj");        
        cout << iss.str() << endl;

        char ch;
        iss >> ch;
        cout << ch << endl;

        iss >> i;
        cout << i << endl;

        float f;
        iss >> f;
        cout << f << endl;

        char buf[1024];
        iss >> buf;
        cout << buf << endl;
        cout << "OK/n";

        iss.ignore (100, 'j'+1);
        iss >> buf;
        cout << buf << endl;

numberTostring

string a;

1、
 ostringstream oss(a);
 oss <<  999999;

 a = oss.str ();  

 2、
 stringstream ss (a);
 ss << 9;
 ss >> a;

 cout << a;

3、
 itoa
(111, buf, 10);
   //十进制
 a = buf;     
//char* 赋值到 string;

 

sscanf 的例子

#include <stdio.h>

void main( void )
{
   char  tokenstring[] = "15 12 14...";
   char  s[81];
   char  c;
   int   i;
   float fp;

   /* Input various data from tokenstring: */
   sscanf( tokenstring, "%s", s );
   sscanf( tokenstring, "%c", &c );
   sscanf( tokenstring, "%d", &i );
   sscanf( tokenstring, "%f", &fp );

   /* Output the data read */
   printf( "String    = %s/n", s );
   printf( "Character = %c/n", c );
   printf( "Integer:  = %d/n", i );
   printf( "Real:     = %f/n", fp );
}

Output

String    = 15
Character = 1
Integer:  = 15
Real:     = 15.000000

sprintf 的例子

#include <stdio.h>

void main( void )
{
   char  buffer[200], s[] = "computer", c = 'l';
   int   i = 35, j;
   float fp = 1.7320534f;

   /* Format and print various data: */
   j  = sprintf( buffer,     "/tString:    %s/n", s );
   j += sprintf( buffer + j, "/tCharacter: %c/n", c );
   j += sprintf( buffer + j, "/tInteger:   %d/n", i );
   j += sprintf( buffer + j, "/tReal:      %f/n", fp );

   printf( "Output:/n%s/ncharacter count = %d/n", buffer, j );
}
Output

Output:
   String:    computer
   Character: l
   Integer:   35
   Real:      1.732053

character count = 71

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值