Introduction
The following c console application is a simple concept of how atm / abm would function. Basically, the console app manipulates data using sequential and random access files by giving the users options to do so as if it's a real-time banking app.
This article is useful for both beginners and Intermediate developers who are interested in using c objective programming skills and techniques such as to declaring variables, manipulating data by sequential and random access files , calling functions, passing values or references and use of pointers etc.
The code will help developers to test and understand c programming concepts. Please Rate :)
Background
The following list and snippet below show the basic function of the c atm console application.
Logins: see customers.txt
For customer: a/c no: 1000 pin: 0
For admin: a/c no: 2000 pin: 0
At start up:
- Login (User Transactions) – If selected, the user is asked for their account credentials (this is analogous to swiping the card) a/c number and pin. Once entered and successfully log-in the User Transactions menu is displayed.
- Exit – Ends the application.
Customer Transaction Menu
- Customer Log-in - If log-in with a customer a/c number then shown above are your options.
Administrative Menu
Administrative log-in - If you are login with an admin a/c then shown above are your options.
Using the code
The following c application is coded using one c file because at the time I was creating a simple application that uses structure. However, organizing your code in multiple files is a good practice so that you can easier for you and others to debug your program. With that said, this one c file is organized by functions and group accordingly. See download.
Below is a snippet showing the declaration of c libraries and my three data structures declare for storing my data in a organize way. Using typedef with struct helps me to define my data types, store records and reduce bugs when manipulating data. This method is still used today.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define LINE printf("\n");
#define INPUT printf("-->\t");
typedef struct bank *vault;
typedef struct bank
{
float money;
}atm;
typedef struct user *ulist;
typedef struct user
{
int userid,pin;
int type,state; float sum;
ulist *next;
}users;
typedef struct log *hlist;
typedef struct log
{
int operation,opuserid;
float opactivity;
hlist *next;
}logs;
Below are the following functions/methods used within the c atm console application. Most of the functions uses parameters. This helps so that the data can pass in, re-used and manipulated across various functions. This technique is useful for debugging, organizing and sharing "the work" between various functions.
Divide and conquer is key technique when developing large applications.
ulist client_hlist (void);
hlist history_hlist(void);
atm banknotes(float balance);
atm read_vaultdb();
int login(ulist header,hlist headerh, int acctno, int acctpin,atm cash);
void userlogin ();
int search_client(ulist header,int key); void create_log(hlist headerh,int noperation, int nopuserid,float noactions);
void option1(ulist header,hlist headerh,int login,int pin,atm cash);
void option2(ulist header,hlist headerh,int login,int pin,atm cash);
void menu(ulist header,hlist headerh,int login,int pin,atm cash);
void menu2(ulist header,hlist headerh,int login, int pin,atm cash);
void create_client(ulist header,hlist headerh,int login,int pin,atm cash);
void create_user(ulist header, int nuserid, int npin, float namount, int ntype, int nstate);
void print_log(ulist header,hlist headerh,int login,int pin,atm cash);
void delete_client(ulist header,hlist headerh,int login, int pin,atm cash);
void print_clients(ulist header,hlist headerh,int login,int pin,atm cash);
int unlock_client(ulist header,hlist headerh,int login, int pin,atm cash);
void query_acct(ulist header,hlist headerh,int login, int pin,atm cash);
void cust_deposit(ulist header, hlist headerh,int login, int pin, atm cash);
void cust_transfer(ulist header,hlist headerh,int login, int pin,atm cash);
void cust_withdraw(ulist header,hlist headerh, int login, int pin, atm cash);
void print_custlog(ulist header,hlist headerh,int login,int pin,atm cash);
int change_client_pin(ulist header,hlist headerh,int login,int pin,atm cash);
void write_custdb(ulist header);
void read_custdb(ulist header);
void read_logdb(hlist headerh);
void write_logdb(hlist headerh);
void write_vaultdb(atm cash);
The snippet below shows how data is stored to the three files. Basically, each file is control by two functions that reads and the other writes. In this case, the data is stored in three (3) text files:
- ATM vault (stores the total amount available)
- Account information (both customer and admin a/c's)
- log information (storing all activity for both admin and customer a/c)
Each method uses parameters from my data structure declared. As these variables value changes they will continue to be group and have the same data type define in my data structure. Therefore, as the data is being manipulated and change across various methods, calling these write or read method won't give me a weird looking output because my data type are consistent within their data structure group.
void write_vaultdb(atm cash)
{
FILE *f_cash = fopen("vault.txt", "w");
fprintf(f_cash,"%6.2f",cash.money );
fclose(f_cash);
}
atm read_vaultdb()
{
float money;
float balance;
FILE *f_cash = fopen("vault.txt", "r");
if (f_cash == NULL)
{
FILE *f_cash = fopen("vault.txt", "w");
fscanf(f_cash,"%f",&balance);
return banknotes(balance);
}
else
fscanf(f_cash,"%f", &money);
return banknotes(money);
}
void read_custdb(ulist header)
{
int i,pin,type,state,userid;
float sum;
FILE *f_clients= fopen("customers.txt", "r");
int res = fscanf(f_clients, "%d\t\t%d\t\t%f\t\t%d\t\t%d\n", &userid,&pin,&sum,&type,&state);
for (i = 0; res > 0; i++)
{
create_user(header,userid,pin,sum,type,state);
res = fscanf(f_clients, "%d\t\t%d\t\t%f\t\t%d\t\t%d\n", &userid,&pin,&sum,&type,&state);
}
fclose (f_clients);
}
void write_custdb(ulist header)
{
ulist l=header->next;
FILE *f_clients = fopen("customers.txt", "w");
while (l)
{
fprintf (f_clients, "%d\t\t%d\t\t%6.2f\t\t%d\t\t%d\n", l->userid,l->pin,l->sum,l->type,l->state);
l=l->next;
}
fclose(f_clients);
}
void read_logdb(hlist headerh)
{
int nop,nuid,i;
float ndest;
hlist l = headerh->next;
FILE *f_hist = fopen("logs.txt", "r");
if (f_hist == NULL)
{
FILE *f_hist = fopen("logs.txt", "w");
}
else
{
int res = fscanf(f_hist, "%d %d %f\n", &nop,&nuid,&ndest);
for (i = 0; res > 0; i++)
{
create_log(headerh,nop,nuid,ndest);
res = fscanf(f_hist, "%d %d %f\n", &nop,&nuid,&ndest);
}
fclose (f_hist);
}
}
void write_logdb(hlist headerh)
{
hlist l=headerh->next;
FILE *f_hist= fopen("logs.txt", "w");
while (l)
{
fprintf (f_hist,"%d %d %6.2f\n",l->operation,l->opuserid,l->opactivity);
l=l->next;
}
fclose(f_hist);
}
As you get familiar with this c coding technique, creating a method to do get, manipulate and return data consistently is basic way when programming in c and other object object oriented languages. In this case, defining data structure, data type and grouping them and have them store consistently is really what makes c and other object oriented languages still used today and is so powerful.
A simple group data structure can let you add, subtract and delete shown in the snippet below:
ulist d = header->next;
cash.money+=value;
d->sum-=fee;
d->sum+=total;
Points of Interest
Developing this code has being fun and interesting although it isn't prefect but I am proud of what I did. I haven't being using c from ever since android invasion to mobile. :) I have being focusing on Java since and various web technology. However, I did this code for someone class project which didn't take me long to finish and their was good remarks. Sharing this code will give me an idea where I can improve and how much positive feedback is there. Please Rate :)
History
March 2014