... continued from my other post.
My Solution
Here's my take on the problem. I didn't care to validate if numbers are provided when asked for, but I made sure the user can enter names with spaces. See GetLine();
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CLINET_NAME 10 /* Including the terminating zero */
#define MAX_ACCOUNT_COUNT 2
#define UNUSED_ACCOUNT 0xFFFFFFFF
#define MAX_USER_INPUT 255
typedef struct
{
unsigned int accountNumber;
char clientName[MAX_CLINET_NAME];
float balance;
} Account;
static Account accounts[MAX_ACCOUNT_COUNT];
static char * lineBuffer = NULL; // Used by GetLine. Do not modify.
static size_t lineBufferLength = 0; // Used by GetLine. Do not modify.
static char * GetLine(size_t max)
{
ssize_t charsRead = getline(&lineBuffer, &lineBufferLength, stdin);
if (charsRead == -1)
{
printf("Error happend. Program terminated.\n");
exit(1);
}
if (charsRead < max)
lineBuffer[charsRead - 1] = '\0'; // Do not include the new line character
else
lineBuffer[max - 1] = '\0'; // Do not allow more characters than max
return lineBuffer;
}
static void GetLineInto(char * buffer, size_t max)
{
strcpy(buffer, GetLine(max));
}
static Account * FindNextUnusedAccount()
{
for (int i = 0; i < MAX_ACCOUNT_COUNT; i++)
if (accounts[i].accountNumber == UNUSED_ACCOUNT)
return &accounts[i];
return NULL;
}
static void PrintAccount(const Account * account)
{
printf("Account number: %u\n", account->accountNumber);
printf("Client Name: %s\n", account->clientName);
printf("Balance: $%.2f\n", account->balance);
}
static bool IsAccountNumberInUse(unsigned int accountNumber)
{
for (int i = 0; i < MAX_ACCOUNT_COUNT; i++)
{
if (accounts[i].accountNumber == accountNumber)
return true;
}
return false;
}
static void SetupAccount(Account * account)
{
unsigned int accountNumber;
printf("Account number: ");
scanf("%u", &accountNumber);
if (IsAccountNumberInUse(accountNumber))
{
printf("This account is already in use. Duplicate accounts are not allowed.\n");
return;
}
if (accountNumber == UNUSED_ACCOUNT)
{
printf("This account number is reserved for internal use.\n");
return;
}
account->accountNumber = accountNumber;
printf("Client Name: ");
getchar(); // Clearning the \n from the stdin. This is one left by scanf.
GetLineInto(account->clientName, MAX_CLINET_NAME);
printf("Balance ($): ");
scanf("%f", &account->balance);
}
static void CreateNewAccount()
{
printf("NEW ACCOUNT\n");
printf("-----------\n");
Account * nextUnusedAccount = FindNextUnusedAccount();
if (!nextUnusedAccount)
{
printf("I'm sorry, but we ran out of accounts for the bank.\nPlease come back at a later time.\n");
return;
}
SetupAccount(nextUnusedAccount);
}
static void ShowSpecificAccounts()
{
printf("SHOW ACCOUNTS\n");
printf("-------------\n");
printf("Please, enter the name of the account holder: ");
getchar(); // Clearning the \n from the stdin. This is one left by scanf.
char * name = GetLine(MAX_CLINET_NAME);
printf("\nAccounts found:\n");
printf("~~~~~~~~~~~~~~~\n");
bool accountFound = false;
for (int i = 0; i < MAX_ACCOUNT_COUNT; i++)
{
if (accounts[i].accountNumber != UNUSED_ACCOUNT &&
strcmp(accounts[i].clientName, name) == 0)
{
PrintAccount(&accounts[i]);
printf("\n");
if (!accountFound)
accountFound = true;
}
}
if (!accountFound)
printf("No account found for client '%s'.\n", name);
}
static void DeleteAccountWithLowestBalance()
{
printf("DELETE ACCOUNT WITH LOWEST BALANCE\n");
printf("----------------------------------\n");
Account * accountWithLowestBalance = NULL;
for (int i = 0; i < MAX_ACCOUNT_COUNT; i++)
{
if (accounts[i].accountNumber != UNUSED_ACCOUNT &&
(accountWithLowestBalance == NULL ||
accounts[i].balance < accountWithLowestBalance->balance))
{
accountWithLowestBalance = &accounts[i];
}
}
if (accountWithLowestBalance)
{
printf("Account deleted:\n");
printf("~~~~~~~~~~~~~~~~\n");
PrintAccount(accountWithLowestBalance);
accountWithLowestBalance->accountNumber = UNUSED_ACCOUNT;
}
else
{
printf("There isn't any account in the system.\n");
}
}
int main()
{
for (int i = 0; i < MAX_ACCOUNT_COUNT; i++)
accounts[i].accountNumber = UNUSED_ACCOUNT;
int choice;
do
{
printf("FIRST BANK - ACCOUNT MANAGEMENT\n");
printf("===============================\n");
printf("1. Create account\n");
printf("2. Show accounts for customer\n");
printf("3. Delete account with lowest balance\n");
printf("4. Exit\n");
do
{
printf("? ");
scanf("%d", &choice);
} while (choice < 1 || choice > 4);
printf("\n");
switch (choice)
{
case 1: CreateNewAccount(); break;
case 2: ShowSpecificAccounts(); break;
case 3: DeleteAccountWithLowestBalance(); break;
case 4: break;
}
printf("\n");
} while (choice != 4);
if (lineBuffer)
free(lineBuffer);
printf("Good bye!\n");
return 0;
}