提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
提示:这里可以添加本文要记录的大概内容:
提示:以下是本篇文章正文内容,下面案例可供参考
C++ 语言中并没有输入/ 输出语句,而是在标准库里包含了一个 I/O 流类库,它与标准模板库同为 C++ 标准库中最重要的组成部分。数据从一个对象到另一个对象的传送被抽象为 “流”。数的输入 / 输出就是通过 输入 / 输出流来实现的;
流是一种抽象的概念,负责在数据的产生者和数据的使用者之间建立联系,并管理数据的流动;
ios 提供了对流进行格式化输入输出和错误处理的成员函数。所有派生都是公有派生。istream 类提供完成提取(输入)
操作的成员函数;而 ostream 类提供完成插入(输出)
操作的成员函数,iostream 类是前两者的结合;
streambuf 是一个独立类,只是 ios 有一个保护访问限制的指针指向它。streambuf 的作用是管理一个流的缓冲区;
在流类库中,最重要的两部分功能为:标准输入 / 输出(standard input / output)和文件处理;在 C++ 的流类库中定义了四个全局流对象:cin、cout、cerr、clog;可以完成人机交互的功能;
【举例1】
// 字符串
int main()
{
char str[256];
int x;
cout << "input int value: " << endl;
cin >> x;
while (cin.fail()) { // 是否失败
cout << cin.rdstate() << endl; // 读取失败状态
cin.clear(0); // 状态清零
cin.getline(str, 256); // 将缓冲区清空
cout << "input int value: " << endl;
cin >> x;
}
cout << "x = " << x << endl;
return 0;
}
【举例2】
int main()
{
const int len = 256;
char str[len];
cin >> str; // yhping hello newdata print
cout << str << endl;
return 0;
}
【注】使用 cin:在连续输入字符串的时候,会以空格作为分隔符,最终打印第一个空格之前的字符;
【分析】使用 getline:默认以 ‘\n’ 分割字符串;getline 也可以指定以什么字符结束输入:
getline(str, len, ‘#’); // 以 # 号结束输入
C++ 根据文件(file)内容的数据格式,可分为两类:二进制文件和文本文件;
【举例 1】
int main()
{
char str[256];
FILE* fp = nullptr;
errno_t tag = fopen_s(&fp, "F:/a.txt", "w");
if (tag) {
cout << "tag = " << tag << endl;
cout << strerror_s(str, 256, tag) << endl;
cout << "str = " << str << endl;
return 0;
}
return 0;
}
【举例 2】
int main()
{
char str[10];
int ar[10] = { 12, 23, 34, 45, 56, 67, 78, 89, 90, 100 };
FILE* fp = nullptr;
errno_t tag = fopen_s(&fp, "b.txt", "w");
if (tag) {
strerror_s(str, tag);
cout << "str = " << str << endl;
exit(1);
}
for (int i = 0; i < 10; ++i) {
//printf("%d ", ar[i]); // stdout 标准输出设备
fprintf(fp, "%d ", ar[i]); // 指定的文件中输出数据
//sprintf(str, "%d ", ar[i]); // 将数据格式化为字符串放到 str 中
}
fclose(fp); // 关闭文件,防止文件指针
fp = nullptr;
return 0;
}
【注】写操作 ”w“:如果当前文件不存在,则创建文件,并写入数据;如果当前文件存在,则清空文件,重新写入数据;
【举例 1】
// 写入文件
#include
int main()
{
const int len = 10;
int ar[10] = { 12, 23, 34, 45, 56, 67, 78 ,89, 90, 100 };
ofstream ofile("a.txt"); // 输出
if (!ofile) {
cout << "file open error" << endl;
exit(1);
}
for (int i = 0; i < len; ++i) {
ofile << ar[i] << " "; // 必须给出空格
}
ofile.close();
return 0;
}
【举例】
// 读文件
#include
int main()
{
int val;
ifstream ifile("a.txt");
if (!ifile) {
exit(1);
}
while (!ifile.eof()) { // 读取文件 读到文件末尾结束,以空格作为分隔符
ifile >> val; // 从文件读取
cout << "val = " << val << endl;
//cin >> val; // 从键盘读取
}
return 0;
}
【注】此种读取方式存在 BUG:当文件末尾有多个空格的时候,需要将空格全部读取完成,
#include
int main()
{
const int len = 10;
int ar[len] = { 12, 23, 34, 45, 56, 67, 78, 89, 90, 100 };
// 二进制: 0C 17 64
ofstream ofile("a.txt", ios::binary); // 以二进制输出文件
if (!ofile.is_open()) {
cout << "file open err " << endl;
exit(1);
}
ofile.write((char*)ar, sizeof(ar));
ofile.close();
return 0;
}
【分析】我们可以看到,向 txt 文件中写入二进制数据之后,再将其打开,看到一堆乱码,是因为:每一个整型数值占 4 字节,二进制存储形式是指:由于数据在内存中是按照二进制的形式存储,先将内存中的数据写入到文件流对象中(按照内存中的存储方式写入),将其存放在输出文件 ofile 的缓冲区,当执行 write 操作时,将数组的内容写入到文件流的缓冲区,最后关闭文件流,关闭的本质是:将写入文件流缓冲区的数据写入到磁盘中,在内存中如何存储,那么写入到磁盘就是按照内存中的存储方式进行写入;此时我们按照文本的形式打开此文件,那么文本文件会将二进制转换为 ASCII 码值来显示,其中 d 是 64 对应的 ASCII 码值;
int main()
{
int ar[10];
ifstream ifile("a.txt", ios::binary);
if (!ifile.is_open()) {
cout << "file open err " << endl;
exit(1);
}
ifile.read((char*)ar, sizeof(int) * 10);
ifile.close();
return 0;
}
【分析】当读取二进制文件时,事先并不知道其中存放多少数据,所以 * 10 是存在 BUG 的,所以文件应该包含头部信息,获取头部信息可以知道其中存放多少什么类型的数据,方便用户读取和操作;
// sprintf 可视化函数 格式化字符串
int main()
{
char str[20];
int a = 100, b = 20;
// str 中存放如下字符:"a = 10 b = 20"
// 若采用如下策略进行存储:
// str[0] = 'a';
// str[1] = ' ';
// str[2] = '=';
// ...
sprintf_s(str, 20, "a = %d b = %d", a, b);
return 0;
}