2025-01-12 22:51:09 +01:00

119 lines
3.2 KiB
C

#include <errno.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
double first, second;
char op;
} CalcStr;
CalcStr parse_input(int n, char *argv[]);
double parse_str_to_int(const char *str);
double calculate(CalcStr calc);
char* manipulate_str(double input);
int main(const int argc, char *argv[]) {
const double res = calculate(parse_input(argc, argv));
char* final_string = manipulate_str(res);
printf("%s %s %s = %s\n", argv[1], argv[2], argv[3], final_string);
free(final_string);
return 0;
}
CalcStr parse_input(const int n, char *argv[]) {
if (n < 4) {
fprintf(stderr, "Insuficient arguments (3 are required), exiting...\n");
exit(EXIT_FAILURE);
}
const CalcStr calc = {parse_str_to_int(argv[1]), parse_str_to_int(argv[3]), *argv[2]};
return calc;
}
double parse_str_to_int(const char *str) {
char *endptr;
errno = 0;
const double num = strtof(str, &endptr);
if (errno == ERANGE || num < INT_MIN || num > INT_MAX) {
fprintf(stderr, "Input '%s' out of bounds\n", str);
exit(EXIT_FAILURE);
}
if (endptr == str) {
fprintf(stderr, "No digits were found\n");
} else if (*endptr != '\0') {
fprintf(stderr, "Invalid character '%c' in input '%s'\n", *endptr, str);
} else {
return num;
}
// if parse fails then quit
exit(EXIT_FAILURE);
}
double calculate(const CalcStr calc) {
switch (calc.op) {
case '+':
return calc.first + calc.second;
case '-':
return calc.first - calc.second;
case 'x':
return calc.first * calc.second;
case '/':
return calc.first / calc.second;
case '%':
return (int)calc.first % (int)calc.second;
case '^':
double r = 1;
for (int i = (int)calc.second; i > 0; i--) {
r *= calc.first;
}
return r;
default:
fprintf(stderr, "Invalid operand type\n");
exit(EXIT_FAILURE);
}
}
char* manipulate_str(const double input) {
const int digit = abs((int)input) == 0 ? 1 : abs((int)input);
const int str_basesize = (int)log10(digit) + 16 + 1;
char *str = malloc(str_basesize * sizeof(char));
if (str == nullptr) {
printf("Failed to allocate the memory\n");
exit(EXIT_FAILURE);
}
memset(str, 0, str_basesize);
snprintf(str, str_basesize, "%f", input);
char *ptr_to_zero = nullptr;
// if it is check if the zeroes are trailing
for (char *i = str; *i != '\0'; i++) {
/* we will only show the last location where zeroes start
if ptr has been reset and we have stumbled upon a zero */
if (*i == '0' && ptr_to_zero == nullptr) {
ptr_to_zero = i;
// reset the pointer if the following digit is no longer zero
} else if (*i != '0') {
ptr_to_zero = nullptr;
}
}
// check if floating point is necessary at all
if (*(ptr_to_zero - 1) == '.') {
ptr_to_zero--;
}
// clean the excess characters: ptr_to_zero is now the final char of the string
*ptr_to_zero = '\0';
return str;
}