Initial Commit of sccash

This commit is contained in:
mrkmntal 2026-03-26 22:23:37 -04:00
commit ab12cec361
4 changed files with 575 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
sccash

220
README.md Normal file
View file

@ -0,0 +1,220 @@
# sccash - Simple C Cash
A lightweight, fast CLI currency converter written in C for USD, JPY, and EUR conversions.
## Features
- **Dual Mode Operation**: Command-line arguments for scripting, interactive prompts for manual use
- **Table Formatted Output**: Clean, readable conversion results
- **Lightweight**: No external dependencies, standard C library only
- **Fast**: Compiles to a small, efficient binary
- **Error Handling**: Clear error messages for invalid inputs
## Exchange Rates (as of March 26, 2026)
- **1 USD** = 159.67 JPY
- **1 USD** = 0.866 EUR
- **1 EUR** = 184.20 JPY
*Note: These rates are hardcoded and may not reflect current market rates.*
## Compilation
```bash
gcc -o sccash sccash.c -Wall -O2
```
Or for a static binary:
```bash
gcc -o sccash sccash.c -Wall -O2 -static
```
## Installation
### Option 1: Local Installation
```bash
# Compile first
gcc -o sccash sccash.c -Wall -O2
# Copy to local bin directory
mkdir -p ~/bin
cp sccash ~/bin/
# Add to PATH if not already
export PATH="$HOME/bin:$PATH"
```
### Option 2: System-wide Installation
```bash
# Compile first
gcc -o sccash sccash.c -Wall -O2
# Install to system path (requires sudo)
sudo cp sccash /usr/local/bin/
# Verify installation
sccash --help
```
## Usage
### CLI Mode
Pass three arguments: `amount`, `from_currency`, and `to_currency`.
```bash
./sccash <amount> <from> <to>
```
**Examples:**
```bash
# Convert 100 USD to JPY
./sccash 100 USD JPY
# Convert 50 EUR to USD
./sccash 50 EUR USD
# Convert 1000 JPY to EUR
./sccash 1000 JPY EUR
```
### Interactive Mode
Run without arguments for interactive prompts:
```bash
./sccash
```
Example session:
```
=== sccash - Simple C Cash ===
Available currencies: USD, JPY, EUR
Enter amount: 100
Convert from (USD/JPY/EUR): USD
Convert to (USD/JPY/EUR): JPY
+--------+---------------+--------+----------------+
| FROM | AMOUNT | TO | CONVERTED |
+--------+---------------+--------+----------------+
| USD | 100.00 | JPY | 15967.00 |
+--------+---------------+--------+----------------+
Show all conversions? (y/n): y
+--------+---------------+--------+----------------+
| FROM | AMOUNT | TO | CONVERTED |
+--------+---------------+--------+----------------+
| USD | 100.00 | JPY | 15967.00 |
| USD | 100.00 | EUR | 86.60 |
+--------+---------------+--------+----------------+
Exchange Rates (as of March 26, 2026):
1 USD = 159.67 JPY
1 USD = 0.866 EUR
1 EUR = 184.20 JPY
```
## Sample Output
```bash
$ ./sccash 250 USD EUR
+--------+---------------+--------+----------------+
| FROM | AMOUNT | TO | CONVERTED |
+--------+---------------+--------+----------------+
| USD | 250.00 | EUR | 216.50 |
+--------+---------------+--------+----------------+
```
## Error Handling
```bash
$ ./sccash 100 GBP USD
Error: Invalid source currency 'GBP'
Available: USD, JPY, EUR
$ ./sccash
=== sccash - Simple C Cash ===
Available currencies: USD, JPY, EUR
Enter amount: invalid
Error: Invalid amount
```
## Architecture
sccash uses USD as the base currency for all conversions:
1. Convert source amount to USD
2. Convert USD amount to target currency
This approach minimizes rounding errors and keeps the code simple and maintainable.
## Currencies Supported
- **USD** - United States Dollar
- **JPY** - Japanese Yen
- **EUR** - Euro
Currency codes are case-insensitive (usd, USD, Usd all work).
## Technical Details
- **Lines of Code**: ~200
- **Dependencies**: Standard C library only (stdio.h, stdlib.h, string.h, ctype.h)
- **Memory Usage**: Minimal - uses only the stack
- **Output Format**: Fixed-width table with 2 decimal precision
## Building for Different Platforms
### Linux
```bash
gcc -o sccash sccash.c -Wall -O2
```
### macOS
```bash
clang -o sccash sccash.c -Wall -O2
```
### Windows (MinGW)
```bash
gcc -o sccash.exe sccash.c -Wall -O2
```
## License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
## Contributing
This is a simple, focused tool. Contributions should maintain the design goals:
- Keep it lightweight
- No external dependencies
- Simple, readable code
- Clear error messages
## Author
Created with simplicity and performance in mind.
---
**Note**: Currency values fluctuate constantly. The exchange rates in this tool are fixed as of March 26, 2026. For real-time rates, consider using a service with API integration.

157
sccash.1 Normal file
View file

@ -0,0 +1,157 @@
.TH SCCASH 1 "March 2026" "sccash 1.0" "User Commands"
.SH NAME
sccash \- Simple C Cash currency converter
.SH SYNOPSIS
.B sccash
.RI [ amount from_currency to_currency ]
.SH DESCRIPTION
.B sccash
is a lightweight, fast CLI currency converter written in C that supports
conversions between USD (US Dollar), JPY (Japanese Yen), and EUR (Euro).
.PP
The program operates in two modes:
.IP \(bu 2
.B Command-line mode:
Pass arguments directly for quick conversions and scripting
.IP \(bu 2
.B Interactive mode:
Run without arguments for guided prompts
.PP
All conversions are performed using USD as the base currency to minimize
rounding errors. Results are displayed in a clean table format with
2 decimal precision.
.SH ARGUMENTS
.TP
.B amount
The numeric value to convert. Must be a positive number.
.TP
.B from_currency
Source currency code. Accepted values: USD, JPY, EUR (case-insensitive).
.TP
.B to_currency
Target currency code. Accepted values: USD, JPY, EUR (case-insensitive).
.SH OPTIONS
.TP
.B \-\-help
Display usage information and exit.
.SH EXAMPLES
.TP
Convert 100 USD to JPY:
.B sccash 100 USD JPY
.TP
Convert 50 EUR to USD:
.B sccash 50 EUR USD
.TP
Convert 1000 JPY to EUR:
.B sccash 1000 JPY EUR
.TP
Start interactive mode:
.B sccash
.PP
Example output:
.PP
.nf
+--------+---------------+--------+----------------+
| FROM | AMOUNT | TO | CONVERTED |
+--------+---------------+--------+----------------+
| USD | 100.00 | JPY | 15967.00 |
+--------+---------------+--------+----------------+
.fi
.SH INTERACTIVE MODE
When run without arguments, sccash enters interactive mode and prompts for:
.IP 1. 4
Amount to convert
.IP 2. 4
Source currency (USD/JPY/EUR)
.IP 3. 4
Target currency (USD/JPY/EUR)
.IP 4. 4
Option to display all possible conversions from the source currency
.PP
Interactive mode is useful for one-off conversions and exploring different
conversion options.
.SH EXCHANGE RATES
The following exchange rates are hardcoded as of March 26, 2026:
.IP \(bu 2
1 USD = 159.67 JPY
.IP \(bu 2
1 USD = 0.866 EUR
.IP \(bu 2
1 EUR = 184.20 JPY
.PP
.B Important:
These rates are fixed and do not update automatically. They may not reflect
current market rates. This tool is designed for quick estimates and personal
use, not for financial trading or time-sensitive conversions.
.SH EXIT STATUS
.TP
.B 0
Successful conversion or help display
.TP
.B 1
Error occurred (invalid amount, invalid currency, or missing arguments)
.SH FILES
No configuration files are used. Exchange rates are compiled directly into
the binary.
.SH ENVIRONMENT
No environment variables are used.
.SH COMPILATION
To compile sccash from source:
.PP
.B gcc -o sccash sccash.c -Wall -O2
.PP
For a static binary:
.PP
.B gcc -o sccash sccash.c -Wall -O2 -static
.SH INSTALLATION
Install the binary to your local bin:
.PP
.B mkdir -p ~/bin && cp sccash ~/bin/
.PP
Or install system-wide:
.PP
.B sudo cp sccash /usr/local/bin/
.SH NOTES
Currency codes are case-insensitive. The following are all equivalent:
.BR USD ,
.BR usd ,
.BR Usd ,
.BR usD .
.PP
The program validates all inputs and provides clear error messages for:
.IP \(bu 2
Non-numeric or negative amounts
.IP \(bu 2
Invalid currency codes
.IP \(bu 2
Missing command-line arguments
.SH BUGS
The exchange rates are static and compiled into the binary. They do not
update automatically with market changes. For real-time currency conversion,
consider using a service with API integration.
.PP
Report bugs at: https://github.com/yourusername/sccash/issues
.SH SEE ALSO
.BR bc (1),
.BR units (1),
.BR convert (1)
.SH AUTHOR
Written by markmental (Mark Robillard Jr).
.SH COPYRIGHT
Copyright (C) 2026 markmental (Mark Robillard Jr).
.PP
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.PP
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.PP
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
.SH VERSION
sccash 1.0 (March 2026)

197
sccash.c Normal file
View file

@ -0,0 +1,197 @@
/*
* sccash - Simple C Cash
* A lightweight CLI currency converter for USD, JPY, and EUR
* Compile: gcc -o sccash sccash.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define RATE_USD_JPY 159.67
#define RATE_USD_EUR 0.866
#define RATE_EUR_JPY 184.20
typedef enum {
CURRENCY_USD,
CURRENCY_JPY,
CURRENCY_EUR,
CURRENCY_INVALID
} Currency;
const char* currency_names[] = {"USD", "JPY", "EUR"};
Currency parse_currency(const char* input) {
char upper[4] = {0};
for (int i = 0; i < 3 && input[i]; i++) {
upper[i] = toupper(input[i]);
}
if (strcmp(upper, "USD") == 0) return CURRENCY_USD;
if (strcmp(upper, "JPY") == 0) return CURRENCY_JPY;
if (strcmp(upper, "EUR") == 0) return CURRENCY_EUR;
return CURRENCY_INVALID;
}
double convert_to_usd(double amount, Currency from) {
switch (from) {
case CURRENCY_USD: return amount;
case CURRENCY_JPY: return amount / RATE_USD_JPY;
case CURRENCY_EUR: return amount / RATE_USD_EUR;
default: return 0.0;
}
}
double convert_from_usd(double usd_amount, Currency to) {
switch (to) {
case CURRENCY_USD: return usd_amount;
case CURRENCY_JPY: return usd_amount * RATE_USD_JPY;
case CURRENCY_EUR: return usd_amount * RATE_USD_EUR;
default: return 0.0;
}
}
double convert_currency(double amount, Currency from, Currency to) {
if (from == to) return amount;
double usd_amount = convert_to_usd(amount, from);
return convert_from_usd(usd_amount, to);
}
void print_table_header(void) {
printf("+--------+---------------+--------+----------------+\n");
printf("| FROM | AMOUNT | TO | CONVERTED |\n");
printf("+--------+---------------+--------+----------------+\n");
}
void print_table_row(const char* from, double amount, const char* to, double converted) {
printf("| %-6s | %13.2f | %-6s | %14.2f |\n", from, amount, to, converted);
}
void print_table_footer(void) {
printf("+--------+---------------+--------+----------------+\n");
}
void print_all_conversions(double amount, Currency from) {
printf("\n");
print_table_header();
for (int i = 0; i < 3; i++) {
if (i != from) {
Currency to = (Currency)i;
double result = convert_currency(amount, from, to);
print_table_row(currency_names[from], amount, currency_names[to], result);
}
}
print_table_footer();
printf("\nExchange Rates (as of March 26, 2026):\n");
printf(" 1 USD = %.2f JPY\n", RATE_USD_JPY);
printf(" 1 USD = %.3f EUR\n", RATE_USD_EUR);
printf(" 1 EUR = %.2f JPY\n", RATE_EUR_JPY);
printf("\n");
}
void interactive_mode(void) {
char from_input[10], to_input[10];
double amount;
Currency from, to;
printf("\n=== sccash - Simple C Cash ===\n\n");
printf("Available currencies: USD, JPY, EUR\n\n");
printf("Enter amount: ");
if (scanf("%lf", &amount) != 1 || amount < 0) {
fprintf(stderr, "Error: Invalid amount\n");
return;
}
printf("Convert from (USD/JPY/EUR): ");
scanf("%9s", from_input);
from = parse_currency(from_input);
if (from == CURRENCY_INVALID) {
fprintf(stderr, "Error: Invalid currency '%s'\n", from_input);
return;
}
printf("Convert to (USD/JPY/EUR): ");
scanf("%9s", to_input);
to = parse_currency(to_input);
if (to == CURRENCY_INVALID) {
fprintf(stderr, "Error: Invalid currency '%s'\n", to_input);
return;
}
if (from == to) {
printf("\nResult: %.2f %s (same currency)\n", amount, currency_names[from]);
return;
}
double result = convert_currency(amount, from, to);
printf("\n");
print_table_header();
print_table_row(currency_names[from], amount, currency_names[to], result);
print_table_footer();
printf("\n");
printf("Show all conversions? (y/n): ");
char show_all[10];
scanf("%9s", show_all);
if (show_all[0] == 'y' || show_all[0] == 'Y') {
print_all_conversions(amount, from);
}
}
void cli_mode(int argc, char* argv[]) {
if (argc < 4) {
fprintf(stderr, "Usage: %s <amount> <from> <to>\n", argv[0]);
fprintf(stderr, " amount: numeric value to convert\n");
fprintf(stderr, " from: source currency (USD, JPY, EUR)\n");
fprintf(stderr, " to: target currency (USD, JPY, EUR)\n\n");
fprintf(stderr, "Example: %s 100 USD JPY\n", argv[0]);
fprintf(stderr, "Or run without arguments for interactive mode\n");
exit(1);
}
double amount = atof(argv[1]);
if (amount <= 0) {
fprintf(stderr, "Error: Invalid amount '%s'\n", argv[1]);
exit(1);
}
Currency from = parse_currency(argv[2]);
Currency to = parse_currency(argv[3]);
if (from == CURRENCY_INVALID) {
fprintf(stderr, "Error: Invalid source currency '%s'\n", argv[2]);
fprintf(stderr, "Available: USD, JPY, EUR\n");
exit(1);
}
if (to == CURRENCY_INVALID) {
fprintf(stderr, "Error: Invalid target currency '%s'\n", argv[3]);
fprintf(stderr, "Available: USD, JPY, EUR\n");
exit(1);
}
double result = convert_currency(amount, from, to);
printf("\n");
print_table_header();
print_table_row(currency_names[from], amount, currency_names[to], result);
print_table_footer();
printf("\n");
}
int main(int argc, char* argv[]) {
if (argc == 1) {
interactive_mode();
} else {
cli_mode(argc, argv);
}
return 0;
}