C++ 文件输入输出及相关编程知识详解
1. 指针序列化
在序列化指针时,唯一重要的是它是否为 nullptr 。若为 nullptr ,则它不指向任何对象,无需向流中写入对象;若不为 nullptr ,则需将其指向的对象写入流中。可以用布尔值表示指针状态, nullptr 写为 false ,否则写为 true ,并记录其指向的对象。
例如,对于封装了 Node 对象链表(每个 Node 包含一个 Item 对象)的对象,若链表非空,指向第一个对象的指针写为 true ,并将第一个 Node 对象中的 Item 对象写入流。若 Node 的 pNext 指针成员不为 nullptr ,先写入 true ,再写入下一个 Node 对象的 Item 对象。最后一个 Node 的 pNext 成员为 nullptr ,写为 false 结束输出。无需在流中存储 Node 对象,它们只是真实数据 Item 的包装器。
另一种序列化方法是使用标记语言(如 XML)表达对象的数据和结构。这种方法独立于读写数据的编程语言,能保留对象定义。
2. 流操作基础
- 标准库支持的流类型 :字符流、二进制(字节)流和字符串流。
- 标准输入输出流 :
std::cin和std::cout用于输入输出,std::cerr和std::clog为标准错误流。 - 文件流类 :
std::ifstream用于输入,std::ofstream用于输出,std::fstream可同时用于输入和输出。 - 流的打开模式 :决定能否读写流、输出时是否覆盖流内容以及流是二进制还是文本模式。
3. 文件特性
- 文件仅包含字节,无论打开模式如何,可将二进制流按文本读取,反之亦然。
- 以不存在的文件名打开文件输出流会创建文件。
- 文件有开头、结尾和当前位置,可将文件流的当前位置更改为之前记录的位置,如相对于流开头的正偏移、相对于流结尾的负偏移或相对于当前位置的正负偏移。
4. 流操作相关
- 格式化操作 :提取和插入运算符为基本类型数据提供格式化流输入输出操作。
- 自定义对象支持 :可通过重载插入和提取运算符(作为类的友元函数)支持自定义对象的流操作。
- 二进制模式操作 :流类提供
read()和write()成员函数用于二进制模式下的读写,二进制模式操作总是读写字节序列。 - 字符串流类 :提供对内存中
std::string对象的流输入输出操作。
5. 练习题
以下练习题可帮助巩固所学知识:
1. 编写 Time 类,以整数存储小时、分钟和秒,提供重载插入运算符 << ,以 hh:mm:ss 格式将时间打印到任何输出流。
2. 为 Time 类提供简单提取运算符 operator>>() ,读取 hh:mm:ss 格式的时间值,需处理 : 字符。
3. 编写程序将时间值记录到文件,再编写匹配程序读取文件中的时间值并输出到屏幕。
4. 编写程序从标准输入读取文本行,去除所有前导空白并将多个空格转换为单个空格后写入标准输出,在键盘输入和从文件读取字符上进行测试。再编写一个将小写字符转换为大写的程序并进行测试。
5. 定义封装 Box 对象链表的类,为该类实现 operator>>() 和 operator<<() ,以便对象可存储在文件中并读取回来,定义 main() 函数验证类的功能。
6. 其他编程概念
- 指针相关 :指针有多种用途,如数组指针、常量指针等。指针算术运算可用于操作数组元素。智能指针(如
unique_ptr<T>、shared_ptr<T>和weak_ptr<T>)可帮助管理动态内存,避免内存泄漏。 - 函数相关 :函数可通过值传递或引用传递参数,支持函数重载和模板。函数模板可创建通用函数,提高代码复用性。
- 类和对象相关 :类具有封装、继承和多态等特性。封装可隐藏数据,继承可创建类层次结构,多态通过虚函数实现动态绑定。
- 异常处理 :可使用
try-catch块捕获和处理异常,标准库提供了一些异常类,如std::range_error等。
7. 代码示例及操作流程
以下是一些关键操作的代码示例和操作流程:
7.1 指针序列化示例
#include <iostream>
#include <fstream>
// 假设的 Node 和 Item 类
class Item {
// 实现省略
};
class Node {
public:
Item item;
Node* pNext;
Node(const Item& i) : item(i), pNext(nullptr) {}
};
void serializeList(const Node* head, std::ofstream& out) {
if (head == nullptr) {
out << false;
return;
}
out << true;
// 这里可以添加 Item 的序列化代码
serializeList(head->pNext, out);
}
int main() {
Item item1, item2;
Node node1(item1), node2(item2);
node1.pNext = &node2;
std::ofstream outFile("list.txt");
serializeList(&node1, outFile);
outFile.close();
return 0;
}
7.2 文件读写操作示例
#include <iostream>
#include <fstream>
#include <string>
// 写入文件
void writeToFile(const std::string& filename, const std::string& data) {
std::ofstream outFile(filename);
if (outFile.is_open()) {
outFile << data;
outFile.close();
}
}
// 读取文件
std::string readFromFile(const std::string& filename) {
std::ifstream inFile(filename);
std::string content;
if (inFile.is_open()) {
std::string line;
while (std::getline(inFile, line)) {
content += line + '\n';
}
inFile.close();
}
return content;
}
int main() {
std::string data = "Hello, World!";
std::string filename = "test.txt";
writeToFile(filename, data);
std::string readData = readFromFile(filename);
std::cout << readData << std::endl;
return 0;
}
8. 总结
通过学习文件输入输出和相关编程概念,我们可以更好地处理数据的存储和读取,提高程序的灵活性和可维护性。掌握指针序列化、流操作、文件读写等知识,能让我们在实际编程中更加得心应手。同时,通过练习题的实践,可以加深对这些知识的理解和运用能力。
以下是一个简单的 mermaid 流程图,展示文件读写的基本流程:
graph LR
A[开始] --> B{选择操作}
B -->|写入文件| C(打开输出文件流)
C --> D(写入数据)
D --> E(关闭文件流)
B -->|读取文件| F(打开输入文件流)
F --> G(读取数据)
G --> H(关闭文件流)
E --> I[结束]
H --> I
通过以上内容,我们对 C++ 中的文件输入输出及相关编程知识有了较为全面的了解。希望这些知识能帮助你在编程道路上取得更好的成果。
C++ 文件输入输出及相关编程知识详解
9. 数据类型与运算符
-
基本数据类型 :C++ 有多种基本数据类型,如整数类型(
int、long等)、浮点类型(float、double等)和字符类型(char)。不同类型有不同的取值范围和精度。
| 数据类型 | 描述 |
| ---- | ---- |
|int| 整数类型,通常为 32 位 |
|float| 单精度浮点类型 |
|double| 双精度浮点类型 |
|char| 字符类型 | -
运算符 :包含算术运算符(
+、-、*、/等)、关系运算符(>、<、==等)、逻辑运算符(&&、||、!等)和位运算符(&、|、^等)。运算符具有不同的优先级和结合性。
10. 控制结构
- 条件语句 :如
if-else语句和switch语句,用于根据条件执行不同的代码块。
// if-else 语句示例
int num = 10;
if (num > 5) {
std::cout << "Number is greater than 5" << std::endl;
} else {
std::cout << "Number is less than or equal to 5" << std::endl;
}
// switch 语句示例
int choice = 2;
switch (choice) {
case 1:
std::cout << "You chose option 1" << std::endl;
break;
case 2:
std::cout << "You chose option 2" << std::endl;
break;
default:
std::cout << "Invalid choice" << std::endl;
}
- 循环语句 :包括
for循环、while循环和do-while循环,用于重复执行代码块。
// for 循环示例
for (int i = 0; i < 5; i++) {
std::cout << i << std::endl;
}
// while 循环示例
int j = 0;
while (j < 5) {
std::cout << j << std::endl;
j++;
}
// do-while 循环示例
int k = 0;
do {
std::cout << k << std::endl;
k++;
} while (k < 5);
11. 类和对象的深入
- 构造函数和析构函数 :构造函数用于初始化对象,析构函数用于在对象销毁时进行清理工作。
class Box {
public:
// 构造函数
Box(double l, double w, double h) : length(l), width(w), height(h) {}
// 析构函数
~Box() {}
private:
double length;
double width;
double height;
};
- 继承和多态 :继承允许一个类继承另一个类的属性和方法,多态通过虚函数实现动态绑定。
// 基类
class Shape {
public:
virtual double area() = 0; // 纯虚函数
};
// 派生类
class Circle : public Shape {
public:
Circle(double r) : radius(r) {}
double area() override {
return 3.14 * radius * radius;
}
private:
double radius;
};
12. 内存管理
- 动态内存分配 :使用
new和delete运算符进行动态内存分配和释放。
int* ptr = new int; // 分配一个整数的内存
*ptr = 10;
delete ptr; // 释放内存
int* arr = new int[5]; // 分配一个包含 5 个整数的数组
for (int i = 0; i < 5; i++) {
arr[i] = i;
}
delete[] arr; // 释放数组内存
- 智能指针 :如
unique_ptr、shared_ptr和weak_ptr,可自动管理内存,避免内存泄漏。
#include <memory>
// unique_ptr 示例
std::unique_ptr<int> uptr = std::make_unique<int>(10);
// shared_ptr 示例
std::shared_ptr<int> sptr = std::make_shared<int>(20);
13. 模板
- 函数模板 :可创建通用函数,适用于不同的数据类型。
template <typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
int result1 = max(10, 20);
double result2 = max(3.14, 2.71);
- 类模板 :用于创建通用类。
template <typename T>
class Array {
public:
Array(int size) : data(new T[size]), size(size) {}
~Array() { delete[] data; }
private:
T* data;
int size;
};
Array<int> intArray(5);
Array<double> doubleArray(10);
14. 异常处理流程
异常处理是保证程序健壮性的重要手段,以下是异常处理的 mermaid 流程图:
graph LR
A[开始] --> B(执行代码)
B --> C{是否抛出异常}
C -->|是| D(查找匹配的 catch 块)
D --> E(执行 catch 块代码)
E --> F(继续执行后续代码)
C -->|否| F
F --> G[结束]
15. 总结
C++ 是一门功能强大且复杂的编程语言,涵盖了丰富的数据类型、运算符、控制结构、类和对象等知识。通过掌握文件输入输出、指针序列化、内存管理、模板和异常处理等重要概念,我们能够编写出高效、健壮的程序。在实际编程中,要不断实践和总结,灵活运用这些知识,以应对各种编程挑战。
通过以下列表,我们可以快速回顾本文的重点内容:
1. 指针序列化的方法和应用
2. 流操作和文件读写的基本流程
3. 基本数据类型和运算符的使用
4. 控制结构的应用
5. 类和对象的构造、继承和多态
6. 动态内存分配和智能指针的使用
7. 函数模板和类模板的创建
8. 异常处理的流程和方法
希望这些知识能帮助你在 C++ 编程领域取得更大的进步。
超级会员免费看
748

被折叠的 条评论
为什么被折叠?



