C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
amort.c
Go to the documentation of this file.
1/** @file amort.c
2 @brief Installment Loan Amortization
3 @author Bill Waller
4 Copyright (c) 2026
5 MIT License
6 billxwaller@gmail.com
7 @date 2026-05-05
8 */
9#define _GNU_SOURCE
10#include <locale.h>
11#include <stdbool.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <time.h>
16#include <unistd.h>
17#ifdef __USE_GNU_GETTEXT
18#include <libintl.h>
19#define _(String) gettext(String)
20#define gettext_noop(String) String
21#define N_(String) gettext_noop(String)
22#else
23#define _(String) (String)
24#define N_(String) String
25#define textdomain(Domain)
26#define bindtextdomain(Package, Directory)
27#endif
28char month[12][4] = {_("Jan"), _("Feb"), _("Mar"), _("Apr"), _("May"), _("Jun"),
29 _("Jul"), _("Aug"), _("Sep"), _("Oct"), _("Nov"), _("Dec")};
30typedef struct {
31 double pv;
32 double pmt;
33 double i;
34 double n;
35 double interest;
36 double principal;
37 double year_total_interest;
38} Amort;
39void print_totals(Amort *);
40
41int main(int argc, char **argv) {
42 setlocale(LC_NUMERIC, "");
43 if (argc > 1 &&
44 ((strcmp(argv[1], _("--help")) == 0 || strcmp(argv[1], "-h") == 0) ||
45 argc < 5)) {
46 printf(_("Usage: amort [present_value][number_of_payments] [interest_rate][payment_amount][yyyy-mm-dd]\n\n"));
47 exit(EXIT_SUCCESS);
48 }
49 struct tm tm;
50 Amort *amort = malloc(sizeof(Amort));
51 sscanf(argv[1], _("%lf"), &amort->pv);
52 sscanf(argv[2], _("%lf"), &amort->n);
53 sscanf(argv[3], _("%lf"), &amort->i);
54 sscanf(argv[4], _("%lf"), &amort->pmt);
55 if (amort->pv == 0 || amort->n == 0 || amort->i == 0 || amort->pmt == 0 ||
56 argv[5][0] == '\0') {
57 fprintf(stderr, _("Error: All arguments must be non-zero.\n"));
58 exit(EXIT_FAILURE);
59 }
60 amort->interest = amort->pv * amort->i / 1200;
61 if (amort->interest > amort->pmt) {
62 fprintf(stderr, _("Error: Payment amount less than interest\n"));
63 exit(EXIT_FAILURE);
64 }
65 memset(&tm, 0, sizeof(tm));
66 if (strptime(argv[5], _("%Y-%m-%d"), &tm) == NULL)
67 if (strptime(argv[5], _("%Y%m%d"), &tm) == NULL)
68 printf(_("Error: Invalid date format. Use yyyy-mm-dd or yyyymmdd.\n")),
69 exit(EXIT_FAILURE);
70 amort->year_total_interest = 0;
71
72 printf("First Payment: %04d-%02d-%02d\n\n", tm.tm_year + 1900,
73 tm.tm_mon + 1, tm.tm_mday);
74 printf(_(" Per Mth Year Balance Payment Principal Interest\n"));
75 printf(_("---- --- ---- ------------ ---------- ---------- ----------\n"));
76 int m = 0;
77 for (int x = 0; x < amort->n; x++) {
78 if (amort->pv <= 0)
79 break;
80 m = (x + tm.tm_mon) % 12;
81 int y = ((x + tm.tm_mon) / 12) + tm.tm_year + 1900;
82 amort->interest = amort->pv * amort->i / 1200;
83 amort->year_total_interest += amort->interest;
84 if (amort->pv + amort->interest < amort->pmt) {
85 amort->pmt = amort->pv + amort->interest;
86 amort->principal = amort->pv;
87 } else
88 amort->principal = amort->pmt - amort->interest;
89 amort->pv -= amort->principal;
90 printf("%4d %4s %4d %'12.2f %'10.2f %'10.2f %'10.2f\n", x + 1, month[m],
91 y, amort->pv, amort->pmt, amort->principal, amort->interest);
92 if (m == 11)
93 print_totals(amort);
94 }
95 if (m != 11)
96 print_totals(amort);
97 free(amort);
98 return EXIT_SUCCESS;
99}
100void print_totals(Amort *amort) {
101 printf(_(" ----------\n"));
102 printf(_(" %'10.2f\n"),
103 amort->year_total_interest);
104 printf(_(" ==========\n\n"));
105 amort->year_total_interest = 0;
106}
#define _(String)
Definition amort.c:23
int main(int argc, char **argv)
Capture the current terminal settings for later restoration.
Definition amort.c:41
void print_totals(Amort *)
Definition amort.c:100
char month[12][4]
Definition amort.c:28