#include <stdio.h> // This defines the standard IO functions
#include <stdlib.h> // This is for atoi
#include <unistd.h> // This is for sleep
#include <string.h> // This is for strlen
#include "atm.h" // This defines the account structure
struct account accounts[MAXACCTS]; // Array of account structures
/*
* Declare functions used in the program.
* This is REQUIRED for functions which return non-integer values.
*/
int load_account_data();
int save_account_data();
struct account *validate_account();
// This is the entry point for the atm program.
int
main(int argc, char **argv)
{
// Declare local variables
int acct_in; // User account number
float amount; // User amount for deposit or withdraw
int fields; // Number of fields processed by scanf
int error; // Function returns error code, 0 = OK
char input[80]; // Data from the keyboard
int keep_going; // Flag - keep the loops going
struct account *my_acct; // Struct pointer for the current record
int pin_in; // User PIN
// 1) Call load_account_data with the structure to load
error = load_account_data(accounts);
if (error) {
printf("Error: Can not open the bank database file.\n");
return 1;
} else if (error >= 2) {
printf("Error: Problems with bank database file.\n");
return 2;
}
for (;;) { // person loop
system("cls"); // clears the screen. "clear" replaces "cls" in Linux/UNIX
printf("Welcome to the ATM Machine!\n\n");
for (keep_going = 1; keep_going;) { // account loop
printf("Please enter your account number: ");
fgets(input, sizeof(input), stdin);
if(input[0] == '0') return 0;
if(input[0] == 'x') return 0;
acct_in = atoi(input);
printf("Please enter your PIN: ");
fgets(input, sizeof(input), stdin);
if(input[0] == '0') return 0;
if(input[0] == 'x') return 0;
pin_in = atoi(input);
// validate the account and PIN against the bank data
my_acct = validate_account(accounts, acct_in, pin_in);
if (my_acct == NULL) {
printf("Invalid account or PIN.\n");
printf("Please try again.\n");
} else {
input[0] = '\0'; // Set for the first time through
for (; keep_going;) { // transaction loop
system("cls"); // Windows clear screen command
printf("Welcome %s %s!\n\n",
my_acct->first_name, my_acct->last_name);
printf("Please choose from the following options:\n\n");
printf("\tB - Balance\n");
printf("\tD - Deposit\n");
printf("\tW - Withdraw\n");
printf("\tE - Exit\n\n");
switch(input[0]) {
case '\0': // This handles the first time through
break;
case 'B':
case 'b': // Balance Logic
printf("Your balance is $%.2f\n",
my_acct->balance);
break;
case 'D':
case 'd': // Deposit logic
printf("Amount: $");
fgets(input, sizeof(input), stdin);
fields = sscanf(input, "%f", &amount);
if (fields <= 0)
printf("Error: Non-numeric amount\n");
else if (amount < 0)
printf("Error: Can NOT transact negative numbers.\n");
else if (amount > 100000)
printf("Error: Can not transact more than $100,000.\n");
else {
my_acct->balance += amount;
printf("Your new balance is $%.2f\n",
my_acct->balance);
}
break;
case 'W':
case 'w': // Withdraw logic
printf("Amount: $");
fgets(input, sizeof(input), stdin);
fields = sscanf(input, "%f", &amount);
if (fields <= 0)
printf("Error: Non-numeric amount\n");
else if (amount < 0)
printf("Error: Can NOT transact negative numbers.\n");
else if (amount > 100000)
printf("Error: Can not transact more than $100,000.\n");
else if (amount > my_acct->balance)
printf("Error: Insufficient funds.\n");
else {
my_acct->balance -= amount;
printf("Your new balance is $%.2f\n\n",
my_acct->balance);
}
break;
case 'E':
case 'e':
case 'X':
case 'x': // Exit logic
printf("Thank you for using the ATM machine.\n\n");
// terminate the transaction and account loops
keep_going = 0;
error = save_account_data(accounts);
if (error >= 1) {
printf("Can not save the database file.\n");
return 1;
}
// This is 2000 milliseconds, not seconds
sleep(2000); // Wait for the user to see the previous message
break;
default:
printf("Unknown command %c", input[0]);
} // switch
if (keep_going) { // Don't ask for input for exit
printf("\nPlease enter your transaction: ");
fgets(input, sizeof(input), stdin);
}
} // Transaction loop
} // If-else
} // Account loop
} // Person loop
} // Main
/*
* Read in the accounts.data file into a structure
* which is passed in as an argument.
*/
int
load_account_data(struct account *acct)
{
// Define local variables
int fields;
FILE *file_in;
// Open the data file
file_in = fopen("accounts.data", "r");
if (file_in == NULL) return 1;
// loop through all the records
for (;; acct++) {
// Read one record into variables
fields = fscanf(file_in, "%s %s %d %d %f",
acct->last_name, acct->first_name,
&acct->acct_number, &acct->pin,
&acct->balance);
// If End Of File, break out of loop
if (fields == EOF) break;
// check for non processed fields
if (fields < 5) return 2;
// check for garbage numbers
// || = logical OR
if (acct->acct_number <= 0 ||
acct->pin <= 0 ||
acct->balance <= 0) return 3;
// check for garbage names
if (strlen(acct->last_name) == 0 ||
strlen(acct->first_name) == 0) return 4;
}
// Mark end of data
acct->pin = 0;
// Close the data file
fclose(file_in);
// Return to the calling function
return 0;
}
/*
* Save all the data in the account structure
* which is passed in as an argument.
*/
int
save_account_data(struct account *acct)
{
FILE *file_in;
// Open the data file
file_in = fopen("accounts.data", "w");
if (file_in == NULL) return 1;
// loop through all the records
for (; acct->pin; acct++) {
// Read one record into variables
fprintf(file_in, "%s %s %d %d %6.2f\n",
acct->last_name, acct->first_name,
acct->acct_number, acct->pin,
acct->balance);
}
// Close the data file
fclose(file_in);
// Return to the calling function
return 0;
}
/*
* Check each member of the bank data to see if the acct and PIN match
* Return the structure address for a match
* Return NULL for no match
*/
struct account *
validate_account(struct account *acct, int acct_in, int pin_in)
{
// loop through all the records
for (; acct->pin; acct++) {
if (acct->acct_number == acct_in &&
acct->pin == pin_in) return(acct);
}
return(NULL);
}