如何用c++做一个可读取数字的笔记本
时间: 2025-09-06 20:21:24 AIGC 浏览: 7
<think>
我们之前讨论了关于斗罗大陆游戏的存档功能,现在用户的新问题是:使用C++编写一个可读取数字的笔记本程序。这是一个全新的问题,与之前的游戏存档无关。
我们需要实现一个简单的笔记本程序,能够记录数字(可能还有文本),并且可以保存和读取笔记本内容。我们可以基于之前存档功能的设计思路,但这次是针对笔记本程序。
笔记本程序需求:
1. 能够添加数字记录(可能还有文本注释)
2. 能够查看所有记录
3. 能够保存记录到文件
4. 能够从文件加载记录
设计思路:
我们可以设计一个Note结构体,保存一条记录(包含数字和可选的文本描述)。
然后使用一个NoteBook类来管理多条记录,并提供保存和加载功能。
存储格式可以选择二进制或文本(如CSV或JSON)。考虑到笔记本数据可能不会特别大,且用户可能希望可读,我们可以采用文本格式(比如每行一条记录,或CSV)。
但用户特别提到“读取数字”,所以重点在数字,但为了扩展性,我们也允许文本注释。
我们将设计:
1. Note结构体:包含一个double类型的数字和一个string类型的注释。
2. NoteBook类:包含一个vector<Note>,以及添加、显示、保存、加载等方法。
存储格式选择CSV:
例如:每行一条记录,数字和注释用逗号分隔。注意:注释中可能包含逗号,所以我们最好用引号将注释括起来,或者使用其他分隔符(如tab)。但为了简单,我们假设注释中不含逗号,或使用tab分隔。
另一种方案:使用简单的空格分隔,但数字和注释之间用空格,注释本身可以包含空格(这样就需要固定格式:一行一条记录,第一个字段是数字,后面都是注释)。这样我们可以读取一行,然后提取第一个数字,剩下的作为注释。
我们选择:每行一条记录,第一项是数字,后面是注释(注释可以包含空格,但不包含换行)。这样我们可以用getline读取一行,然后用stringstream分割第一个数字和后面的注释。
但是,如果注释中可能包含不可预测的字符,我们最好用CSV格式,并引用字符串。这里为了简单,我们采用第一种方法:一行一条记录,数字在前,然后空格,后面是注释(直到行尾)。
例如:
3.14 圆周率
2.71828 自然常数
如果用户输入了空格,那么注释部分就会包含多个空格,这没关系。
步骤:
1. 读取一行,然后尝试提取第一个double,剩下的字符串即为注释(包括后面的空格)。
实现保存和加载:
保存:将每个Note对象写入文件,格式为:数字 + 空格 + 注释 + 换行
加载:读取每一行,将第一个单词转换为数字,剩下的作为注释(注意:数字和注释之间的空格可能不止一个,所以提取第一个单词后,剩下的部分需要去掉开头的空格)。
注意:数字可能为负数。
代码结构:
注意:我们使用C++标准库。
我们将创建一个NoteBook类,包含:
vector<Note> notes;
void addNote(double number, const std::string& comment);
void displayAll() const;
bool saveToFile(const std::string& filename) const;
bool loadFromFile(const std::string& filename);
Note结构体:
double value;
std::string comment;
下面开始实现代码:
</think>
### 使用C++编写数字笔记本程序的实现方法
#### 一、核心数据结构设计
```cpp
#include <vector>
#include <string>
#include <fstream>
// 数字笔记本条目
struct NoteEntry {
double value; // 存储的数字值
std::string timestamp; // 时间戳
std::string comment; // 用户注释
};
// 笔记本整体结构
class DigitalNotebook {
private:
std::vector<NoteEntry> entries;
std::string filename = "notebook.dat";
public:
void addEntry(double val, const std::string& cmt);
void displayAll() const;
bool saveToFile();
bool loadFromFile();
};
```
#### 二、关键功能实现
1. **添加数字条目**
```cpp
#include <ctime>
#include <iomanip>
void DigitalNotebook::addEntry(double val, const std::string& cmt) {
// 获取当前时间戳
auto now = std::time(nullptr);
std::string time_str = std::ctime(&now);
time_str.pop_back(); // 移除换行符
// 创建新条目
entries.push_back({val, time_str, cmt});
std::cout << "已添加: " << val << " - " << cmt << "\n";
}
```
2. **数据显示功能**
```cpp
void DigitalNotebook::displayAll() const {
if (entries.empty()) {
std::cout << "笔记本为空\n";
return;
}
std::cout << "===== 数字笔记 =====";
for (const auto& entry : entries) {
std::cout << "\n[" << entry.timestamp << "]\n"
<< "数值: " << std::fixed << std::setprecision(4) << entry.value
<< "\n注释: " << entry.comment << "\n";
}
std::cout << "===================\n";
}
```
3. **CSV格式文件存储**
```cpp
bool DigitalNotebook::saveToFile() {
std::ofstream file(filename);
if (!file) return false;
// 写入CSV格式
for (const auto& entry : entries) {
file << entry.value << ","
<< "\"" << entry.timestamp << "\","
<< "\"" << entry.comment << "\"\n";
}
return true;
}
```
4. **文件读取解析**
```cpp
#include <sstream>
bool DigitalNotebook::loadFromFile() {
std::ifstream file(filename);
if (!file) return false;
entries.clear();
std::string line;
while (std::getline(file, line)) {
std::istringstream ss(line);
NoteEntry entry;
char comma;
// 解析CSV格式
ss >> entry.value >> comma;
// 处理带引号的字符串
std::getline(ss, entry.timestamp, ',');
if (!entry.timestamp.empty() && entry.timestamp.front() == '"') {
entry.timestamp = entry.timestamp.substr(1, entry.timestamp.size() - 2);
}
std::getline(ss, entry.comment);
if (!entry.comment.empty() && entry.comment.front() == '"') {
entry.comment = entry.comment.substr(1, entry.comment.size() - 2);
}
entries.push_back(entry);
}
return true;
}
```
#### 三、用户交互示例
```cpp
#include <iostream>
int main() {
DigitalNotebook myNotebook;
// 加载现有数据
if (myNotebook.loadFromFile()) {
std::cout << "读取历史笔记成功\n";
}
// 添加新条目
myNotebook.addEntry(3.14159, "圆周率近似值");
myNotebook.addEntry(2.71828, "自然常数");
// 显示所有内容
myNotebook.displayAll();
// 保存数据
if (myNotebook.saveToFile()) {
std::cout << "笔记已保存到文件\n";
}
return 0;
}
```
#### 四、高级功能扩展
1. **数据加密保护**
```cpp
#include <openssl/aes.h>
void encryptData(std::string& data, const std::string& key) {
AES_KEY aesKey;
AES_set_encrypt_key(reinterpret_cast<const unsigned char*>(key.data()), 128, &aesKey);
unsigned char iv[AES_BLOCK_SIZE] = {0};
unsigned char* out = new unsigned char[data.size()];
AES_cbc_encrypt(reinterpret_cast<const unsigned char*>(data.data()),
out, data.size(), &aesKey, iv, AES_ENCRYPT);
data = std::string(reinterpret_cast<char*>(out), data.size());
delete[] out;
}
```
2. **集成Qt图形界面**[^3]
```cpp
#include <QTableWidget>
#include <QFileDialog>
// 在Qt中显示笔记本内容
void displayInTable(QTableWidget* table, const DigitalNotebook& notebook) {
table->setRowCount(notebook.entries.size());
for (int i = 0; i < notebook.entries.size(); ++i) {
const auto& entry = notebook.entries[i];
table->setItem(i, 0, new QTableWidgetItem(QString::number(entry.value)));
table->setItem(i, 1, new QTableWidgetItem(QString::fromStdString(entry.timestamp)));
table->setItem(i, 2, new QTableWidgetItem(QString::fromStdString(entry.comment)));
}
}
// 图形界面保存功能
void onSaveClicked() {
QString path = QFileDialog::getSaveFileName(nullptr, "保存笔记", "", "CSV文件 (*.csv)");
if (!path.isEmpty()) {
notebook.saveToFile(path.toStdString());
}
}
```
3. **数学表达式解析**
```cpp
#include <cmath>
void evaluateExpression(const std::string& expr) {
// 简单表达式求值示例
if (expr.find("sin") != std::string::npos) {
double rad = std::stod(expr.substr(4));
double result = std::sin(rad);
std::cout << "sin(" << rad << ") = " << result << "\n";
}
// 可扩展支持更多数学函数
}
```
#### 五、开发环境配置
1. VS Code配置建议[^1]
- 安装C/C++扩展
- 配置tasks.json用于编译
- 使用CMake进行项目管理
2. 调试技巧
```bash
# 编译命令示例
g++ -std=c++17 -o notebook main.cpp -lcrypto -lssl
```
阅读全文
相关推荐



















