#include #include #include #include #include #include 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; }