-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcalc.c
More file actions
109 lines (99 loc) · 3.04 KB
/
Copy pathcalc.c
File metadata and controls
109 lines (99 loc) · 3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include "calc.h"
#include "abacus.h"
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
// TODO: REMOVE
void calc_print_input(struct calc_input* in)
{
printf("k = %zu\n"
"operator: %s\n"
"operands: ",
in->k, in->operator);
for (size_t i = 0; i < in->k; ++i) {
printf("%g ", in->operands[i]);
}
putchar('\n');
}
struct calc_input* calc_input_create()
{
return malloc(sizeof(struct calc_input));
}
void calc_input_init(size_t n, struct calc_input* in)
{
*in = (struct calc_input){
.k = n,
.operands = malloc(sizeof(double[n])),
.result = NAN,
.operator = 0,
};
}
void calc_input_destroy(struct calc_input* input)
{
free(input->operands);
*input = (struct calc_input){ 0 };
free(input);
}
/**
* calc_parse parses and stores every number present in command line input
* passed to the function. Supports either infix or polish notation and an
* arbitrary number of operands.
*
* size_t n indicates the length of the args array.
*
* struct calc_input* res must be a valid pointer to a calc_input object that
* has been created and initialized.
*/
void calc_parse(size_t n, char** args, struct calc_input* res)
{
double* operands = res->operands;
char* pos;
char* op;
/* Handle case of polish notation by checking if the first entry in args
* is a valid double or not; if it is not it is the operator. */
size_t i = 1;
double currNum = strtod(args[i], &pos);
if (pos == args[i]) {
op = args[i];
++i;
}
operands[i] = currNum;
++i;
/* Parse remaining numbers */
for (; i < n; ++i) {
currNum = strtod(args[i], &pos);
/* Any conversion that does not yield a double must be an
* operator; if there is more than one operator present, use the
* most recently-encountered one */
if (pos == args[i]) {
op = args[i];
continue;
}
operands[i] = currNum;
}
/* op may be null if input is composed solely of doubles */
if (!op) {
fprintf(stderr, "calc (FATAL): no operator\n");
errno = 1;
return;
}
res->operator = op;
}
/* Performs the actual calculation and returns the result */
double calc_compute(struct calc_input* in)
{
switch (*in->operator) {
case '+':
return abacus_sum(in->k, in->operands);
case '-':
return abacus_difference(in->k, in->operands);
case '/':
return abacus_quotient(in->k, in->operands);
case '*':
return abacus_product(in->k, in->operands);
default:
fprintf(stderr, "operation unknown: %s", in->operator);
return NAN;
}
}