Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
246 changes: 246 additions & 0 deletions C/Expense_Tracker/Expense-tracker.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#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;
}
125 changes: 125 additions & 0 deletions C/Expense_Tracker/Readme.md
Original file line number Diff line number Diff line change
@@ -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.
Loading