程序设计实习(5) —— 输入输出和文件操作

输入输出流

istream 是用于输入的流类, ostream 是用于输出的流类. ifstream 继承 自 istream, 用于从文件中读取数据; ofstream 继承自 ostream, 用于向文件中写入数据. fstream 继承自 iostream, 既可以用于输入也可以用于输出.

  • 输入流对象:
    • cin 与标准输入设备相连, 对应于标准输入流, 用于从键盘读取数据, 也可以被重定向为从文件中读取数据.
  • 输出流对象:
    • cout 与标准输出设备相连, 对应于标准输出流, 用于向屏幕输出数据, 也可以被重定向为向文件写入数据.
    • cerr 与标准错误输出设备相连.
    • clog 与标准错误输出设备相连, 但是缓冲的, 用于输出调试信息.

持续读入直到结束:

1
2
3
int x;
while (cin >> x) {
}

背后的原理是 istream 有一个 operator bool() 来判断.

读取输入流:

1
2
istream &getline(char *buf, int bufSize);
istream &getline(char *buf, int bufSize, char delim);

从输入流中读取 bufSize - 1 个字符 (要给 '\0' 留一个) 到缓冲区buf, 或读到碰到 \ndelim 字符为止 (哪个先到算哪个).

默认分隔符是换行符 \n, 也可以指定其他分隔符. 会自动在 buf 中读入数据的结尾添加'\0', '\n'delim 都不会被读入buf, 但会被从输入流中取走.

需要注意, 如果 buf 不足以容纳读入的字符, 就导致读入出错, 其结果就是虽然本次读入已经完成, 但是之后的读入就都会失败了.

重定向:

1
2
freopen("test.txt", "w", stdout); // 重定向标准输出到文件
freopen("test.txt", "r", stdin); // 重定向标准输入到文件

流操纵算子

流操纵算子是一些函数, 需要 #include <iomanip>, 用于控制输入输出流的格式. 例如:

  • 整数流基数: dec (十进制), hex (十六进制), oct (八进制), setbase (设置基数);

  • 浮点数的精度: setprecision (设置精度) (precision 是成员函数);

    • 非定点模式下, setprecision 设置有效数字的位数;
    • 定点模式下 (setiosflags(ios::fixed)), setprecision 设置小数点后面的有效位数;
  • 域宽: setw (设置域宽) (width 是成员函数); 不够宽会用空格填充, 且宽度设置是一次性的.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    int main() {
      int w = 4;
      char string[10];
      cin.width(5);
      while (cin >> string) {
        cout.width(w++);
        cout << string << endl;
        cin.width(5);
      }
    }
    

    输入:

    1
    
    1234567890
    

    输出:

    1
    2
    3
    
    1234
     5678
        90
    

用户也可以自定义流操纵算子, 例如:

1
2
3
4
ostream &tab(ostream &output){
  return output << '\t';
}
cout << "aa" << tab << "bb" << endl;

原理是 iostream 类中有一个 operator<< 函数

1
ostream &operator<<(ostream &(*p)(ostream &));

可以接收一个函数指针作为参数, 且函数内部把 this 对象传入这个函数, 这个函数返回一个 ostream 对象的引用.

文件操作

1
2
#include <fstream> // 包含头文件
ofstream outFile("clients.dat", ios::out | ios::binary); // 创建

给出打开方式: ios::out 输出到文件,删除原有内容; ios::app 输出到文件,保留原有内容,总是在尾部添加.

  • 对于输入文件, 有一个读指针;
  • 对于输出文件, 有一个写指针;
  • 对于输入输出文件, 有一个读写指针;

标识文件操作的当前位置, 该指针在哪里, 读写操作就在哪里进行:

1
2
3
4
5
6
7
ofstream fout("a1.out", ios::app); // 以添加方式打开
long location = fout.tellp(); // 取得写指针的位置
location = 10;
fout.seekp(location); // 将写指针移动到第 10 个字节处
fout.seekp(location, ios::beg); // 从头数 location
fout.seekp(location, ios::cur); // 从当前位置数 location
fout.seekp(location, ios::end); // 从尾部数 location
本文遵循 CC BY-NC-SA 4.0 协议
使用 Hugo 构建