diff --git a/C/Expense_Tracker/Expense-tracker.c b/C/Expense_Tracker/Expense-tracker.c new file mode 100644 index 0000000..85dc86b --- /dev/null +++ b/C/Expense_Tracker/Expense-tracker.c @@ -0,0 +1,246 @@ +#include +#include +#include +#include + +#define MAX_CATEGORY_LEN 50 +#define MAX_LINE_LEN 256 +#define FILENAME "expenses.csv" + +typedef struct { + char date[11]; + double amount; + char category[MAX_CATEGORY_LEN]; +} Expense; + +void clearInputBuffer() { + int c; + while ((c = getchar()) != '\n' && c != EOF); +} + +void getCurrentDate(char *dateStr) { + time_t t = time(NULL); + struct tm *tm_info = localtime(&t); + strftime(dateStr, 11, "%Y-%m-%d", tm_info); +} + +void initializeFile() { + FILE *file = fopen(FILENAME, "r"); + if (file == NULL) { + file = fopen(FILENAME, "w"); + if (file != NULL) { + fprintf(file, "Date,Amount,Category\n"); + fclose(file); + printf("Created new expense file: %s\n\n", FILENAME); + } else { + printf("Error creating file!\n"); + } + } else { + fclose(file); + } +} + +void addExpense() { + Expense exp; + FILE *file; + + getCurrentDate(exp.date); + + printf("\n=== Add New Expense ===\n"); + printf("Date: %s (today)\n", exp.date); + + printf("Enter amount: $"); + if (scanf("%lf", &exp.amount) != 1 || exp.amount <= 0) { + printf("Invalid amount! Please enter a positive number.\n"); + clearInputBuffer(); + return; + } + clearInputBuffer(); + + printf("Enter category: "); + if (fgets(exp.category, MAX_CATEGORY_LEN, stdin) == NULL) { + printf("Error reading category!\n"); + return; + } + exp.category[strcspn(exp.category, "\n")] = 0; + + if (strlen(exp.category) == 0) { + printf("Category cannot be empty!\n"); + return; + } + + file = fopen(FILENAME, "a"); + if (file == NULL) { + printf("Error opening file!\n"); + return; + } + + fprintf(file, "%s,%.2f,%s\n", exp.date, exp.amount, exp.category); + fclose(file); + + printf("\n✓ Expense added successfully!\n"); + printf(" Date: %s\n", exp.date); + printf(" Amount: $%.2f\n", exp.amount); + printf(" Category: %s\n", exp.category); +} + +void viewExpenses() { + FILE *file; + char line[MAX_LINE_LEN]; + int count = 0; + double total = 0.0; + + file = fopen(FILENAME, "r"); + if (file == NULL) { + printf("No expenses found! File doesn't exist.\n"); + return; + } + + printf("\n=== All Expenses ===\n"); + printf("%-12s %-12s %-20s\n", "Date", "Amount", "Category"); + printf("------------------------------------------------\n"); + + fgets(line, MAX_LINE_LEN, file); + + while (fgets(line, MAX_LINE_LEN, file) != NULL) { + char date[11]; + double amount; + char category[MAX_CATEGORY_LEN]; + + char *token = strtok(line, ","); + if (token != NULL) strcpy(date, token); + + token = strtok(NULL, ","); + if (token != NULL) amount = atof(token); + + token = strtok(NULL, "\n"); + if (token != NULL) strcpy(category, token); + + printf("%-12s $%-11.2f %-20s\n", date, amount, category); + total += amount; + count++; + } + + fclose(file); + + printf("------------------------------------------------\n"); + printf("Total Expenses: %d\n", count); + printf("Total Amount: $%.2f\n", total); +} + +void viewSummaryByCategory() { + FILE *file; + char line[MAX_LINE_LEN]; + + typedef struct { + char category[MAX_CATEGORY_LEN]; + double total; + int count; + } CategorySummary; + + CategorySummary summaries[100]; + int numCategories = 0; + + file = fopen(FILENAME, "r"); + if (file == NULL) { + printf("No expenses found!\n"); + return; + } + + fgets(line, MAX_LINE_LEN, file); + + while (fgets(line, MAX_LINE_LEN, file) != NULL) { + char category[MAX_CATEGORY_LEN]; + double amount; + + strtok(line, ","); + char *token = strtok(NULL, ","); + if (token != NULL) amount = atof(token); + + token = strtok(NULL, "\n"); + if (token != NULL) strcpy(category, token); + + int found = 0; + for (int i = 0; i < numCategories; i++) { + if (strcmp(summaries[i].category, category) == 0) { + summaries[i].total += amount; + summaries[i].count++; + found = 1; + break; + } + } + + if (!found && numCategories < 100) { + strcpy(summaries[numCategories].category, category); + summaries[numCategories].total = amount; + summaries[numCategories].count = 1; + numCategories++; + } + } + + fclose(file); + + printf("\n=== Expense Summary by Category ===\n"); + printf("%-20s %-12s %-10s\n", "Category", "Total", "Count"); + printf("------------------------------------------------\n"); + + for (int i = 0; i < numCategories; i++) { + printf("%-20s $%-11.2f %d\n", + summaries[i].category, + summaries[i].total, + summaries[i].count); + } +} + +void displayMenu() { + printf("\n╔════════════════════════════════════╗\n"); + printf("║ EXPENSE TRACKER MENU ║\n"); + printf("╠════════════════════════════════════╣\n"); + printf("║ 1. Add Expense ║\n"); + printf("║ 2. View All Expenses ║\n"); + printf("║ 3. View Summary by Category ║\n"); + printf("║ 4. Exit ║\n"); + printf("╚════════════════════════════════════╝\n"); + printf("Choose an option: "); +} + +int main() { + int choice; + + printf("╔════════════════════════════════════╗\n"); + printf("║ WELCOME TO EXPENSE TRACKER ║\n"); + printf("╚════════════════════════════════════╝\n\n"); + + initializeFile(); + + while (1) { + displayMenu(); + + if (scanf("%d", &choice) != 1) { + printf("Invalid input! Please enter a number.\n"); + clearInputBuffer(); + continue; + } + clearInputBuffer(); + + switch (choice) { + case 1: + addExpense(); + break; + case 2: + viewExpenses(); + break; + case 3: + viewSummaryByCategory(); + break; + case 4: + printf("\nThank you for using Expense Tracker!\n"); + printf("Your expenses are saved in '%s'\n", FILENAME); + return 0; + default: + printf("Invalid choice! Please select 1-4.\n"); + } + } + + return 0; +} diff --git a/C/Expense_Tracker/Readme.md b/C/Expense_Tracker/Readme.md new file mode 100644 index 0000000..c845746 --- /dev/null +++ b/C/Expense_Tracker/Readme.md @@ -0,0 +1,125 @@ +Expense Tracker (C Program) + +A simple and lightweight command-line Expense Tracker written in C. +It allows you to record, view, and summarize expenses by category — all stored in a CSV file for easy access. + +Features + +Automatically records the current date +Add new expenses with amount and category +Stores data in a expenses.csv file +View all recorded expenses in a tabular format + +Summary of expenses grouped by category + +Persistent data across sessions (CSV-based) + +File Structure +. +├─ expense_tracker.c # Source code +└─ readme.md + +How to Compile & Run + +Make sure you have a C compiler installed (like GCC). + +Compile: +gcc expense_tracker.c -o expense_tracker + +Run: +./expense_tracker + +CSV Format + +The program automatically generates expenses.csv (if not present) with the following header: + +Date,Amount,Category +2025-10-30,199.99,Groceries +2025-10-31,550.00,Travel +... + + +This means you can open it directly in Excel, Google Sheets, or any data analytics tool. + +Menu Options + +When you run the program, you'll see: + +1. Add Expense +2. View All Expenses +3. View Summary by Category +4. Exit + +Add Expense + +Enter amount + +Enter category + +Date auto-fills to today + +Example: + +Enter amount: $250 +Enter category: Utilities +Expense added successfully! +View All Expenses + +Displays all recorded entries: + +Date Amount Category +2025-10-30 $250.00 Utilities + + +Additionally shows: + +Total expense count + +Overall amount spent + +Summary by Category + +Groups expenses by category: + +Category Total Count +Groceries $500.00 3 +Travel $550.00 1 + +Persistent Storage + +All expenses are permanently saved inside expenses.csv, so nothing is lost when the program closes. + +Concepts Used + +File handling (fopen, fprintf, fgets) + +String tokenization (strtok) + +Structs for data modeling + +Looping, conditions, and input validation + +Basic memory-safe input cleanup +Input Validation + +The program prevents: + +Negative/zero amounts +Empty categories +Invalid main menu input + +Future Enhancements (Ideas) + +Delete/Update expenses + +Filter by date range + +Export monthly/annual summaries + +Category-wise budgeting + +Graphical visualization using Python integration + +Author + +Developed as a simple terminal-based expense management utility written in C.