C++ 从键盘、文件读入

会有一股神秘感。 提交于 2020-01-13 14:45:12

Background Info

  • EOF是C语言中为了区分有效数据和输入结束符的。 EOF的输入由系统锁定,windows下是 ctrl+z,linux/unix下是 ctrl+d.
  • 在 C++ 中,输入输出流被定义为类。C++ 的I/O库中的类称为流类(stream class)。 用流类定义的对象称为流对象。
      输入和输出是数据传送的过程,数据如流水一样从一处流向另一处。C++ 形象地将此过程称为流(Stream)。C++的输入输出流是指由若干字节组成的宇节序列,这些宇节中的数据按顺序从一个对象传送到另一对象。流表示了信息从源到目的端的流动。在输入操作时,字节流从输入设备(如键盘、磁盘)流向内存,在输出操作时,字节流从内存流向输出设备(如屏幕、打印机、磁盘等)。流中的内容可以是ASCII字符、二进制形式的数据、图形图像、数字音频视频或其他形式的信息。
      实际上,在内存中为每一个数据流开辟一个内存缓冲区,用来存放流中的数据。当用cout和插入运算符“<<”向显示器输出数据时,先将这些数据送到程序中的输出缓冲区保存,直到缓冲区满了或遇到endl,就将缓冲区中的全部数据送到显示器显示出来。在输入时,从键盘输入的数据先放在键盘的缓冲区中,当按回车键时,键盘缓冲区中的数据输入到程序中的输入缓冲区,形成cin流,然后用提取运算符“ >>”从输入缓冲区中提取数据送给程序中的有关变量。总之,流是与内存缓冲区相对应的,或者说,缓冲区中的数据就是流。

从键盘读入

1. cin

  • cin 继承了 istream 类,是 istream 的一个对象。
  • cin无法读入空格和换行。

来看一段代码:

#include<iostream>
using namespace std;
char a[10], b;
cin >> b;
cout << b << endl;
cin.getline(a, 10);
cout << a << endl;

运行程序,输入a,程序运行的结果是:

/media/sf_code> ./a.out 
a
a
     // 此处为一个空格
/media/sf_code> 

  这里涉及到的是:cin在读入的时候,输入内容暂时被保存在缓存中,遇到回车时内容被传递给输入流 cin。但是换行符仍然滞留在输入流了,如果在 cin 后面有getline语句,这个换行符就被这个 getline 读取了,于是得到 getline 的结果为空。

  可以用cin.ignore()来清空缓存区。

  cin.getline()不会把’\0’, ‘ ‘, ‘\n’等默认的分隔符写入到字符数组,因此如果在std::cin>>w后面紧接着的cin.getline语句(可以尝试把ignore()语句注释掉),会变为空读入,再后面的cin.getline()就正常读入每一行内容,并且把读入的分隔符舍弃。

2. getline

在C++中本质上有两种getline函数:
第一种:在头文件中,是iostream类的成员函数。
第二种:在头文件中,是普通函数。

第二种其实是在string类定义中对getline进行了重载。

cin.getline()

  • istream& getline (char* s, streamsize n );
  • istream& getline (char* s, streamsize n, char delim );

getline()

  • istream& getline (istream& is, string& str, char delim);
  • istream& getline (istream&& is, string& str, char delim);
  • istream& getline (istream& is, string& str);
  • istream& getline (istream&& is, string& str);

3. cin.get

  • int get();
  • istream& get (char& c);
  • istream& get (char* s, streamsize n);
  • istream& get (char* s, streamsize n, char delim);
  • istream& get (streambuf& sb);
  • istream& get (streambuf& sb, char delim);

  cin.get() 遇到delimiting character 时候是不读取的,将其留在流中;而 getline() 读取限定符但不显示。
  假定输入一串字符,以Enter结束输入。cin.get遇到 \n后便返回,此时\n还留在缓冲区中,所以下次读出来的将是\n,而getline遇到\n时会将其从缓存区中移除之后在返回。所以很多时候用getline方便些。

利用 while 连续读入

  • while (bool) 语句的判定条件是一个bool类型,而 getline 返回地类型是 istream. 这里实际上还隐式的调用了转换函数,将 istream 转换成 bool.
operator void *() const { if(state&(badbit|failbit) ) return 0; return (void *)this; }
operator bool() const { if(state&(badbit|failbit) ) return 0; return (void *)this; }
string s;
while(getline(cin,s)) {
    cout << s << endl;
}

从文件读入

  从文件读入和从键盘读入类似,只是需要先将文件以文件流的形式打开。

// 输入文件流
#include<iostream>
#include<fstream>
#include <string>
using namespace std;

int main() {
  char line[50];
  ifstream ifile("./text.txt");  
  while (ifile.getline(line, sizeof(line))) {
    cout << line << endl;
  }
  ifile.close();
  return 0;
}
// 输出文件流
#include<iostream>
#include<fstream>
#include <string>
using namespace std;

int main() {
  ofstream ofile("./text2.txt");
  ofile << "hello world!" << endl; 
  ofile.close();
  return 0;
}

References:
getline函数介绍:
https://www.cnblogs.com/xiaofeiIDO/p/8574042.html
getline实际使用中常见问题分析:
https://blog.csdn.net/iamiman/article/details/53468250
https://blog.csdn.net/JiuHuangShan/article/details/53150766
文件流:
https://www.cnblogs.com/zhengfa-af/p/8157199.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!