C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
iloan.c File Reference

Installment Loan Calculator. More...

#include <math.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
Include dependency graph for iloan.c:

Go to the source code of this file.

Macros

#define FALSE   0
#define TRUE   1

Functions

void numbers (char *d, char *s)
double calculate_i (double, double, double)
double calculate_n (double, double, double)
double calculate_pmt (double, double, double)
double calculate_pv (double, double, double)
int is_numeric (char *)
void accept_str (char *s)
char * format_currency (float)
char * format_interest (float)
double accept_pv ()
double accept_n ()
double accept_i ()
double accept_pmt ()
void error_press_any_key (char *)
void ABEND (int)
int main (int argc, char **argv)
 iloan is a trivial application to demonstrate how a command-line program can be integrated into C-Menu Form with simple file, argument, or pipe i-o.

Variables

char in_str [BUFSIZ+1]
int f_pv = 0
int f_n = 0
int f_i = 0
int f_pmt = 0
bool f_quiet = false

Detailed Description

Installment Loan Calculator.

Author
Bill Waller Copyright (c) 2025 MIT License billx.nosp@m.wall.nosp@m.er@gm.nosp@m.ail..nosp@m.com
Date
2026-02-09

Definition in file iloan.c.

Macro Definition Documentation

◆ FALSE

#define FALSE   0

Definition at line 18 of file iloan.c.

◆ TRUE

#define TRUE   1

Definition at line 19 of file iloan.c.

Function Documentation

◆ ABEND()

void ABEND ( int e)

Definition at line 402 of file iloan.c.

402 {
403 printf("ABEND: Error %d:\n", e);
404 exit(EXIT_FAILURE);
405}

Referenced by main().

Here is the caller graph for this function:

◆ accept_i()

double accept_i ( )

Definition at line 221 of file iloan.c.

221 {
222 double i;
223 while (1) {
224 accept_str("Rate (annual) - - -> ");
225 if (in_str[0] == '\0') {
226 i = 0;
227 break;
228 } else {
229 if (is_numeric(in_str)) {
230 i = atof(in_str);
231 if (i < 0)
232 error_press_any_key("interest Rate can't be less than 0");
233 else
234 break;
235 } else
236 error_press_any_key("Interest Rate must be numeric");
237 }
238 }
239 return (i);
240}
char in_str[BUFSIZ+1]
Definition iloan.c:20
void accept_str(char *s)
Definition iloan.c:349
void error_press_any_key(char *)
Definition iloan.c:260
int is_numeric(char *)
Definition iloan.c:340

References accept_str(), error_press_any_key(), in_str, and is_numeric().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ accept_n()

double accept_n ( )

Definition at line 205 of file iloan.c.

205 {
206 double n;
207 while (1) {
208 accept_str("Number of Payments > ");
209 if (is_numeric(in_str)) {
210 n = atof(in_str);
211 if (n < 0)
212 error_press_any_key("Number of Payments can't be less than 0");
213 else
214 break;
215 } else
216 error_press_any_key("Number of Payments must be numeric");
217 }
218 return (n);
219}

References accept_str(), error_press_any_key(), in_str, and is_numeric().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ accept_pmt()

double accept_pmt ( )

Definition at line 242 of file iloan.c.

242 {
243 double pmt;
244 while (1) {
245 accept_str("Payment Amount - -> ");
246 if (in_str[0] == '\0') {
247 pmt = 0;
248 break;
249 } else {
250 if (is_numeric(in_str)) {
251 pmt = atof(in_str);
252 break;
253 } else
254 error_press_any_key("Payment Amount must be numeric");
255 }
256 }
257 return (pmt);
258}

References accept_str(), error_press_any_key(), in_str, and is_numeric().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ accept_pv()

double accept_pv ( )

Definition at line 184 of file iloan.c.

184 {
185 double pv;
186 while (1) {
187 accept_str("Present Value - - -> ");
188 if (in_str[0] == '\0') {
189 pv = 0;
190 break;
191 } else {
192 if (is_numeric(in_str)) {
193 pv = atof(in_str);
194 if (pv < 0)
195 error_press_any_key("Present Value can't be less than 0");
196 else
197 break;
198 } else
199 error_press_any_key("Present Value must be numeric");
200 }
201 }
202 return (pv);
203}

References accept_str(), error_press_any_key(), in_str, and is_numeric().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ accept_str()

void accept_str ( char * s)

Definition at line 349 of file iloan.c.

349 {
350 fprintf(stderr, "%s", s);
351 read(0, in_str, BUFSIZ);
352}
#define BUFSIZ
Definition view.h:29

References in_str.

Referenced by accept_i(), accept_n(), accept_pmt(), and accept_pv().

Here is the caller graph for this function:

◆ calculate_i()

double calculate_i ( double pv,
double n,
double pmt )

Definition at line 291 of file iloan.c.

291 {
292 double i1 = 0, i;
293 double delta = 0.0000001;
294 double xdelta;
295 double fdelta;
296 double fprimi;
297 double ffact;
298 double fi;
299 double fman;
300 double fmann;
301 if (pv == 0 || n == 0 || pmt == 0)
303 "3 non-zero values required to calculate Interest Rate");
304 ffact = pv / pmt;
305 xdelta = 0;
306 if (ffact < n) {
307 i1 = 0.0125;
308 xdelta = 0.9;
309 }
310 while (xdelta > delta) {
311 fman = 1 / (1 + i1);
312 fmann = pow(fman, n);
313 fi = ffact * i1 + fmann - 1;
314 fprimi = ffact - n * fmann * fman;
315 fdelta = fi / fprimi;
316 i1 = i1 - fdelta;
317 if (fdelta < 0)
318 xdelta = -fdelta;
319 else
320 xdelta = fdelta;
321 }
322 i = i1 * 1200;
323 if (!f_quiet)
324 printf("interest Rate - - - - - -> %s\n", format_interest(i));
325 return (i);
326}
char * format_interest(float)
Definition iloan.c:393
bool f_quiet
Definition iloan.c:41

References error_press_any_key(), f_quiet, and format_interest().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_n()

double calculate_n ( double pv,
double i,
double pmt )

Definition at line 279 of file iloan.c.

279 {
280 double i1, n;
281 if (pv == 0 || i == 0 || pmt == 0)
282 error_press_any_key("3 non-zero values required to calculate "
283 "Number of Payments");
284 i1 = i / 1200;
285 n = -log(1 - pv * i1 / pmt) / log(1 + i1);
286 if (!f_quiet)
287 printf("Number of Payments - - -> %s\n", format_currency(n));
288 return (n);
289}
char * format_currency(float)
Definition iloan.c:354

References error_press_any_key(), f_quiet, and format_currency().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_pmt()

double calculate_pmt ( double pv,
double n,
double i )

Definition at line 328 of file iloan.c.

328 {
329 double i1, pmt;
330 if (pv == 0 || n == 0 || i == 0)
332 "3 non-zero values required to calculate Payment Amount");
333 i1 = i / 1200;
334 pmt = pv * i1 / (1 - pow(1 + i1, -n));
335 if (!f_quiet)
336 printf("Payment Amount - - - - -> %s\n", format_currency(pmt));
337 return (pmt);
338}

References error_press_any_key(), f_quiet, and format_currency().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ calculate_pv()

double calculate_pv ( double n,
double i,
double pmt )

Definition at line 266 of file iloan.c.

266 {
267 double i1, pv;
268
269 if (n == 0 || i == 0 || pmt == 0)
271 "3 non-zero values required to calculate Present Value");
272 i1 = i / 1200;
273 pv = pmt * (1 - pow(1 + i1, -n)) / i1;
274 if (!f_quiet)
275 printf("Present Value - - - - - -> %s\n", format_currency(pv));
276 return (pv);
277}

References error_press_any_key(), f_quiet, and format_currency().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ error_press_any_key()

void error_press_any_key ( char * s)

Definition at line 260 of file iloan.c.

260 {
261 printf("%s", s);
262 getc(stdin);
263 printf("\n\n");
264}

Referenced by accept_i(), accept_n(), accept_pmt(), accept_pv(), calculate_i(), calculate_n(), calculate_pmt(), calculate_pv(), and main().

Here is the caller graph for this function:

◆ format_currency()

char * format_currency ( float a)

Definition at line 354 of file iloan.c.

354 {
355 int digit_count, left_of_point;
356 static char sstr[80];
357 static char fstr[80];
358 char *src_ptr, *dst_ptr, *sptr, *FPtr;
359
360 sprintf(sstr, "%-18.2f", a);
361 sptr = sstr;
362 src_ptr = sstr;
363 FPtr = fstr;
364 dst_ptr = fstr;
365 while (*src_ptr++ != '\0')
366 ;
367 src_ptr -= 2;
368 left_of_point = FALSE;
369 digit_count = 0;
370 while (src_ptr >= sptr) {
371 if (left_of_point) {
372 if (*src_ptr >= '0' && *src_ptr <= '9') {
373 if (digit_count == 3) {
374 *dst_ptr++ = ',';
375 digit_count = 1;
376 } else
377 digit_count++;
378 }
379 } else if (*src_ptr == '.')
380 left_of_point = TRUE;
381 *dst_ptr++ = *src_ptr--;
382 }
383 src_ptr = dst_ptr - 1;
384 dst_ptr = sptr;
385 while (src_ptr >= FPtr)
386 *dst_ptr++ = *src_ptr--;
387 while (*--dst_ptr == ' ')
388 ;
389 *++dst_ptr = '\0';
390 return (sptr);
391}
#define TRUE
Definition iloan.c:19
#define FALSE
Definition iloan.c:18

Referenced by calculate_n(), calculate_pmt(), calculate_pv(), and main().

Here is the caller graph for this function:

◆ format_interest()

char * format_interest ( float a)

Definition at line 393 of file iloan.c.

393 {
394 static char sstr[80];
395 char *s;
396
397 sprintf(sstr, "%-3.5f", a);
398 s = sstr;
399 return (s);
400}

Referenced by calculate_i(), and main().

Here is the caller graph for this function:

◆ is_numeric()

int is_numeric ( char * s)

Definition at line 340 of file iloan.c.

340 {
341 char c;
342
343 while ((c = *s++) != '\0' && c != '\n')
344 if ((c < '0' || c > '9') && c != '.' && c != ',')
345 return (FALSE);
346 return (TRUE);
347}

Referenced by accept_i(), accept_n(), accept_pmt(), and accept_pv().

Here is the caller graph for this function:

◆ main()

int main ( int argc,
char ** argv )

iloan is a trivial application to demonstrate how a command-line program can be integrated into C-Menu Form with simple file, argument, or pipe i-o.

Note
Positional arguments present_value The present value of the loan (the amount borrowed). number_of_payments The total number of payments to be made. interest_rate The annual interest rate (as a percentage). payment_amount The amount of each payment.
The program calculates the missing value based on the three provided values. For example, if the present value, number of payments, and interest rate are provided, it will calculate the payment amount. If the present value, interest rate, and payment amount are provided, it will calculate the number of payments, and so on.
The program can be used in a non-interactive way by passing the four values as arguments, with the value to be calculated set to 0. For example, to calculate the payment amount for a $10,000 loan with a 5% annual interest rate and 60 monthly payments, you could run:
iloan 10000 60 5 0
This is proof-of-concept code, and is not intended for production use. It is not designed to be robust, and does not handle all edge cases or input errors. It is intended solely to demonstrate how a simple command-line program can be integrated into C-Menu Form.
In the future, more sophisticated abstractions, such as async event handlers, serialization, rpc, database, and a standardized plugin interface will be integrated into C-Menu.
Feel free to modify and enhance this code as needed, but please do not use it in production without proper testing and validation. It is provided as-is without any warranty or support. Use at your own risk.

Definition at line 74 of file iloan.c.

74 {
75 double pv = 0, pmt = 0, i = 0, n = 0;
76 char tmp_str[BUFSIZ];
77
78 signal(SIGINT, ABEND);
79 signal(SIGQUIT, ABEND);
80 signal(SIGHUP, ABEND);
81
82 if (argc > 1 &&
83 ((strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) ||
84 argc < 4)) {
85 printf("Usage: iloan [present_value number_of_payments "
86 "interest_rate payment_amount]\n\n");
87 exit(EXIT_SUCCESS);
88 }
89 if (argc > 4) {
90 numbers(tmp_str, argv[1]);
91 sscanf(tmp_str, "%lf", &pv);
92 sscanf(argv[2], "%lf", &n);
93 sscanf(argv[3], "%lf", &i);
94 numbers(tmp_str, argv[4]);
95 sscanf(tmp_str, "%lf", &pmt);
96 if (pv != 0)
97 f_pv = 1;
98 if (n != 0)
99 f_n = 1;
100 if (i != 0)
101 f_i = 1;
102 if (pmt != 0)
103 f_pmt = 1;
104 if (f_pv + f_n + f_i + f_pmt < 3) {
106 "Error: At least three values must be greater than zero.");
107 exit(EXIT_FAILURE);
108 }
109 f_quiet = true;
110 } else {
111 if (argc != 1) {
112 printf("Usage: iloan [present_value number_of_payments "
113 "interest_rate payment_amount]\n\n");
114 exit(EXIT_FAILURE);
115 } else {
116 if (argc == 1) {
117 printf("\nInstallment Loan Calculator\n\n");
118 printf("Three of these values must be greater than 0. The "
119 "field\n");
120 printf("with a value of 0 will be calculated.\n\n");
121 while (f_pv + f_n + f_i + f_pmt < 3) {
122 if (pv == 0) {
123 pv = accept_pv();
124 if (pv != 0)
125 f_pv = 1;
126 }
127 if (n == 0) {
128 n = accept_n();
129 if (n != 0)
130 f_n = 1;
131 }
132 if (i == 0) {
133 i = accept_i();
134 if (i != 0)
135 f_i = 1;
136 }
137 if (pmt == 0) {
138 pmt = accept_pmt();
139 if (pmt != 0)
140 f_pmt = 1;
141 }
142 if (f_pv + f_n + f_i + f_pmt < 3) {
143 error_press_any_key("Error: At least three values must "
144 "be greater than zero.");
145 }
146 }
147 printf("\nYou entered:\n\n");
148 if (pv != 0)
149 printf("Present Value - - - - - -> %s\n",
150 format_currency(pv));
151 if (n != 0)
152 printf("Number of Payments - - -> %s\n",
153 format_currency(n));
154 if (i != 0)
155 printf("Interest Rate - - - - - -> %s\n",
156 format_interest(i));
157 if (pmt != 0)
158 printf("Payment Amount - - - - -> %s\n",
159 format_currency(pmt));
160 printf("\n\nCalculation result:\n\n");
161 }
162 }
163 }
164 if (pv == 0)
165 pv = calculate_pv(n, i, pmt);
166 else if (n == 0)
167 n = calculate_n(pv, i, pmt);
168 else if (i == 0)
169 i = calculate_i(pv, n, pmt);
170 else if (pmt == 0)
171 pmt = calculate_pmt(pv, n, i);
172
173 if (f_quiet) {
174 printf("%s\n", format_currency(pv));
175 printf("%s\n", format_currency(n));
176 printf("%s\n", format_interest(i));
177 printf("%s\n", format_currency(pmt));
178 }
179 signal(SIGINT, SIG_DFL);
180 signal(SIGQUIT, SIG_DFL);
181 signal(SIGHUP, SIG_DFL);
182}
double calculate_pmt(double, double, double)
Definition iloan.c:328
double calculate_n(double, double, double)
Definition iloan.c:279
int f_n
Definition iloan.c:38
double accept_n()
Definition iloan.c:205
void numbers(char *d, char *s)
Definition iloan.c:407
double accept_pmt()
Definition iloan.c:242
double calculate_i(double, double, double)
Definition iloan.c:291
double accept_pv()
Definition iloan.c:184
int f_i
Definition iloan.c:39
double accept_i()
Definition iloan.c:221
int f_pv
Definition iloan.c:37
double calculate_pv(double, double, double)
Definition iloan.c:266
int f_pmt
Definition iloan.c:40
void ABEND(int)
Definition iloan.c:402

References ABEND(), accept_i(), accept_n(), accept_pmt(), accept_pv(), calculate_i(), calculate_n(), calculate_pmt(), calculate_pv(), error_press_any_key(), f_i, f_n, f_pmt, f_pv, f_quiet, format_currency(), format_interest(), and numbers().

Here is the call graph for this function:

◆ numbers()

void numbers ( char * d,
char * s )

Definition at line 407 of file iloan.c.

407 {
408 while (*s != '\0') {
409 if (*s == '-' || *s == '.' || (*s >= '0' && *s <= '9'))
410 *d++ = *s++;
411 else
412 s++;
413 }
414 *d = '\0';
415}

Referenced by main().

Here is the caller graph for this function:

Variable Documentation

◆ f_i

int f_i = 0

Definition at line 39 of file iloan.c.

Referenced by main().

◆ f_n

int f_n = 0

Definition at line 38 of file iloan.c.

Referenced by main().

◆ f_pmt

int f_pmt = 0

Definition at line 40 of file iloan.c.

Referenced by main().

◆ f_pv

int f_pv = 0

Definition at line 37 of file iloan.c.

Referenced by main().

◆ f_quiet

bool f_quiet = false

Definition at line 41 of file iloan.c.

Referenced by calculate_i(), calculate_n(), calculate_pmt(), calculate_pv(), and main().

◆ in_str

char in_str[BUFSIZ+1]
Examples
/usr/local/src/C-Menu/src/enterstr.c.

Definition at line 20 of file iloan.c.

Referenced by accept_i(), accept_n(), accept_pmt(), accept_pv(), and accept_str().