C++ I/O相关技巧与问题

当使用C ++ I / O时,有三个头文件要包含在内

#include<iostream>
只要使用C ++ I / O,就包括此文件
#include<iomanip>
当使用控制符、操纵符(manipulator)时,该文件必须包含。
#include<fstream>
每次使用文件时都要包含这个文件。


默认情况下,前导空格(回车符,制表符,空格)被cin忽略。

例如:

int i;
float fl;
std :: cin >> fl;
std :: cin >> i;

然后输入:3.14 <enter> 42 <enter>

  • 3.14被读入fl。 3.14之后的换行符(enter键)仍然位于输入缓冲区中。
  • 由于std :: cin忽略空白,所以第一个换行符被std :: cin >> i“吃掉”。 然后整数42被读入i,第二个换行符留在输入缓冲区中。

std::getline() 在std::cin >> var前使用时可能会出错。

  • getline可以提供第三个参数 ——一个“停止”字符。 这个角色确定了getline的截止输入。 停止字符将从输入流中移除,并且getline结束。 例如:
//遇到字符'w'时,getline停止,并且'w'移出输入流
std :: getline(std :: cin,str,'w';
  • 如果不提供std :: getline()作为第三个参数的“停止”字符,它将在到达换行符时停止。
    假设:
  float fl;
  std::cin >> fl;
  std::string str;
  std::getline(std::cin, str);
  1. 键盘输入:3.14 <enter>
  2. 3.14被读入fl3.14之后的换行符仍然位于输入缓冲区中。
  3. std :: getline(std::cin,str)立即处理仍在输入缓冲区中的换行符。 str变成空字符串。
  4. 由此产生了程序跳过执行了std :: getline()语句。

解决的办法是在std::cin之后添加std :: cin.ignore()。 这将从输入缓冲区中抓取一个字符(在本例中为换行符)并丢弃它。

std :: cin.ignore()有三种调用方式:

  • 无参数:从输入缓冲区中取出一个字符并丢弃:
    std :: cin.ignore();//丢弃一个字符
  • 一个参数:从缓冲区中取出并丢弃指定数量的字符:
    std :: cin.ignore(33); //丢弃33个字符
  • 两个参数:丢弃的字符数,或丢弃任何字符直到某个字符为止(以先到者为准):
    std :: cin.ignore(26,'\n'); //忽略26个字符或换行符,以先到者为准

直接读取数字是有些许问题的

  • 如果std :: cin遇到它无法处理的输入,它会进入fail状态
  • 它无法处理的输入保留在输入流中。
  • 在调用std :: cin.clear()清除fail状态前,所有输入都将被std :: cin忽略
  • 一个直接读取数字的更强大的例子:
    1. 读入数字
    2. 确认输入流仍然正常工作
    3. 如果输入流无法工作(!std::cin)
      1. 调用std::cin.clear()使输入流恢复正常状态。
      2. 从流中删除导致问题的输入:std::cin.ignore(...)
      3. 如果可以的话再次获取输入或者处理错误

直接读取数字的第一个版本:

  #include<limits> 
  float fl;
  int bad_input;
  do{
    bad_input=0;
    std::cin >> fl;
    if(!std::cin)
    {
      bad_input=1;
      std::cin.clear();
      std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
    }

  }while(bad_input);

第二个版本:

  #include<limits> 
  float fl;
  while(!(std::cin >> fl))
  {
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
  }

使用getline读入数字是直接读取数字的更强大的替代方法

#include <string>
...
int i;
float fl;
std::string temp;

std::getline(std::cin, temp);
fl=std::stof(temp);
std::getline(std::cin, temp);
i=std::stoi(temp);
  • getline将读取字符串和数字,而不会进入“失败”状态。
  • 使用转换函数,包括:字符串到整数(stoi),字符串到长整数(stol),字符串到浮点(stof),字符串到双精度(stod)

一旦打开一个文件,就可以像使用std :: cin一样使用它。

std::ifstream someVarName("data.txt");
float fl;
std::string temp;
std::getline(someVarName, temp);
fl=std::stof(temp);
int i;
someVarName >> i;

读取整个文件时,将文件输入嵌入到循环条件中

std::ifstream inf("data.txt");
std::string line;
while(!getline(inf, line).eof())
{
  //process the line
}
  • 一旦达到文件末尾,循环将退出

可以让getline在遇到任何指定的字符时停止读取

std::string temp;
std::getline(std::cin, temp, '|');
  • 如果只有两个参数提供给getline,则getline将在一行的末尾停止(换行符处)。
  • 如果向getline提供了三个参数,getline将在第三个参数所指定的字符处停止。
  • 停止字符不会被读入到字符串中。
  • 停止字符会被消耗掉(从输入流中删除)。

使用while循环和getline可以轻松读取数据被分隔的文件。

假设有如下数据:

John|83|52.2
swimming|Jefferson
Jane|26|10.09
sprinting|San Marin

则可以使用如下方式处理:

std::ifstream inf("data.txt");
std::string name;
while(!std::getline(inf, name, '|').eof())//第一次读取John
{
  Athlete* ap;
  std::string jersey_number;
  std::string best_time;
  std::string sport;
  std::string high_school;
  std::getline(inf, jersey_number, '|'); //第一次读取83
  std::getline(inf, best_time);          //第一次读取52.2
  std::getline(inf, sport, '|');         //第一次读取swimming
  std::getline(inf, high_school);        //第一次读取Jefferson
  ap = new Athlete(name, stoi(number), stof(best_time), sport, high_school);
}

如何让输出流来输出固定的精确数字(例如3.40而不是3.4)

std::cout.setf(std::ios::fixed, std::ios::floatfield);
std::cout.setf(std::ios::showpoint);
std::cout.precision(2);

如何设置打印字段的宽度

假设:int one=4, two=44;

  std::cout << one << std::endl.;
  //output:  "4"

  std::cout << setw(2) << one << std::endl.;
  //output:  " 4"

  std::cout.fill('X');
  std::cout << setw(2) << one << std::endl.;
  //output:  "X4"

  std::cout.fill('X');
  std::cout << setw(2) << two << std::endl.;
  //output:  "44"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值