1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
| // L07_10_READ_RATES_FROM_FILE.cpp
// 忽略scanf不安全告警
#define _CRT_SECURE_NO_WARNINGS
// 屏蔽scanf返回值被忽略警告
#pragma warning(disable: 6031)
//
#include <stdio.h>
// windows.h提供 Sleep 函数
#include <windows.h>
// errno.h 提供错误码,如 EACCES 13
#include <errno.h>
// string.h 提供 strerror 函数,获取错误码对应的异常说明
#include <string.h>
// stdbool.h 提供布尔逻辑true和false
#include <stdbool.h>
// 附加包含目录已经添加 D:/BC101/Libraries/Mars
// 此处引入自定义的静态库的头文件需要相对路径
#include "str.h"
#include "input.h"
// 附加包含目录已经添加 D:/BC101/Libraries/BOCRates/BOCRates.h
// 此处引入作者提供的静态库的头文件
#include "BOCRates.h"
// #pragma comment:VS 编译器专用指令,给编译器发命令
// lib:表示我要链接一个静态库
// 路径/Mars.lib":库文件在哪里
// 链接器--附加库目录,加上 D:/BC101/Libraries/Mars 和 D:/BC101/Libraries/BOCRates目录
#pragma comment(lib,"Mars.lib")
#pragma comment(lib, "BOCRates.lib")
// 函数声明, 判断文件模式是否有效
bool is_valid_fopen_mode(const char* mode);
// 通用二进制读取:从文件读取任意数据到内存
bool load_data_from_file(const char* filename, void* data, int size);
// 打印外汇牌价结构体信息
void print_rate_info(const EXCHANGE_RATE* rate);
int main()
{
// 定义外汇牌价结构体变量
EXCHANGE_RATE USDRates;
// 从文件中读取数据存到结构体中
load_data_from_file("D:/BC101/Examples/L07/L07_09_SAVE_USD_RATES/USDRates.txt", &USDRates, sizeof(EXCHANGE_RATE));
print_rate_info(&USDRates);
return 0;
}
// 检查文件打开模式是否合法
bool is_valid_fopen_mode(const char* mode)
{
// 合法模式列表
const char* valid_modes[] = {
// 文本模式
"r", "r+",
"w", "w+",
"a", "a+",
// 二进制 b 模式
"rb", "rb+", "r+b",
"wb", "wb+", "w+b",
"ab", "ab+", "a+b"
};
// 计算一共有多少个合法模式
int len = sizeof(valid_modes) / sizeof(valid_modes[0]);
// 逐个比对
for (int i = 0; i < len; i++)
{
// strcmp 也是 string.h 中的,表示对两个字符串进行比较,相等就等于0
if (strcmp(mode, valid_modes[i]) == 0)
{
return true; // 找到合法模式 → 返回真
}
}
return false; // 没找到 → 非法
}
// 通用二进制写入:任意数据原样存文件
// 功能:把 任意一块内存数据 写入文件
// 参数:
// filename 文件名
// data 任意数据指针(void* 万能)
// size 数据大小(sizeof(结构体))
// 返回:true 成功 / false 失败
bool save_data_to_file(const char* filename, const void* data, int size)
{
const char* mode = "wb"; // 二进制写入模式
// 1. 检查模式对不对
if (!is_valid_fopen_mode(mode))
{
printf("错误:文件打开模式( %s )不合法!\n", mode);
return false;
}
printf("文件打开模式( %s )合法!\n", mode);
// 2. 打开文件
FILE* fp = fopen(filename, mode);
printf("文件句柄地址:%p\n", fp);
// 3. 检查文件是否打开成功
if (fp == NULL)
{
printf("打开文件失败!错误编号:%d, 原因: %s\n", errno, strerror(errno));
return false;
}
// 4. 打开成功,进行等待
printf("打开文件成功!\n");
int count;
count = fwrite(data, size, 1, fp);
if (count != 1) {
printf("\n文件写入异常,写入个数:%d,期望个数:%d\n", count, 1);
printf("错误编号:%d, 原因: %s\n", errno, strerror(errno));
fclose(fp);
return false;
}
printf("\n文件写入成功\n");
// 5. 关闭文件,释放文件句柄
fclose(fp);
return true;
}
// 通用二进制读取:从文件读取任意数据到内存
// 参数:
// filename 文件名
// data 接收数据的内存地址
// size 要读取的字节大小(必须和写入时一样)
// 返回:true 成功 / false 失败
bool load_data_from_file(const char* filename, void* data, int size)
{
const char* mode = "rb"; // 二进制只读模式
// 1. 检查模式对不对
if (!is_valid_fopen_mode(mode))
{
printf("错误:文件打开模式( %s )不合法!\n", mode);
return false;
}
printf("文件打开模式( %s )合法!\n", mode);
// 2. 打开文件
FILE* fp = fopen(filename, mode);
printf("文件句柄地址:%p\n", fp);
// 3. 检查文件是否打开成功
if (fp == NULL)
{
printf("打开文件失败!错误编号:%d, 原因: %s\n", errno, strerror(errno));
return false;
}
// 4. 打开成功,进行等待
printf("打开文件成功!\n");
int count;
// 读取数据
count = fread(data, size, 1, fp);
if (count != 1) {
printf("\n文件读取异常,读取个数:%d,期望个数:%d\n", count, 1);
printf("错误编号:%d, 原因: %s\n", errno, strerror(errno));
fclose(fp);
return false;
}
printf("\n文件读取成功\n");
// 5. 关闭文件,释放文件句柄
fclose(fp);
return true;
}
// 打印外汇牌价结构体信息
void print_rate_info(const EXCHANGE_RATE* rate)
{
printf("货币代码:%s\n", rate->CurrencyCode);
printf("货币名称:%s\n", rate->CurrencyName);
printf("发布时间:%s\n", rate->PublishTime);
printf("现汇买入价:%.2f\n", rate->BuyingRate);
printf("现钞买入价:%.2f\n", rate->CashBuyingRate);
printf("现汇卖出价:%.2f\n", rate->SellingRate);
printf("现钞卖出价:%.2f\n", rate->CashSellingRate);
printf("中行折算价:%.2f\n", rate->MiddleRate);
}
|