Simple Calculator Project in C: Complete Guide

Project Overview

A comprehensive calculator project demonstrating various C programming concepts including functions, loops, conditionals, and user input handling. This project includes multiple calculator implementations from basic to advanced.


Project Structure

calculator_project/
├── basic_calculator.c      # Basic arithmetic operations
├── advanced_calculator.c   # Scientific calculator
├── menu_calculator.c       # Menu-driven interface
├── expression_calculator.c # Expression parsing
├── gui_calculator.c        # Simple GUI (if applicable)
├── calculator.h            # Header file
└── Makefile                # Build configuration

1. Basic Calculator Implementation

basic_calculator.c

#include <stdio.h>
#include <stdlib.h>
// Function prototypes
double add(double a, double b);
double subtract(double a, double b);
double multiply(double a, double b);
double divide(double a, double b);
int modulus(int a, int b);
void printResult(double result, char operation);
int main() {
double num1, num2, result;
char operator;
char choice;
printf("====================================\n");
printf("     SIMPLE CALCULATOR PROGRAM     \n");
printf("====================================\n\n");
do {
// Get user input
printf("Enter first number: ");
scanf("%lf", &num1);
printf("Enter operator (+, -, *, /, %%): ");
scanf(" %c", &operator);
printf("Enter second number: ");
scanf("%lf", &num2);
// Perform calculation based on operator
switch(operator) {
case '+':
result = add(num1, num2);
printResult(result, '+');
break;
case '-':
result = subtract(num1, num2);
printResult(result, '-');
break;
case '*':
result = multiply(num1, num2);
printResult(result, '*');
break;
case '/':
if (num2 != 0) {
result = divide(num1, num2);
printResult(result, '/');
} else {
printf("Error: Division by zero is not allowed!\n");
}
break;
case '%':
// Modulus works only with integers
if ((int)num2 != 0) {
result = modulus((int)num1, (int)num2);
printf("%.0f %% %.0f = %.0f\n", num1, num2, result);
} else {
printf("Error: Modulus by zero is not allowed!\n");
}
break;
default:
printf("Error: Invalid operator!\n");
}
// Ask if user wants to continue
printf("\nDo you want to perform another calculation? (y/n): ");
scanf(" %c", &choice);
printf("\n");
} while(choice == 'y' || choice == 'Y');
printf("Thank you for using the calculator!\n");
return 0;
}
// Function definitions
double add(double a, double b) {
return a + b;
}
double subtract(double a, double b) {
return a - b;
}
double multiply(double a, double b) {
return a * b;
}
double divide(double a, double b) {
return a / b;
}
int modulus(int a, int b) {
return a % b;
}
void printResult(double result, char operation) {
printf("\nResult: %.2f\n", result);
}

2. Menu-Driven Calculator

menu_calculator.c

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// Function prototypes
void showMenu();
double add();
double subtract();
double multiply();
double divide();
double power();
double squareRoot();
double percentage();
double logarithm();
double trigonometric();
void clearScreen();
int main() {
int choice;
do {
showMenu();
printf("Enter your choice (0-9): ");
scanf("%d", &choice);
switch(choice) {
case 1:
printf("\n--- Addition ---\n");
printf("Result: %.2f\n\n", add());
break;
case 2:
printf("\n--- Subtraction ---\n");
printf("Result: %.2f\n\n", subtract());
break;
case 3:
printf("\n--- Multiplication ---\n");
printf("Result: %.2f\n\n", multiply());
break;
case 4:
printf("\n--- Division ---\n");
divide();
break;
case 5:
printf("\n--- Power ---\n");
printf("Result: %.2f\n\n", power());
break;
case 6:
printf("\n--- Square Root ---\n");
squareRoot();
break;
case 7:
printf("\n--- Percentage ---\n");
printf("Result: %.2f%%\n\n", percentage());
break;
case 8:
printf("\n--- Logarithm ---\n");
logarithm();
break;
case 9:
printf("\n--- Trigonometric ---\n");
trigonometric();
break;
case 0:
printf("\nExiting calculator. Goodbye!\n");
break;
default:
printf("\nInvalid choice! Please try again.\n\n");
}
if (choice != 0) {
printf("Press Enter to continue...");
getchar();
getchar(); // Wait for Enter key
clearScreen();
}
} while(choice != 0);
return 0;
}
void showMenu() {
printf("====================================\n");
printf("     ADVANCED CALCULATOR MENU      \n");
printf("====================================\n");
printf(" 1. Addition\n");
printf(" 2. Subtraction\n");
printf(" 3. Multiplication\n");
printf(" 4. Division\n");
printf(" 5. Power (x^y)\n");
printf(" 6. Square Root\n");
printf(" 7. Percentage\n");
printf(" 8. Logarithm\n");
printf(" 9. Trigonometric Functions\n");
printf(" 0. Exit\n");
printf("====================================\n");
}
double add() {
double a, b;
printf("Enter two numbers: ");
scanf("%lf %lf", &a, &b);
return a + b;
}
double subtract() {
double a, b;
printf("Enter two numbers: ");
scanf("%lf %lf", &a, &b);
return a - b;
}
double multiply() {
double a, b;
printf("Enter two numbers: ");
scanf("%lf %lf", &a, &b);
return a * b;
}
double divide() {
double a, b;
printf("Enter two numbers: ");
scanf("%lf %lf", &a, &b);
if (b == 0) {
printf("Error: Division by zero!\n");
return 0;
}
printf("Result: %.2f\n\n", a / b);
return a / b;
}
double power() {
double base, exponent;
printf("Enter base and exponent: ");
scanf("%lf %lf", &base, &exponent);
return pow(base, exponent);
}
void squareRoot() {
double num;
printf("Enter a number: ");
scanf("%lf", &num);
if (num < 0) {
printf("Error: Cannot calculate square root of negative number!\n");
} else {
printf("Square root of %.2f = %.2f\n", num, sqrt(num));
}
}
double percentage() {
double value, total;
printf("Enter value and total: ");
scanf("%lf %lf", &value, &total);
if (total == 0) {
printf("Error: Total cannot be zero!\n");
return 0;
}
return (value / total) * 100;
}
void logarithm() {
double num;
int choice;
printf("1. Natural Log (ln)\n");
printf("2. Log base 10\n");
printf("Choose option: ");
scanf("%d", &choice);
printf("Enter a number: ");
scanf("%lf", &num);
if (num <= 0) {
printf("Error: Number must be positive!\n");
return;
}
switch(choice) {
case 1:
printf("ln(%.2f) = %.2f\n", num, log(num));
break;
case 2:
printf("log10(%.2f) = %.2f\n", num, log10(num));
break;
default:
printf("Invalid option!\n");
}
}
void trigonometric() {
double angle;
int choice;
printf("1. Sine\n");
printf("2. Cosine\n");
printf("3. Tangent\n");
printf("Choose function: ");
scanf("%d", &choice);
printf("Enter angle in degrees: ");
scanf("%lf", &angle);
// Convert to radians
double rad = angle * M_PI / 180.0;
switch(choice) {
case 1:
printf("sin(%.2f°) = %.4f\n", angle, sin(rad));
break;
case 2:
printf("cos(%.2f°) = %.4f\n", angle, cos(rad));
break;
case 3:
printf("tan(%.2f°) = %.4f\n", angle, tan(rad));
break;
default:
printf("Invalid choice!\n");
}
}
void clearScreen() {
// For Windows
#ifdef _WIN32
system("cls");
#else
// For Unix/Linux/Mac
system("clear");
#endif
}

3. Expression Calculator

expression_calculator.c

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#define MAX_EXPRESSION 100
// Function prototypes
double evaluateExpression(const char *expr);
double parseExpression(const char **expr);
double parseTerm(const char **expr);
double parseFactor(const char **expr);
double parseNumber(const char **expr);
void skipWhitespace(const char **expr);
int hasMoreTokens(const char *expr);
void showError(const char *message);
int main() {
char expression[MAX_EXPRESSION];
double result;
char choice;
printf("====================================\n");
printf("    EXPRESSION CALCULATOR          \n");
printf("====================================\n");
printf("Supports: +, -, *, /, ^, ( )\n");
printf("Example: 3 + 4 * 2 / (1 - 5)^2\n\n");
do {
printf("Enter expression: ");
fgets(expression, MAX_EXPRESSION, stdin);
// Remove trailing newline
expression[strcspn(expression, "\n")] = 0;
if (strlen(expression) > 0) {
result = evaluateExpression(expression);
printf("Result: %.4f\n", result);
}
printf("\nAnother expression? (y/n): ");
scanf(" %c", &choice);
getchar(); // Consume newline
printf("\n");
} while(choice == 'y' || choice == 'Y');
return 0;
}
double evaluateExpression(const char *expr) {
const char *p = expr;
double result = parseExpression(&p);
if (*p != '\0') {
showError("Unexpected characters at end");
return 0;
}
return result;
}
double parseExpression(const char **expr) {
double value = parseTerm(expr);
while (**expr != '\0') {
skipWhitespace(expr);
if (**expr == '+') {
(*expr)++;
value += parseTerm(expr);
}
else if (**expr == '-') {
(*expr)++;
value -= parseTerm(expr);
}
else {
break;
}
}
return value;
}
double parseTerm(const char **expr) {
double value = parseFactor(expr);
while (**expr != '\0') {
skipWhitespace(expr);
if (**expr == '*') {
(*expr)++;
value *= parseFactor(expr);
}
else if (**expr == '/') {
(*expr)++;
double divisor = parseFactor(expr);
if (divisor == 0) {
showError("Division by zero");
return 0;
}
value /= divisor;
}
else {
break;
}
}
return value;
}
double parseFactor(const char **expr) {
skipWhitespace(expr);
double value;
if (**expr == '(') {
(*expr)++; // Skip '('
value = parseExpression(expr);
skipWhitespace(expr);
if (**expr != ')') {
showError("Missing closing parenthesis");
return 0;
}
(*expr)++; // Skip ')'
}
else {
value = parseNumber(expr);
}
// Handle exponentiation
skipWhitespace(expr);
if (**expr == '^') {
(*expr)++;
double exponent = parseFactor(expr);
value = pow(value, exponent);
}
return value;
}
double parseNumber(const char **expr) {
skipWhitespace(expr);
char *endptr;
double value = strtod(*expr, &endptr);
if (*expr == endptr) {
showError("Expected number");
return 0;
}
*expr = endptr;
return value;
}
void skipWhitespace(const char **expr) {
while (isspace(**expr)) {
(*expr)++;
}
}
void showError(const char *message) {
printf("Error: %s\n", message);
}

4. Scientific Calculator with Memory Functions

scientific_calculator.c

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define MAX_HISTORY 100
// Structure for calculator memory
typedef struct {
double value;
int isSet;
} Memory;
// Structure for calculation history
typedef struct {
char operation[50];
double result;
} History;
// Global variables
Memory memory = {0, 0};
History history[MAX_HISTORY];
int historyCount = 0;
// Function prototypes
void showScientificMenu();
void basicOperations();
void trigonometricFunctions();
void logarithmicFunctions();
void powerFunctions();
void memoryOperations();
void showHistory();
void addToHistory(const char *op, double result);
void clearHistory();
int main() {
int choice;
do {
showScientificMenu();
printf("Enter your choice: ");
scanf("%d", &choice);
switch(choice) {
case 1:
basicOperations();
break;
case 2:
trigonometricFunctions();
break;
case 3:
logarithmicFunctions();
break;
case 4:
powerFunctions();
break;
case 5:
memoryOperations();
break;
case 6:
showHistory();
break;
case 7:
clearHistory();
break;
case 0:
printf("\nExiting calculator. Goodbye!\n");
break;
default:
printf("\nInvalid choice!\n");
}
if (choice != 0) {
printf("\nPress Enter to continue...");
getchar();
getchar();
system("clear"); // Use "cls" on Windows
}
} while(choice != 0);
return 0;
}
void showScientificMenu() {
printf("\n======================================\n");
printf("    SCIENTIFIC CALCULATOR MENU       \n");
printf("======================================\n");
printf(" 1. Basic Operations (+, -, *, /)\n");
printf(" 2. Trigonometric Functions\n");
printf(" 3. Logarithmic Functions\n");
printf(" 4. Power and Root Functions\n");
printf(" 5. Memory Operations\n");
printf(" 6. Show History\n");
printf(" 7. Clear History\n");
printf(" 0. Exit\n");
printf("======================================\n");
}
void basicOperations() {
double a, b, result;
char op;
printf("\n--- Basic Operations ---\n");
printf("Enter expression (e.g., 5 + 3): ");
scanf("%lf %c %lf", &a, &op, &b);
switch(op) {
case '+':
result = a + b;
printf("%.2f + %.2f = %.2f\n", a, b, result);
addToHistory("Addition", result);
break;
case '-':
result = a - b;
printf("%.2f - %.2f = %.2f\n", a, b, result);
addToHistory("Subtraction", result);
break;
case '*':
result = a * b;
printf("%.2f * %.2f = %.2f\n", a, b, result);
addToHistory("Multiplication", result);
break;
case '/':
if (b != 0) {
result = a / b;
printf("%.2f / %.2f = %.2f\n", a, b, result);
addToHistory("Division", result);
} else {
printf("Error: Division by zero!\n");
}
break;
default:
printf("Invalid operator!\n");
}
}
void trigonometricFunctions() {
double angle, result;
int choice;
printf("\n--- Trigonometric Functions ---\n");
printf("1. Sine (sin)\n");
printf("2. Cosine (cos)\n");
printf("3. Tangent (tan)\n");
printf("4. Arcsine (asin)\n");
printf("5. Arccosine (acos)\n");
printf("6. Arctangent (atan)\n");
printf("Choose function: ");
scanf("%d", &choice);
printf("Enter angle in degrees: ");
scanf("%lf", &angle);
// Convert to radians for calculation
double rad = angle * M_PI / 180.0;
switch(choice) {
case 1:
result = sin(rad);
printf("sin(%.2f°) = %.4f\n", angle, result);
addToHistory("sin", result);
break;
case 2:
result = cos(rad);
printf("cos(%.2f°) = %.4f\n", angle, result);
addToHistory("cos", result);
break;
case 3:
result = tan(rad);
printf("tan(%.2f°) = %.4f\n", angle, result);
addToHistory("tan", result);
break;
case 4:
result = asin(rad) * 180.0 / M_PI;
printf("asin(%.2f) = %.2f°\n", angle, result);
addToHistory("asin", result);
break;
case 5:
result = acos(rad) * 180.0 / M_PI;
printf("acos(%.2f) = %.2f°\n", angle, result);
addToHistory("acos", result);
break;
case 6:
result = atan(rad) * 180.0 / M_PI;
printf("atan(%.2f) = %.2f°\n", angle, result);
addToHistory("atan", result);
break;
default:
printf("Invalid choice!\n");
}
}
void logarithmicFunctions() {
double num, result;
int choice;
printf("\n--- Logarithmic Functions ---\n");
printf("1. Natural Log (ln)\n");
printf("2. Log Base 10\n");
printf("3. Log Base 2\n");
printf("4. Exponential (e^x)\n");
printf("Choose function: ");
scanf("%d", &choice);
printf("Enter number: ");
scanf("%lf", &num);
switch(choice) {
case 1:
if (num > 0) {
result = log(num);
printf("ln(%.2f) = %.4f\n", num, result);
addToHistory("ln", result);
} else {
printf("Error: Number must be positive!\n");
}
break;
case 2:
if (num > 0) {
result = log10(num);
printf("log10(%.2f) = %.4f\n", num, result);
addToHistory("log10", result);
} else {
printf("Error: Number must be positive!\n");
}
break;
case 3:
if (num > 0) {
result = log2(num);
printf("log2(%.2f) = %.4f\n", num, result);
addToHistory("log2", result);
} else {
printf("Error: Number must be positive!\n");
}
break;
case 4:
result = exp(num);
printf("e^%.2f = %.4f\n", num, result);
addToHistory("exp", result);
break;
default:
printf("Invalid choice!\n");
}
}
void powerFunctions() {
double base, exponent, result;
int choice;
printf("\n--- Power and Root Functions ---\n");
printf("1. Power (x^y)\n");
printf("2. Square Root\n");
printf("3. Cube Root\n");
printf("4. nth Root\n");
printf("5. Square\n");
printf("6. Cube\n");
printf("Choose function: ");
scanf("%d", &choice);
switch(choice) {
case 1:
printf("Enter base and exponent: ");
scanf("%lf %lf", &base, &exponent);
result = pow(base, exponent);
printf("%.2f^%.2f = %.4f\n", base, exponent, result);
addToHistory("power", result);
break;
case 2:
printf("Enter number: ");
scanf("%lf", &base);
if (base >= 0) {
result = sqrt(base);
printf("√%.2f = %.4f\n", base, result);
addToHistory("sqrt", result);
} else {
printf("Error: Cannot calculate square root of negative number!\n");
}
break;
case 3:
printf("Enter number: ");
scanf("%lf", &base);
result = cbrt(base);
printf("∛%.2f = %.4f\n", base, result);
addToHistory("cbrt", result);
break;
case 4:
printf("Enter number and root (n): ");
scanf("%lf %lf", &base, &exponent);
if (base >= 0 || (int)exponent % 2 == 1) {
result = pow(base, 1.0 / exponent);
printf("%.2f^(1/%.0f) = %.4f\n", base, exponent, result);
addToHistory("nth root", result);
} else {
printf("Error: Cannot calculate even root of negative number!\n");
}
break;
case 5:
printf("Enter number: ");
scanf("%lf", &base);
result = base * base;
printf("%.2f² = %.4f\n", base, result);
addToHistory("square", result);
break;
case 6:
printf("Enter number: ");
scanf("%lf", &base);
result = base * base * base;
printf("%.2f³ = %.4f\n", base, result);
addToHistory("cube", result);
break;
default:
printf("Invalid choice!\n");
}
}
void memoryOperations() {
int choice;
double value;
printf("\n--- Memory Operations ---\n");
printf("1. Store in memory\n");
printf("2. Recall from memory\n");
printf("3. Clear memory\n");
printf("4. Add to memory\n");
printf("5. Subtract from memory\n");
printf("Choose operation: ");
scanf("%d", &choice);
switch(choice) {
case 1:
printf("Enter value to store: ");
scanf("%lf", &value);
memory.value = value;
memory.isSet = 1;
printf("Stored %.2f in memory\n", value);
addToHistory("Memory store", value);
break;
case 2:
if (memory.isSet) {
printf("Memory value: %.2f\n", memory.value);
} else {
printf("Memory is empty!\n");
}
break;
case 3:
memory.isSet = 0;
printf("Memory cleared\n");
addToHistory("Memory clear", 0);
break;
case 4:
if (memory.isSet) {
printf("Enter value to add: ");
scanf("%lf", &value);
memory.value += value;
printf("New memory value: %.2f\n", memory.value);
addToHistory("Memory add", memory.value);
} else {
printf("Memory is empty!\n");
}
break;
case 5:
if (memory.isSet) {
printf("Enter value to subtract: ");
scanf("%lf", &value);
memory.value -= value;
printf("New memory value: %.2f\n", memory.value);
addToHistory("Memory subtract", memory.value);
} else {
printf("Memory is empty!\n");
}
break;
default:
printf("Invalid choice!\n");
}
}
void showHistory() {
printf("\n--- Calculation History ---\n");
if (historyCount == 0) {
printf("No calculations yet.\n");
} else {
for (int i = 0; i < historyCount; i++) {
printf("%d. %s = %.2f\n", i + 1, 
history[i].operation, history[i].result);
}
}
}
void addToHistory(const char *op, double result) {
if (historyCount < MAX_HISTORY) {
strcpy(history[historyCount].operation, op);
history[historyCount].result = result;
historyCount++;
}
}
void clearHistory() {
historyCount = 0;
printf("\nHistory cleared.\n");
}

5. Calculator with File I/O

file_calculator.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAX_LINE 100
#define LOG_FILE "calculator.log"
// Function prototypes
void logCalculation(const char *operation, double result);
void showLastCalculations(int n);
void clearLogFile();
double calculate(double a, double b, char op);
void batchProcessing(const char *filename);
int main() {
int choice;
double a, b, result;
char op;
printf("====================================\n");
printf("    CALCULATOR WITH FILE I/O       \n");
printf("====================================\n");
do {
printf("\n1. Perform Calculation\n");
printf("2. Show Last 10 Calculations\n");
printf("3. Show All Calculations\n");
printf("4. Clear Log File\n");
printf("5. Batch Process from File\n");
printf("0. Exit\n");
printf("Choice: ");
scanf("%d", &choice);
switch(choice) {
case 1:
printf("\nEnter expression (e.g., 5 + 3): ");
scanf("%lf %c %lf", &a, &op, &b);
result = calculate(a, b, op);
if (!(op == '/' && b == 0)) {
printf("Result: %.2f\n", result);
char operation[50];
sprintf(operation, "%.2f %c %.2f", a, op, b);
logCalculation(operation, result);
}
break;
case 2:
showLastCalculations(10);
break;
case 3:
showLastCalculations(-1); // -1 means show all
break;
case 4:
clearLogFile();
break;
case 5:
{
char filename[100];
printf("Enter filename: ");
scanf("%s", filename);
batchProcessing(filename);
}
break;
case 0:
printf("\nGoodbye!\n");
break;
default:
printf("Invalid choice!\n");
}
} while(choice != 0);
return 0;
}
double calculate(double a, double b, char op) {
switch(op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/':
if (b != 0) return a / b;
printf("Error: Division by zero!\n");
return 0;
default:
printf("Invalid operator!\n");
return 0;
}
}
void logCalculation(const char *operation, double result) {
FILE *file = fopen(LOG_FILE, "a");
if (file == NULL) {
printf("Error: Cannot open log file!\n");
return;
}
time_t now = time(NULL);
char *timeStr = ctime(&now);
timeStr[strlen(timeStr) - 1] = '\0'; // Remove newline
fprintf(file, "[%s] %s = %.2f\n", timeStr, operation, result);
fclose(file);
printf("Calculation logged.\n");
}
void showLastCalculations(int n) {
FILE *file = fopen(LOG_FILE, "r");
if (file == NULL) {
printf("No log file found or file is empty.\n");
return;
}
// Count lines
char line[MAX_LINE];
int lineCount = 0;
while (fgets(line, MAX_LINE, file) != NULL) {
lineCount++;
}
if (lineCount == 0) {
printf("No calculations logged yet.\n");
fclose(file);
return;
}
// Determine how many lines to show
int startLine = (n < 0 || n >= lineCount) ? 0 : lineCount - n;
// Rewind and read again
rewind(file);
int currentLine = 0;
printf("\n--- Calculation Log ---\n");
while (fgets(line, MAX_LINE, file) != NULL) {
if (currentLine >= startLine) {
printf("%s", line);
}
currentLine++;
}
fclose(file);
}
void clearLogFile() {
FILE *file = fopen(LOG_FILE, "w");
if (file == NULL) {
printf("Error: Cannot clear log file!\n");
return;
}
fclose(file);
printf("Log file cleared.\n");
}
void batchProcessing(const char *filename) {
FILE *input = fopen(filename, "r");
if (input == NULL) {
printf("Error: Cannot open file %s\n", filename);
return;
}
char line[MAX_LINE];
int lineNum = 0;
int successCount = 0;
int errorCount = 0;
printf("\n--- Batch Processing Results ---\n");
while (fgets(line, MAX_LINE, input) != NULL) {
lineNum++;
// Remove newline
line[strcspn(line, "\n")] = 0;
// Skip empty lines
if (strlen(line) == 0) continue;
double a, b, result;
char op;
if (sscanf(line, "%lf %c %lf", &a, &op, &b) == 3) {
if (op == '/' && b == 0) {
printf("Line %d: Error - Division by zero\n", lineNum);
errorCount++;
} else {
result = calculate(a, b, op);
printf("Line %d: %.2f %c %.2f = %.2f\n", 
lineNum, a, op, b, result);
logCalculation(line, result);
successCount++;
}
} else {
printf("Line %d: Invalid format - %s\n", lineNum, line);
errorCount++;
}
}
fclose(input);
printf("\n--- Summary ---\n");
printf("Total lines: %d\n", lineNum);
printf("Successful: %d\n", successCount);
printf("Errors: %d\n", errorCount);
}

6. Calculator Header File

calculator.h

#ifndef CALCULATOR_H
#define CALCULATOR_H
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
// Constants
#define PI 3.14159265358979323846
#define E 2.71828182845904523536
#define MAX_HISTORY 100
// Structures
typedef struct {
double value;
int isSet;
} Memory;
typedef struct {
char operation[50];
double result;
time_t timestamp;
} HistoryEntry;
// Basic operations
double add(double a, double b);
double subtract(double a, double b);
double multiply(double a, double b);
double divide(double a, double b);
int modulus(int a, int b);
// Advanced operations
double power(double base, double exponent);
double squareRoot(double x);
double cubeRoot(double x);
double nthRoot(double x, double n);
// Trigonometric operations
double sine(double angle);      // angle in degrees
double cosine(double angle);    // angle in degrees
double tangent(double angle);   // angle in degrees
double arcsine(double x);
double arccosine(double x);
double arctangent(double x);
// Logarithmic operations
double naturalLog(double x);
double logBase10(double x);
double logBase2(double x);
double exponential(double x);
// Utility functions
double toRadians(double degrees);
double toDegrees(double radians);
int isZero(double x);
void printResult(double result, const char *operation);
// History functions
void addToHistory(const char *operation, double result);
void showHistory(int n);
void clearHistory(void);
#endif

7. Makefile

# Makefile for Calculator Project
CC = gcc
CFLAGS = -Wall -Wextra -std=c99 -O2
LDFLAGS = -lm
# Source files
SOURCES = basic_calculator.c \
menu_calculator.c \
expression_calculator.c \
scientific_calculator.c \
file_calculator.c
# Executables
EXECUTABLES = $(SOURCES:.c=)
all: $(EXECUTABLES)
%: %.c
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
# Individual targets
basic: basic_calculator.c
$(CC) $(CFLAGS) -o basic_calculator basic_calculator.c $(LDFLAGS)
menu: menu_calculator.c
$(CC) $(CFLAGS) -o menu_calculator menu_calculator.c $(LDFLAGS)
expression: expression_calculator.c
$(CC) $(CFLAGS) -o expression_calculator expression_calculator.c $(LDFLAGS)
scientific: scientific_calculator.c
$(CC) $(CFLAGS) -o scientific_calculator scientific_calculator.c $(LDFLAGS)
file: file_calculator.c
$(CC) $(CFLAGS) -o file_calculator file_calculator.c $(LDFLAGS)
# Clean up
clean:
rm -f $(EXECUTABLES) *.o *.log
# Install
install: all
cp $(EXECUTABLES) /usr/local/bin/
# Run tests
test: all
@echo "Testing Basic Calculator..."
@./basic_calculator < test_input.txt
.PHONY: all clean install test

8. Sample Input File for Batch Processing

calculations.txt

5 + 3
10 - 4
6 * 7
15 / 3
8 / 0
2 ^ 3
sqrt 16
sin 30
log 100

9. Compilation and Usage Instructions

Compilation

# Compile all calculators
make all
# Compile specific calculator
make basic
make menu
make expression
make scientific
make file
# Clean compiled files
make clean

Running the Calculators

# Basic calculator
./basic_calculator
# Menu-driven calculator
./menu_calculator
# Expression calculator
./expression_calculator
# Scientific calculator
./scientific_calculator
# File-based calculator
./file_calculator

10. Testing and Validation

test_calculator.c

#include <stdio.h>
#include <assert.h>
#include <math.h>
#include "calculator.h"
void testBasicOperations() {
printf("Testing basic operations...\n");
assert(add(5, 3) == 8);
assert(subtract(10, 4) == 6);
assert(multiply(6, 7) == 42);
assert(divide(15, 3) == 5);
assert(modulus(17, 5) == 2);
printf("Basic operations passed!\n");
}
void testAdvancedOperations() {
printf("Testing advanced operations...\n");
assert(power(2, 3) == 8);
assert(fabs(squareRoot(16) - 4) < 0.0001);
assert(fabs(cubeRoot(27) - 3) < 0.0001);
assert(fabs(nthRoot(16, 4) - 2) < 0.0001);
printf("Advanced operations passed!\n");
}
void testTrigonometric() {
printf("Testing trigonometric functions...\n");
assert(fabs(sine(30) - 0.5) < 0.0001);
assert(fabs(cosine(60) - 0.5) < 0.0001);
assert(fabs(tangent(45) - 1.0) < 0.0001);
printf("Trigonometric functions passed!\n");
}
void testLogarithmic() {
printf("Testing logarithmic functions...\n");
assert(fabs(naturalLog(E) - 1.0) < 0.0001);
assert(fabs(logBase10(100) - 2.0) < 0.0001);
assert(fabs(exponential(1) - E) < 0.0001);
printf("Logarithmic functions passed!\n");
}
int main() {
printf("=== Calculator Test Suite ===\n\n");
testBasicOperations();
testAdvancedOperations();
testTrigonometric();
testLogarithmic();
printf("\nAll tests passed!\n");
return 0;
}

Project Features Summary

Basic Calculator

  • Addition, subtraction, multiplication, division
  • Modulus operation
  • Input validation
  • Continuous operation option

Menu-Driven Calculator

  • User-friendly menu interface
  • Multiple operation categories
  • Clear screen functionality
  • Press-to-continue feature

Expression Calculator

  • Parses complex expressions
  • Handles parentheses
  • Operator precedence
  • Exponentiation support

Scientific Calculator

  • Trigonometric functions
  • Logarithmic functions
  • Power and root functions
  • Memory operations
  • Calculation history

File-Based Calculator

  • Logs calculations to file
  • Batch processing from file
  • View calculation history
  • Error handling for file operations

Learning Outcomes

This project demonstrates:

  1. Basic C Concepts
  • Variables and data types
  • Input/output operations
  • Control structures (if-else, switch)
  • Loops (while, do-while)
  1. Functions
  • Function declaration and definition
  • Parameter passing
  • Return values
  • Function pointers (in advanced version)
  1. Arrays and Structures
  • Arrays for history storage
  • Structures for memory and history
  • Array of structures
  1. File I/O
  • Reading from files
  • Writing to files
  • File error handling
  1. Math Library
  • Using math.h functions
  • Floating-point operations
  • Trigonometry and logarithms
  1. Error Handling
  • Division by zero
  • Invalid input
  • File operation errors
  1. Modular Programming
  • Header files
  • Multiple source files
  • Makefile for building

Conclusion

This calculator project provides a comprehensive learning experience for C programming, covering everything from basic syntax to advanced concepts like file I/O and modular programming. Each calculator version builds upon the previous one, adding new features and complexity.

Extending the Project

You can extend this project further by:

  1. Adding GUI interface using GTK or ncurses
  2. Implementing more advanced mathematical functions
  3. Adding unit conversion features
  4. Creating a plugin system for custom functions
  5. Adding network capabilities for remote calculations
  6. Implementing expression graphing
  7. Adding support for complex numbers
  8. Creating a web interface using CGI

This project serves as an excellent portfolio piece demonstrating proficiency in C programming and software development best practices.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper