活期储蓄帐目管理系统
【问题描述】
编写一个活期储蓄帐目管理系统,实现储户开户、销户、存入、支出等活动。其主要要求是能比较迅速地找到储户的帐户,实现存款、取款,还要能比较简单、迅速地实现插入和删除,以实现开户和销户的需要。
【基本要求】
(1)实现储户开户。开户时需要填写登记卡,记录储户信息(包括姓名和帐号),并设置开户余额为0。
(2)实现储户销户。需要先找到储户的帐户信息,然后将其删除。
(3)向某帐户存款。
(4)从某帐户取款。
(5)排序显示所有帐户信息。根据帐号对所有帐户信息排序。
(6)查询某帐户余额。
【选作内容】
(1)查询某帐户交易记录。
(2)所有帐户及其交易信息存储至文件,程序运行时从文件中读入。
理清头绪, 再加上一些些简单的库函数调用就OK了。
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include <time.h>
#define USERS_FILENAME "Users_information.txt"
#define RECORDOPERATION_FILENAME "Record_operation.txt"
#define Status int
#define ERROR 1
#define OK 0
#define OVERFLOW -1
typedef struct {
//该类型结构体用于记录账户信息
char name[10]; //用户姓名
double number; //用户账号
int balance; //账号余额
} Account;
typedef struct LNode {
//用链表存储账户信息
Account data; //链表指针域为账户信息
struct LNode *next; //指针域
} LNode, *LinkList;
typedef struct {
//该结构体用于记录账号的操作记录
int time_year;
int time_mon;
int time_day;
int time_hour;
int time_min;
int time_sec;
double record_accont;
char record_name [6];
int money_number;
} Record;
typedef struct Operation {
//该链表存储操作记录
Record data;
struct Operation *next;
} Operation, *RecordOperation;
Status Read_Account ( LinkList &L ) {
//从文件读入数据并初始化账号信息链表
LinkList p,q;
FILE *fp = fopen ( USERS_FILENAME, "r" ); //以只读的方式打开存有用户信息的文件
if ( !fp )
{
printf ("\n用户信息文件不存在\n");
FILE *fp = fopen ( USERS_FILENAME, "wa" );
printf ( "\n\n新建用户信息文件成功\n\n" );
}
L = ( LinkList ) malloc (sizeof (LNode) ); //构建链表
if ( !L )
{
printf ("\n分配内存失败\n");
exit ( ERROR );
}
L->next = NULL;
if ( !fread ( &L->data, sizeof( Account ), 1, fp ) )
{
//当读入文件得到无效信息时
L->data.number = 20175101000; //第一个注册的账号以 20175101000 为基础加1
return OK;
}
q = L;
p = ( LinkList ) malloc ( sizeof ( LNode ) ); //为文件存储信息分配空间
if ( !p )
{
printf ("\n分配内存失败\n");
exit ( ERROR );
}
while ( fread ( &p->data, sizeof( Account ), 1, fp ) )
{
//读入文件成功时
q->next = p;
p->next = NULL; //读入有效信息时添加到链表中
p = ( LinkList ) malloc ( sizeof ( LNode ) ); //为下一条信息分配空间
if ( !p )
{
printf ("\n分配内存失败\n");
exit ( ERROR );
}
q = q->next;
}
free ( p ); //最后一次调用fread函数返回值为0,最后一次读入的是无效信息,应释放为其分配的内存空间
fclose ( fp ); //关闭文件
return OK;
}
Status Read_Record ( RecordOperation &T ) {
//从文件中读入操作记录并存储在链表中
RecordOperation p,q;
FILE *fp = fopen ( RECORDOPERATION_FILENAME, "r" ); //以只读的方式打开存有操作记录的文件
if ( !fp )
{
printf ("\n操作信息文件不存在\n\n");
FILE *fp = fopen ( RECORDOPERATION_FILENAME, "wa" );
printf ( "新建操作信息文件成功\n\n" );
}
T = ( RecordOperation ) malloc (sizeof ( Operation ) ); //构建链表
if ( !T )
{
printf ("\n分配内存失败\n");
exit ( ERROR );
}
T->next = NULL;
q = T;
p = ( RecordOperation ) malloc (sizeof ( Operation ) ); //为文件存储信息分配空间
if ( !p )
{
printf ("\n分配内存失败\n");
exit ( ERROR );
}
while ( fread ( &p->data, sizeof( Record ), 1, fp ) )
{
//读入文件成功时
q->next = p;
p->next = NULL; //读入有效信息时添加到链表中
p = ( RecordOperation ) malloc (sizeof ( Operation ) ); //为下一条信息分配空间
if ( !p )
{
printf ("\n分配内存失败\n");
exit ( ERROR );
}
q = q->next;
}
free ( p ); //最后一次调用fread函数返回值为0,最后一次读入的是无效信息,应释放为其分配的内存空间
fclose ( fp ); //关闭文件
return OK;
}
Status Write_Account ( LinkList &L ) {
//该函数用于把更新后的账号信息存储在文件中
LinkList p = L;
FILE *fp = fopen ( USERS_FILENAME, "w" ); //以从头开始写的方式打开文件
if ( !fp )
{
printf("\n保存文件失败\n");
exit ( ERROR );
}
while ( p )
{
//将更新后的信息写入文件
fwrite ( &p->data, sizeof( Account ), 1, fp );
p = p->next;
}
fclose ( fp ); //关闭文件
return OK;
}
Status Write_Record ( RecordOperation &T ) {
//该函数用于把更新后的操作记录存储在文件中
RecordOperation p = T->next;
FILE *fp = fopen ( RECORDOPERATION_FILENAME, "w" ); //以从头开始写的方式打开文件
if ( !fp )
{
printf("\n保存文件失败\n");
exit ( ERROR );
}
while ( p )
{
//将更新后的信息写入文件
fwrite ( &p->data, sizeof( Record ), 1, fp );
p = p->next;
}
fclose ( fp ); //关闭文件
return OK;
}
void Record_Operation ( RecordOperation &T, Record rp ) {
//该函数用于添加一个账号的操作记录
RecordOperation m, n = T;
m = ( RecordOperation ) malloc ( sizeof ( Operation ) );
if ( !m )
{
printf ( "\n为操作记录分配内存失败\n" );
exit ( ERROR );
}
time_t t;
struct tm * lt;
time ( &t ); //获取Unix时间戳。
lt = localtime (&t); //转为时间结构
rp.time_year = lt->tm_year+1900;
rp.time_mon = lt->tm_mon + 1;
rp.time_day = lt->tm_mday;
rp.time_hour = lt->tm_hour;
rp.time_min = lt->tm_min;
rp.time_sec = lt->tm_sec;
m->data = rp;
while ( n->next )
{
n = n->next;
}
n->next = m;
m->next = NULL;
}
Status Register ( LinkList &L, RecordOperation &T ) {
//该函数用于注册一个新账户
Record rp; //记录本次操作相关信息
Account enroll; //记录正在注册的账户信息
enroll.balance = 0; //余额初始化为0
LinkList p = L, q; //q用于搜索已有账户信息并与正在注册账户的信息进行比对
printf ( "\n请输入注册人姓名:\n\n" );
scanf ( "%s", enroll.name );
while ( p->next )
{
//比对正在注册的账户信息与已注册过的账户信息
if ( strcmp ( p->next->data.name, enroll.name ) == 0 ) //当正在注册账户姓名已存在时
{
printf ( "\n此身份信息已被注册\n\n" );
return OVERFLOW;
}
p = p->next;
}
q = ( LinkList ) malloc ( sizeof ( LNode ) ); //比对完毕为正在注册账户信息分配存储空间
if ( !q )
{
printf ( "\n无法分配存储空间,注册失败\n\n" );
return OVERFLOW;
}
else
{
enroll.number = L->data.number + 1; //以注册过的最大账号为基础加1作为正在注册的账号
L->data.number ++ ; //记录现有的最大账号
p->next = q;
q->next = NULL;
q->data = enroll;
rp.record_accont = enroll.number; //记录注册的账号
strcpy ( rp.record_name, "注册" ); //记录本次操作名称为“注册”
Record_Operation ( T, rp ); //调用函数添加本次操作记录
printf ( "\n注册成功! 账号为 %.0lf \n\n", q->data.number );
return OK;
}
}
Status Query ( LinkList L ) {
//该函数用于查询一个账户的信息
int i = 0;
LinkList p = L->next;
printf ( "请选择查询方式: 1:通过账号查询 2:通过姓名查询\n" );
scanf ( "%d", &i );
while ( i != 1 && i != 2 )
{
printf ( "\n输入的指令无效\n\n" );
printf ( "请选择查询方式: 1:通过账号查询 2:通过姓名查询\n" );
scanf ( "%d", &i );
}
if ( i == 1 )
{
double number; //将要查询的账号
printf ( "请输入要查询的账号:" );
scanf ( "%lf", &number );
while ( p )
{
if ( number == p->data.number ) //比对账号信息
{
break;
}
p = p->next;
}
}
else if ( i == 2 )
{
char name[11]; //将要查询的姓名
printf ( "请输入将要查询账户户主姓名: " );
scanf ( "%s", name );
while ( p )
{
if ( strcmp ( name, p->data.name ) == 0 ) //比对姓名信息
{
break;
}
p = p->next;
}
}
if ( !p )
{
printf ( "\n该账户不存在\n\n\n" );
return OVERFLOW;
}
else
{
printf ( "用户姓名:%s 用户账号:%.0lf 余额:%d\n\n\n", p->data.name, p->data.number, p->data.balance );
return OK;
}
}
void Query_Record ( RecordOperation T ) {
//该函数用于查询一个账号的所有操作记录,包括已经注销过的账号
double number;
int i = 0;
RecordOperation p = T->next;
printf ( "\n请输入想要查询的账号:" );
scanf ( "%lf", &number );
printf ( "\n账户:%.0lf 的操作记录 : \n\n", number );
while ( p )
{
if ( p->data.record_accont == number )
{
printf("%d/%d/%d/%d:%d:%d",p->data.time_year,p->data.time_mon,p->data.time_day,p->data.time_hour,p->data.time_min,p->data.time_sec);
printf(" %s", p->data.record_name );
if ( strcmp ( p->data.record_name, "注册" ) !=0 && strcmp ( p->data.record_name, "注销" ) != 0 )
{
printf ( " %d 元\n\n",p->data.money_number );
}
else
{
printf ( "\n\n" );
}
i ++;
}
p = p->next;
}
if ( i == 0 )
{
printf ( "\n暂无此账号操作记录\n\n\n" );
}
}
Status Delete ( LinkList &L, RecordOperation &T ) {
//该函数用于注销一个账户
int i;
Record rp; //记录本次操作相关信息
LinkList q = L, p = L->next;
change:
printf( "\n请选择: 1:通过账号注销 2:通过姓名注销 0:退出\n" );
scanf ( "%d", &i );
if ( i == 1 || i== 2 )
{
if ( i == 1 )
{
double number; //将要注销的账号
printf ( "\n请输入要注销账户的账号:" );
scanf ( "%lf", &number );
while ( p )
{
if ( number == p->data.number )
{
break;
}
p = p->next;
q = q->next;
}
}
else
{
char name[11];
printf ( "\n请输入将要注销账户户主姓名: " );
scanf ( "%s", name );
while ( p )
{
if ( strcmp ( name, p->data.name ) == 0 )
{
break;
}
p = p->next;
q = q->next;
}
}
if ( p )
{
printf ( "\n是否要注销此账户? 姓名:%s 账号:%.0lf 当前余额:%d\n", p->data.name, p->data.number, p->data.balance );
printf ( "\n1:是 2:否\n" );
scanf ( "%d", &i );
if ( i == 1 )
{
q->next = p->next;
strcpy ( rp.record_name, "注销" );
rp.record_accont = p->data.number;
free ( p );
Record_Operation ( T, rp );
printf ( "\n注销成功\n\n" );
return OK;
}
}
else
{
printf ( "\n没有找到该账户\n" );
return ERROR;
}
}
else if ( i == 0 )
{
return OVERFLOW;
}
else
{
printf ( "\n输入的指令无效\n" );
goto change;
}
}
Status Deposit ( LinkList &L, RecordOperation &T ) {
//该函数用于向一个账户存款
Record rp; //记录本次操作相关信息
int money_number;
double number;
LinkList p = L->next;
printf ( "\n请输入存款帐号:" );
scanf ( "%lf", &number );
while ( p )
{
if ( p->data.number == number )
{
printf ( "\n账户信息: 账号:%.0lf 姓名:%s 余额:%d\n", p->data.number, p->data.name, p->data.balance );
break;
}
p = p->next;
}
if ( !p )
{
printf ( "\n输入账号有误\n\n\n" );
return ERROR;
}
else
{
printf ( "\n请输入存款金额(必须是整数):" );
scanf ( "%d", &money_number );
p->data.balance += money_number;
printf ( "\n存款成功! 余额:%d\n\n", p->data.balance );
strcpy ( rp.record_name, "存款" );
rp.record_accont = number;
rp.money_number = money_number;
Record_Operation ( T, rp );
return OK;
}
}
Status TakeOut ( LinkList &L, RecordOperation &T ) {
//该函数用于从一个账户中取款
Record rp; //记录本次操作相关信息
int money_number;
double number;
LinkList p = L->next;
printf ( "\n请输入取款帐号:" );
scanf ( "%lf", &number );
while ( p )
{
if ( p->data.number == number )
{
printf ( "\n账户信息: 账号:%.0lf 姓名:%s 余额:%d\n\n", p->data.number, p->data.name, p->data.balance );
break;
}
p = p->next;
}
if ( !p )
{
printf ( "\n输入账号有误\n\n\n" );
return ERROR;
}
else
{
printf ( "\n请输入取款金额(必须是整数);" );
scanf ( "%d", &money_number );
if ( p->data.balance < money_number )
{
printf ( "\n余额不足\n" );
return ERROR;
}
else
{
p->data.balance -= money_number;
printf ( "\n取款成功! 余额:%d\n\n", p->data.balance );
strcpy ( rp.record_name, "取款" );
rp.record_accont = number;
rp.money_number = money_number;
Record_Operation ( T, rp );
return OK;
}
}
}
void Overview ( LinkList L ) {
//该函数用于浏览所有账户信息
LinkList p = L->next;
if ( !p )
{
printf ( "\n暂无用户信息\n" );
}
while ( p )
{
printf ( "\n账号:%.0lf 姓名:%-10s 余额:%d\n", p->data.number, p->data.name, p->data.balance );
p = p->next;
}
printf ( "\n\n" );
}
int main()
{
LinkList L;
RecordOperation T;
int i;
Read_Account ( L );
Read_Record ( T );
printf ( "请选择操作: 1:注册账号 3:存款 5:查询所有账户 7:查询一个账号的操作记录\n" );
printf ( " 2:注销账号 4:取款 6:查询指定账户 0:退出\n\n" );
scanf ( "%d", &i );
while ( i )
{
switch ( i )
{
case 1: Register ( L, T );
break;
case 2: Delete ( L, T );
break;
case 3: Deposit ( L, T );
break;
case 4: TakeOut ( L, T );
break;
case 5: Overview ( L );
break;
case 6: Query ( L );
break;
case 7: Query_Record ( T );
}
printf ( "请选择操作: 1:注册账号 3:存款 5:查询所有账户 7:查询一个账号的操作记录\n" );
printf ( " 2:注销账号 4:取款 6:查询指定账户 0:退出\n\n" );
scanf ( "%d", &i );
}
Write_Account ( L );
Write_Record ( T );
return 0;
}