Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Financial Account Tracker (FAT) v0.0
- // Geecko, 2011
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- typedef struct
- {
- char name[16];
- int (*f)();
- } Command;
- typedef struct
- {
- int c, i;
- char** v;
- } Argument;
- typedef struct
- {
- int day, month, year;
- char desc[31];
- float balance;
- } Operation;
- char file_path[128];
- Argument arg;
- Operation *op = NULL;
- int op_size = 0;
- // Common
- int checkCommand(Command cmd[], int size, char name[])
- {
- int i;
- for (i=0; i<size; i++)
- {
- if (!strcmp(cmd[i].name,name)) return i;
- }
- return -1;
- }
- int remainingArg()
- {
- return arg.c - arg.i;
- }
- int exec(Command cmd[], int size)
- {
- int err;
- if (arg.i >= arg.c) return -1;
- err = checkCommand(cmd,size,arg.v[arg.i]);
- if (err < 0)
- {
- printf("Invalid command (%s)\n",arg.v[arg.i]);
- return 1;
- }
- arg.i++;
- err = cmd[err].f();
- if (err > 0) printf("Error arg #%d\n",arg.i+err-1);
- arg.i--;
- return 0;
- }
- void push(Operation t)
- {
- op = realloc(op,(++op_size) * sizeof(Operation));
- op[op_size-1] = t;
- }
- void pop()
- {
- op = realloc(op,(--op_size) * sizeof(Operation));
- }
- void getDCB(float* debit, float* credit, float* balance, int id)
- {
- *balance = (id>0 ? op[id-1].balance : 0.f);
- *debit = 0.f;
- *credit = 0.f;
- if (op[id].balance - *balance > 0.f)
- {
- *credit = op[id].balance - *balance;
- }
- else
- {
- *debit = *balance - op[id].balance;
- }
- *balance = op[id].balance;
- }
- void getDMY(int* day, int* month, int* year)
- {
- time_t rawTime;
- struct tm* timeInfo;
- time(&rawTime);
- timeInfo = localtime(&rawTime);
- *day = timeInfo->tm_mday;
- *month = timeInfo->tm_mon + 1;
- *year = timeInfo->tm_year + 1900;
- }
- void tableJoint()
- {
- printf("+-------+----------+-----------------------------+---------+---------+---------+\n");
- }
- void tableHead()
- {
- tableJoint();
- printf("|ID |Date |Description |Debit |Credit |Balance |\n");
- tableJoint();
- }
- void tableElement(int id)
- {
- float balance, credit, debit;
- if (id < 0 || id >= op_size) return;
- getDCB(&debit,&credit,&balance,id);
- printf("|%7d|%02d/%02d/%4d|%29s|",id+1,
- op[id].day,op[id].month,op[id].year,op[id].desc);
- if (credit > 0.f) printf(" |%9.2f|",credit);
- else if (debit > 0.f) printf("%9.2f| |",debit);
- printf("%9.2f|\n",balance);
- }
- // File management
- void load()
- {
- op = NULL;
- op_size = 0;
- FILE* file = fopen(file_path,"r");
- if (file == NULL)
- {
- printf("Error opening file for reading\n");
- return;
- }
- Operation t;
- for (;;)
- {
- if (fscanf(file,"%*d %2d%2d%4d \"%[^\"]\" %f\n",
- &t.day,&t.month,&t.year,t.desc,&t.balance) <= 0) break;
- op = realloc(op,(++op_size) * sizeof(Operation));
- op[op_size-1] = t;
- }
- fclose(file);
- }
- void write()
- {
- int i;
- FILE* file = fopen(file_path,"w");
- if (file == NULL)
- {
- printf("Error opening file for writing\n");
- return;
- }
- Operation t;
- for (i=0; i<op_size; i++)
- {
- t = op[i];
- if (fprintf(file,"%d %02d%02d%4d \"%s\" %.2f\n",
- i+1,t.day,t.month,t.year,t.desc,t.balance) <= 0) break;
- }
- fclose(file);
- }
- // Commands
- int add()
- {
- float amount;
- char desc[31] = {0};
- if (remainingArg() < 2) return remainingArg() + 1;
- if (strncpy(desc,arg.v[arg.i+0],29) <= 0) return 1;
- if (sscanf(arg.v[arg.i+1],"%f",&amount) <= 0) return 2;
- if (amount == 0.f) return 2;
- Operation t;
- getDMY(&t.day,&t.month,&t.year);
- t.balance = amount + (op_size>0 ? op[op_size-1].balance : 0);
- strcpy(t.desc,desc);
- push(t);
- write();
- printf("Adding an operation (%02d/%02d/%4d):\n",t.day,t.month,t.year);
- printf(" - ID is #%d\n",op_size);
- printf(" - Description is \"%s\"\n",desc);
- printf(" - Amount is %+.2f euro(s)\n",amount);
- printf(" - Current balance is %+.2f euro(s)\n",op[op_size-1].balance);
- return 0;
- }
- int delete()
- {
- float old_amount, old_balance;
- char* old_desc;
- if (op_size <= 0)
- {
- printf("Nothing to delete\n");
- return 0;
- }
- old_desc = op[op_size-1].desc;
- old_balance = (op_size>1 ? op[op_size-2].balance : 0);
- old_amount = op[op_size-1].balance - old_balance;
- printf("Deleting the last operation (%02d/%02d/%4d):\n",
- op[op_size-1].day,op[op_size-1].month,op[op_size-1].year);
- printf(" - ID was #%d\n",op_size);
- printf(" - Description was \"%s\"\n",old_desc);
- printf(" - Amount was %+.2f euro(s)\n",old_amount);
- printf(" - Balance is back to %+.2f euro(s)\n",old_balance);
- pop();
- write();
- return 0;
- }
- int view_recap()
- {
- int i;
- float balance, debit, credit, acc_debit=0.f, acc_credit=0.f;
- for (i=0; i<op_size; i++)
- {
- getDCB(&debit,&credit,&balance,i);
- acc_debit += debit;
- acc_credit += credit;
- }
- printf("Total credit: %.2f\n",acc_credit);
- printf("Total debit: %.2f\n",acc_debit);
- printf("Current balance: %.2f\n",balance);
- return 0;
- }
- int view_last()
- {
- int i, n;
- n = 20;
- if (remainingArg() > 0)
- {
- if (sscanf(arg.v[arg.i],"%d",&n) <= 0) return 1;
- }
- if (op_size < n) n = op_size;
- if (n < 1)
- {
- printf("Nothing to print\n");
- return 0;
- }
- tableHead();
- for (i=op_size-n; i<op_size; i++) tableElement(i);
- tableJoint();
- return 0;
- }
- int view_id()
- {
- int id;
- if (remainingArg() <= 0) return 1;
- if (sscanf(arg.v[arg.i],"%d",&id) <= 0) return 1;
- if (id < 1 || id > op_size) return 1;
- tableHead();
- tableElement(id-1);
- tableJoint();
- return 0;
- }
- int view_day()
- {
- int i, day, month, year;
- if (remainingArg() < 3) getDMY(&day,&month,&year);
- else
- {
- if (sscanf(arg.v[arg.i+0],"%d",&day) <= 0) return 1;
- if (sscanf(arg.v[arg.i+1],"%d",&month) <= 0) return 2;
- if (sscanf(arg.v[arg.i+2],"%d",&year) <= 0) return 3;
- }
- for (i=0; i<op_size; i++)
- {
- if (op[i].day == day && op[i].month == month && op[i].year == year) break;
- }
- if (i >= op_size)
- {
- printf("Nothing to print\n");
- return 0;
- }
- tableHead();
- for (i=0; i<op_size; i++)
- {
- if (op[i].day == day && op[i].month == month && op[i].year == year)
- {
- tableElement(i);
- }
- }
- tableJoint();
- return 0;
- }
- int view_month()
- {
- int i, day, month, year;
- if (remainingArg() < 2) getDMY(&day,&month,&year);
- else
- {
- if (sscanf(arg.v[arg.i+0],"%d",&month) <= 0) return 1;
- if (sscanf(arg.v[arg.i+1],"%d",&year) <= 0) return 2;
- }
- for (i=0; i<op_size; i++)
- {
- if (op[i].month == month && op[i].year == year) break;
- }
- if (i >= op_size)
- {
- printf("Nothing to print\n");
- return 0;
- }
- tableHead();
- for (i=0; i<op_size; i++)
- {
- if (op[i].month == month && op[i].year == year) tableElement(i);
- }
- tableJoint();
- return 0;
- }
- int view_year()
- {
- int i, day, month, year;
- if (remainingArg() < 1) getDMY(&day,&month,&year);
- else
- {
- if (sscanf(arg.v[arg.i+0],"%d",&year) <= 0) return 1;
- }
- for (i=0; i<op_size; i++)
- {
- if (op[i].year == year) break;
- }
- if (i >= op_size)
- {
- printf("Nothing to print\n");
- return 0;
- }
- tableHead();
- for (i=0; i<op_size; i++)
- {
- if (op[i].year == year) tableElement(i);
- }
- tableJoint();
- return 0;
- }
- Command cmd_view[6] =
- {
- {"recap",view_recap},
- {"last",view_last},
- {"id",view_id},
- {"day",view_day},
- {"month",view_month},
- {"year",view_year}
- };
- int view()
- {
- if (exec(cmd_view,6) < 0)
- {
- printf("Financial account tracker (FAT) v0.0\n");
- printf("Usage: fat view COMMAND [ARGS]\n\n");
- printf("Commands available:\n");
- printf(" recap\n");
- printf(" last [n]\n");
- printf(" id num\n");
- printf(" day [dd mm yyyy]\n");
- printf(" month [mm yyyy]\n");
- printf(" year [yyyy]\n");
- }
- return 0;
- }
- // Main
- Command cmd_main[3] =
- {
- {"add",add},
- {"delete",delete},
- {"view",view}
- };
- int main(int argc, char **argv)
- {
- arg.c = argc;
- arg.v = argv;
- arg.i = 1;
- strcpy(file_path,argv[0]);
- strcpy(strrchr(file_path,'/')+1,"facc");
- load();
- if (exec(cmd_main,3) < 0)
- {
- printf("Financial account tracker (FAT) v0.0\n");
- printf("Usage: fat COMMAND [ARGS]\n\n");
- printf("Commands available:\n");
- printf(" add \"desc\" amount\n");
- printf(" delete\n");
- printf(" view COMMAND [ARGS]\n");
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement