Skip to content

Commit 0cf82f1

Browse files
authored
Merge pull request #100 from riddhima-7321/riddhima-7321-expense-tracker
Expense Tracker in C
2 parents 72f3eb1 + 413b39e commit 0cf82f1

File tree

2 files changed

+371
-0
lines changed

2 files changed

+371
-0
lines changed
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include <time.h>
5+
6+
#define MAX_CATEGORY_LEN 50
7+
#define MAX_LINE_LEN 256
8+
#define FILENAME "expenses.csv"
9+
10+
typedef struct {
11+
char date[11];
12+
double amount;
13+
char category[MAX_CATEGORY_LEN];
14+
} Expense;
15+
16+
void clearInputBuffer() {
17+
int c;
18+
while ((c = getchar()) != '\n' && c != EOF);
19+
}
20+
21+
void getCurrentDate(char *dateStr) {
22+
time_t t = time(NULL);
23+
struct tm *tm_info = localtime(&t);
24+
strftime(dateStr, 11, "%Y-%m-%d", tm_info);
25+
}
26+
27+
void initializeFile() {
28+
FILE *file = fopen(FILENAME, "r");
29+
if (file == NULL) {
30+
file = fopen(FILENAME, "w");
31+
if (file != NULL) {
32+
fprintf(file, "Date,Amount,Category\n");
33+
fclose(file);
34+
printf("Created new expense file: %s\n\n", FILENAME);
35+
} else {
36+
printf("Error creating file!\n");
37+
}
38+
} else {
39+
fclose(file);
40+
}
41+
}
42+
43+
void addExpense() {
44+
Expense exp;
45+
FILE *file;
46+
47+
getCurrentDate(exp.date);
48+
49+
printf("\n=== Add New Expense ===\n");
50+
printf("Date: %s (today)\n", exp.date);
51+
52+
printf("Enter amount: $");
53+
if (scanf("%lf", &exp.amount) != 1 || exp.amount <= 0) {
54+
printf("Invalid amount! Please enter a positive number.\n");
55+
clearInputBuffer();
56+
return;
57+
}
58+
clearInputBuffer();
59+
60+
printf("Enter category: ");
61+
if (fgets(exp.category, MAX_CATEGORY_LEN, stdin) == NULL) {
62+
printf("Error reading category!\n");
63+
return;
64+
}
65+
exp.category[strcspn(exp.category, "\n")] = 0;
66+
67+
if (strlen(exp.category) == 0) {
68+
printf("Category cannot be empty!\n");
69+
return;
70+
}
71+
72+
file = fopen(FILENAME, "a");
73+
if (file == NULL) {
74+
printf("Error opening file!\n");
75+
return;
76+
}
77+
78+
fprintf(file, "%s,%.2f,%s\n", exp.date, exp.amount, exp.category);
79+
fclose(file);
80+
81+
printf("\n✓ Expense added successfully!\n");
82+
printf(" Date: %s\n", exp.date);
83+
printf(" Amount: $%.2f\n", exp.amount);
84+
printf(" Category: %s\n", exp.category);
85+
}
86+
87+
void viewExpenses() {
88+
FILE *file;
89+
char line[MAX_LINE_LEN];
90+
int count = 0;
91+
double total = 0.0;
92+
93+
file = fopen(FILENAME, "r");
94+
if (file == NULL) {
95+
printf("No expenses found! File doesn't exist.\n");
96+
return;
97+
}
98+
99+
printf("\n=== All Expenses ===\n");
100+
printf("%-12s %-12s %-20s\n", "Date", "Amount", "Category");
101+
printf("------------------------------------------------\n");
102+
103+
fgets(line, MAX_LINE_LEN, file);
104+
105+
while (fgets(line, MAX_LINE_LEN, file) != NULL) {
106+
char date[11];
107+
double amount;
108+
char category[MAX_CATEGORY_LEN];
109+
110+
char *token = strtok(line, ",");
111+
if (token != NULL) strcpy(date, token);
112+
113+
token = strtok(NULL, ",");
114+
if (token != NULL) amount = atof(token);
115+
116+
token = strtok(NULL, "\n");
117+
if (token != NULL) strcpy(category, token);
118+
119+
printf("%-12s $%-11.2f %-20s\n", date, amount, category);
120+
total += amount;
121+
count++;
122+
}
123+
124+
fclose(file);
125+
126+
printf("------------------------------------------------\n");
127+
printf("Total Expenses: %d\n", count);
128+
printf("Total Amount: $%.2f\n", total);
129+
}
130+
131+
void viewSummaryByCategory() {
132+
FILE *file;
133+
char line[MAX_LINE_LEN];
134+
135+
typedef struct {
136+
char category[MAX_CATEGORY_LEN];
137+
double total;
138+
int count;
139+
} CategorySummary;
140+
141+
CategorySummary summaries[100];
142+
int numCategories = 0;
143+
144+
file = fopen(FILENAME, "r");
145+
if (file == NULL) {
146+
printf("No expenses found!\n");
147+
return;
148+
}
149+
150+
fgets(line, MAX_LINE_LEN, file);
151+
152+
while (fgets(line, MAX_LINE_LEN, file) != NULL) {
153+
char category[MAX_CATEGORY_LEN];
154+
double amount;
155+
156+
strtok(line, ",");
157+
char *token = strtok(NULL, ",");
158+
if (token != NULL) amount = atof(token);
159+
160+
token = strtok(NULL, "\n");
161+
if (token != NULL) strcpy(category, token);
162+
163+
int found = 0;
164+
for (int i = 0; i < numCategories; i++) {
165+
if (strcmp(summaries[i].category, category) == 0) {
166+
summaries[i].total += amount;
167+
summaries[i].count++;
168+
found = 1;
169+
break;
170+
}
171+
}
172+
173+
if (!found && numCategories < 100) {
174+
strcpy(summaries[numCategories].category, category);
175+
summaries[numCategories].total = amount;
176+
summaries[numCategories].count = 1;
177+
numCategories++;
178+
}
179+
}
180+
181+
fclose(file);
182+
183+
printf("\n=== Expense Summary by Category ===\n");
184+
printf("%-20s %-12s %-10s\n", "Category", "Total", "Count");
185+
printf("------------------------------------------------\n");
186+
187+
for (int i = 0; i < numCategories; i++) {
188+
printf("%-20s $%-11.2f %d\n",
189+
summaries[i].category,
190+
summaries[i].total,
191+
summaries[i].count);
192+
}
193+
}
194+
195+
void displayMenu() {
196+
printf("\n╔════════════════════════════════════╗\n");
197+
printf("║ EXPENSE TRACKER MENU ║\n");
198+
printf("╠════════════════════════════════════╣\n");
199+
printf("║ 1. Add Expense ║\n");
200+
printf("║ 2. View All Expenses ║\n");
201+
printf("║ 3. View Summary by Category ║\n");
202+
printf("║ 4. Exit ║\n");
203+
printf("╚════════════════════════════════════╝\n");
204+
printf("Choose an option: ");
205+
}
206+
207+
int main() {
208+
int choice;
209+
210+
printf("╔════════════════════════════════════╗\n");
211+
printf("║ WELCOME TO EXPENSE TRACKER ║\n");
212+
printf("╚════════════════════════════════════╝\n\n");
213+
214+
initializeFile();
215+
216+
while (1) {
217+
displayMenu();
218+
219+
if (scanf("%d", &choice) != 1) {
220+
printf("Invalid input! Please enter a number.\n");
221+
clearInputBuffer();
222+
continue;
223+
}
224+
clearInputBuffer();
225+
226+
switch (choice) {
227+
case 1:
228+
addExpense();
229+
break;
230+
case 2:
231+
viewExpenses();
232+
break;
233+
case 3:
234+
viewSummaryByCategory();
235+
break;
236+
case 4:
237+
printf("\nThank you for using Expense Tracker!\n");
238+
printf("Your expenses are saved in '%s'\n", FILENAME);
239+
return 0;
240+
default:
241+
printf("Invalid choice! Please select 1-4.\n");
242+
}
243+
}
244+
245+
return 0;
246+
}

C/Expense_Tracker/Readme.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
Expense Tracker (C Program)
2+
3+
A simple and lightweight command-line Expense Tracker written in C.
4+
It allows you to record, view, and summarize expenses by category — all stored in a CSV file for easy access.
5+
6+
Features
7+
8+
Automatically records the current date
9+
Add new expenses with amount and category
10+
Stores data in a expenses.csv file
11+
View all recorded expenses in a tabular format
12+
13+
Summary of expenses grouped by category
14+
15+
Persistent data across sessions (CSV-based)
16+
17+
File Structure
18+
.
19+
├─ expense_tracker.c # Source code
20+
└─ readme.md
21+
22+
How to Compile & Run
23+
24+
Make sure you have a C compiler installed (like GCC).
25+
26+
Compile:
27+
gcc expense_tracker.c -o expense_tracker
28+
29+
Run:
30+
./expense_tracker
31+
32+
CSV Format
33+
34+
The program automatically generates expenses.csv (if not present) with the following header:
35+
36+
Date,Amount,Category
37+
2025-10-30,199.99,Groceries
38+
2025-10-31,550.00,Travel
39+
...
40+
41+
42+
This means you can open it directly in Excel, Google Sheets, or any data analytics tool.
43+
44+
Menu Options
45+
46+
When you run the program, you'll see:
47+
48+
1. Add Expense
49+
2. View All Expenses
50+
3. View Summary by Category
51+
4. Exit
52+
53+
Add Expense
54+
55+
Enter amount
56+
57+
Enter category
58+
59+
Date auto-fills to today
60+
61+
Example:
62+
63+
Enter amount: $250
64+
Enter category: Utilities
65+
Expense added successfully!
66+
View All Expenses
67+
68+
Displays all recorded entries:
69+
70+
Date Amount Category
71+
2025-10-30 $250.00 Utilities
72+
73+
74+
Additionally shows:
75+
76+
Total expense count
77+
78+
Overall amount spent
79+
80+
Summary by Category
81+
82+
Groups expenses by category:
83+
84+
Category Total Count
85+
Groceries $500.00 3
86+
Travel $550.00 1
87+
88+
Persistent Storage
89+
90+
All expenses are permanently saved inside expenses.csv, so nothing is lost when the program closes.
91+
92+
Concepts Used
93+
94+
File handling (fopen, fprintf, fgets)
95+
96+
String tokenization (strtok)
97+
98+
Structs for data modeling
99+
100+
Looping, conditions, and input validation
101+
102+
Basic memory-safe input cleanup
103+
Input Validation
104+
105+
The program prevents:
106+
107+
Negative/zero amounts
108+
Empty categories
109+
Invalid main menu input
110+
111+
Future Enhancements (Ideas)
112+
113+
Delete/Update expenses
114+
115+
Filter by date range
116+
117+
Export monthly/annual summaries
118+
119+
Category-wise budgeting
120+
121+
Graphical visualization using Python integration
122+
123+
Author
124+
125+
Developed as a simple terminal-based expense management utility written in C.

0 commit comments

Comments
 (0)