#pragma once
/*
设计开户的用户信息, 包含结构体、文件操作等
*/
#define ACCOUNT_DATA_FILE "account.txt"
#define CARD_DATA_FILE "card.txt"
enum ACTION_STATE {OK, FAIL}; // OK 0 表示成功, 1 FAIL 失败
struct account_t {
char aid[37]; // uuid 表示, 用户ID
char name[32]; // 用户名
char pwd[32]; // 口令
char phone[12]; // 手机号
};
// 开户
ACTION_STATE add_account(const char* name,
const char* pwd,
const char* phone);
// 登录
ACTION_STATE login_account(const char* name,
const char* pwd,
account_t* account);
#pragma once
#include "account.h"
struct card_t {
char aid[37];
double balance; // 金额
unsigned long no; // 卡号
};
ACTION_STATE add_balance(const char *aid, double money);
ACTION_STATE sub_balance(const char* aid, double money);
void load_data(); // 加载数据
void save_data(); // 保存数据
//头文件
#define _CRT_SECURE_NO_WARNINGS
#include "account.h"
#include <Windows.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
// 必须包含 UUID 相关头文件
#include <rpcdce.h>
#pragma comment(lib, "rpcrt4.lib")
// 存在返回1,不存在返回0
// static修饰时,只能用于当前的源文件中
static int exists(const char* name) { // 搜索name用户名是否存在
FILE* f = fopen(ACCOUNT_DATA_FILE, "r");
int ret = 0;
if (f != NULL) {
char line[256] = "";
while (fgets(line, 256, f) != NULL) {
if (strstr(line, name) != NULL) {
ret = 1;
break;
}
memset(line, 0, 256);// 清空行的空间
}
fclose(f);
}
return ret;
}
static void getAID(char* aid) {
// 定义 UUID 结构体(存储生成的原始 UUID)
UUID uuid;
RPC_STATUS status;
// 生成 UUID(UuidCreate 可能返回 RPC_S_UUID_LOCAL_ONLY:本地生成的 UUID,不影响使用)
status = UuidCreate(&uuid);
if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
return;
}
// 将 UUID 转为 ASCII 字符串(RpcStringFree 需释放该字符串)
RPC_CSTR rpcStr = NULL; // RPC_CSTR 等价于 char*
status = UuidToStringA(&uuid, &rpcStr);
if (status != RPC_S_OK || rpcStr == NULL) {
return; // 转换失败
}
// 将非-字符放入到结果字符串
// strncpy_s(aid, 37, (char *)rpcStr, _TRUNCATE);
int i = 0;
for (int j = 0; j < strlen((char *)rpcStr); j++) {
if (rpcStr[j] != '-') {
aid[i++] = rpcStr[j];
}
}
// 释放 RPC 分配的字符串内存(必须释放,否则内存泄漏)
RpcStringFreeA(&rpcStr);
}
ACTION_STATE add_account(const char* name,
const char* pwd,
const char* phone) {
// 1. 打开文件,搜索name账号是否已存在,如果存在,则不会再开户的
// 如果不存在的,则可以开户。 可以设计exists函数,实现功能
if (exists(name)) return FAIL;
// 2. 可以开户时, 获取UUID 作为用户ID
account_t acc = {0};
// memset(&acc, 0, sizeof(acc)); //初始化
strncpy(acc.name, name, strlen(name));
strncpy(acc.pwd, pwd, strlen(pwd));
strncpy(acc.phone, phone, strlen(phone));
getAID(acc.aid);
// 3. 以追加模式打开文件,并追加一行内容
FILE* f = fopen(ACCOUNT_DATA_FILE, "a");
fprintf(f, "%s,%s,%s,%s\n", acc.aid, acc.name, acc.pwd, acc.phone);
fclose(f);
srand(time(NULL));
// 4. 开通银行卡号
unsigned long card_no = rand() % 10000 + 5678900000;
f = fopen(CARD_DATA_FILE, "a");
fprintf(f, "%s,%.5f,%lu\n", acc.aid, 0.0, card_no);
fclose(f);
return OK;
}
ACTION_STATE login_account(const char* name,const char* pwd,
account_t* account) {
// 以r模式,打开文件
char line[256] = "";
FILE* f = fopen(ACCOUNT_DATA_FILE, "r");
// 读每一行的内容
while (fgets(line, 256, f) != NULL) {
// 通过strstr函数查找 行的内容是否包含 name 用户名
if (strstr(line, name) != NULL) {
char* aid = strtok(line, ",");
char* aname = strtok(NULL, ",");
char* apwd = strtok(NULL, ",");
char* aphone = strtok(NULL, ",");
// 查找到 将数据写入 account 空间中, 且return OK
if (strcmp(apwd, pwd) == 0) {
// 登录成功
strcpy(account->aid, aid);
strcpy(account->name, aname);
strcpy(account->pwd, apwd);
strcpy(account->phone, aphone);
fclose(f);
return OK;
}
}
}
// 未找到内容,关闭文件流
if (feof(f)) fclose(f);
return FAIL;
}
//int main() {
// //printf("%d\n", exists("jack"));
// printf("%d\n", add_account("jack", "8888", "110"));
// //printf("%d\n", add_account("lucy","8888","110"));
//
// account_t acc = { 0 };
// printf("login %d\n" ,login_account("jack", "8888", &acc));
//
// return 0;
//}
#define _CRT_SECURE_NO_WARNINGS
#include "card.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifndef MAX_LEN
#define MAX_LEN 50
#endif
#ifndef LINE_SIZE
#define LINE_SIZE 128
#endif
static card_t* all;
int len = 0;
void load_data() { // 将card.txt文件中的所有数据加载出来
all = (card_t*)malloc(MAX_LEN * sizeof(card_t));
assert(all != NULL);
memset(all, 0, MAX_LEN * sizeof(card_t)); // 初始化
FILE* f = fopen(CARD_DATA_FILE, "r");
char line[LINE_SIZE] = "";
while (fgets(line, LINE_SIZE, f) != NULL) {
//sscanf(line, "%s,%.5f,%lu\n", all[len].aid, &all[len].balance, &all[len].no);
char* aid = strtok(line, ",");
char* balance = strtok(NULL, ",");
char* no = strtok(NULL, ",");
strcpy(all[len].aid, aid);
all[len].balance = atof(balance);
all[len].no = atoi(no);
len++;
}
fclose(f);
}
void save_data() { // 保存数据
FILE* f = fopen(CARD_DATA_FILE, "w");
for (int i = 0; i < len; i++) {
fprintf(f, "%s,%.5f,%lu\n", all[i].aid, all[i].balance, all[i].no);
}
fclose(f);
free(all);//释放空间, 在退出程序之前保存
}
ACTION_STATE add_balance(const char* aid, double money) {
for (int i = 0; i < len; i++) { // 从所有数据中查找用户的银行卡信息
if (strncmp(aid, all[i].aid, strlen(aid)) == 0) {
printf("%lu 余额 %.5f add %.5f ->", all[i].no, all[i].balance,money);
all[i].balance += money; // 在已加载的数据空间中修改
printf("%.5f\n", all[i].balance);
return OK;
}
}
return FAIL;
}
ACTION_STATE sub_balance(const char* aid, double money) {
for (int i = 0; i < len; i++) { // 从所有数据中查找用户的银行卡信息
if (strncmp(aid, all[i].aid, strlen(aid)) == 0) {
printf("%lu 余额 %.5f add %.5f ->", all[i].no, all[i].balance, money);
all[i].balance -= money; // 在已加载的数据空间中修改
printf("%.5f\n", all[i].balance);
return OK;
}
}
return FAIL;
}
//int main() {
// // 1. 登录
// account_t acc = {0};
// if (login_account("jack", "8888", &acc) == OK) {
// load_data();
//
// // 存
// add_balance(acc.aid, 100);
// add_balance(acc.aid, 200);
//
// // 取
// sub_balance(acc.aid, 50);
//
// // 保存数据
// save_data();
// }
//
//
// return 0;
//}
//源文件