diff --git a/.vscode/settings.json b/.vscode/settings.json index 1de26dd..bca80c1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,8 @@ { "files.associations": { "*.ejs": "html", - "stdio.h": "c" + "stdio.h": "c", + "stdbool.h": "c", + "string.h": "c" } } \ No newline at end of file diff --git a/Makefile b/Makefile index b75a8e0..f6378c6 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,3 @@ build: mkdir -p bin - gcc -O3 -o bin/cargon $(shell find src -name '*.c') -Wall -Wextra -Werror \ No newline at end of file + gcc -O3 -o bin/cargon $(shell find src -name '*.c') -lm -Wall -Wextra -Werror \ No newline at end of file diff --git a/bin/cargon b/bin/cargon index c3bed33..e010e00 100755 Binary files a/bin/cargon and b/bin/cargon differ diff --git a/src/main.c b/src/main.c index 95ea820..17bda6e 100644 --- a/src/main.c +++ b/src/main.c @@ -1,32 +1,29 @@ #include "string/string.h" +#include "number/number.h" #include #include #include +void initialize() { + initNumber(); +} + +void cleanup() { + cleanupNumber(); +} + int main() { - char* str = malloc(100 * sizeof(char)); - if (str == NULL) { - printf("Failed to allocate memory\n"); + initialize(); + char *code = "1.2e20"; + struct number mynum = translateNumber(code); + if (mynum.denominator == 0) { + printf("Invalid number\n"); return 1; } - strcpy(str, " \t\n\r\f\vHello, World! \t\n\r\f\v"); - char* clone = cloneString(str); - - if (clone == NULL) { - printf("Failed to clone string\n"); - return 1; - } - - stripString(clone, WHITE_SPACE); - - printf("Original string: \"%s\"\n", str); - - free(str); - - - printf("Cloned string: \"%s\"\n", clone); - free(clone); - + double f = 1.0 * mynum.numerator / mynum.denominator; + printf("Numerator: %ld\n", mynum.numerator); + printf("Denominator: %lu\n", mynum.denominator); + printf("Float: %lf\n", f); return 0; } diff --git a/src/number/number.c b/src/number/number.c index 861eb98..63ddef0 100644 --- a/src/number/number.c +++ b/src/number/number.c @@ -1,9 +1,108 @@ #include "number.h" +#include "../string/string.h" #include +#include +#include +#include +#include -struct number translateNumber(char *code) { +regex_t numberCompile; + +void initNumber() +{ + int compileError; + compileError = regcomp(&numberCompile, "^( *)(-)?(((([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))(e((\\-|\\+)?([0-9]+)))?))( *)$", REG_EXTENDED); + if (compileError) + { + char errorBuffer[1024]; + regerror(compileError, &numberCompile, errorBuffer, sizeof(errorBuffer)); + fprintf(stderr, "Error compiling regex: %s\n", errorBuffer); + exit(1); + } +} + +void cleanupNumber() +{ + regfree(&numberCompile); +} + +int gcd(int64_t a, int64_t b) +{ + while (b != 0) + { + int temp = b; + b = a % b; + a = temp; + } + return a; +} + +void simplifyFraction(int64_t *numerator, int64_t *denominator) +{ + int common_divisor = gcd(*numerator, *denominator); + *numerator /= common_divisor; + *denominator /= common_divisor; +} + +void doubleToFraction(double num, int64_t *numerator, uint64_t *denominator) { + int currentSign = (num < 0) ? -1 : 1; + num = fabs(num); + + double tolerance = 1.0e-10; + double h1 = 1, h2 = 0, k1 = 0, k2 = 1; + double b = num; + do { + double a = floor(b); + double aux = h1; + h1 = a * h1 + h2; + h2 = aux; + aux = k1; + k1 = a * k1 + k2; + k2 = aux; + b = 1 / (b - a); + } while (fabs(num - h1 / k1) > num * tolerance); + + *numerator = (int64_t)(h1 * currentSign); + *denominator = (uint64_t)k1; +} + +struct number translateNumber(char *code) +{ + char *codeClone = cloneString(code); + stripString(codeClone, WHITE_SPACE); + int reti = regexec(&numberCompile, codeClone, 0, NULL, 0); + if (reti == REG_NOMATCH) + { + return (struct number){ + .numerator = 0, + .denominator = 0 + }; + } struct number num; - num.sign = code[0] == '-' ? 1 : 0; + num.numerator = 0; + num.denominator = 1; + + double coefficient = 0; + int exponent = 0; + + char *e = strchr(codeClone, 'e'); + if (e) { + *e = '\0'; + e++; + if (*e == '+') e++; + exponent = atoi(e); + } + + coefficient = atof(codeClone); + + doubleToFraction(coefficient, &num.numerator, &num.denominator); + + if (exponent > 0) { + num.numerator *= (int64_t)pow(10, exponent); + } else if (exponent < 0) { + num.denominator *= (int64_t)pow(10, -exponent); + } + return num; } diff --git a/src/number/number.h b/src/number/number.h index 0e93d1e..8fff0b1 100644 --- a/src/number/number.h +++ b/src/number/number.h @@ -2,13 +2,17 @@ #define CLONESTRING_HNUMBER_H #include +#include + #include struct number { - uint8_t sign; - uint64_t numerator; + int64_t numerator; uint64_t denominator; }; struct number translateNumber(char *code); +void initNumber(); +void cleanupNumber(); + #endif // NUMBER_H