#include // This defines the standard IO functions #include // This is for atoi #include // This is for sleep #include // 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); }