summaryrefslogtreecommitdiff
path: root/my_atoi.c
diff options
context:
space:
mode:
authorClay Smith <claysmith158@gmail.com>2023-08-01 01:09:09 -0500
committerClay Smith <claysmith158@gmail.com>2023-08-01 01:09:09 -0500
commit102341d7ae8793c29d44fa416d3b5b797d1eca3e (patch)
tree6df9a5d5ef978dc6809a7d71d50de6e359dae2e7 /my_atoi.c
First commitHEADmain
Diffstat (limited to 'my_atoi.c')
-rw-r--r--my_atoi.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/my_atoi.c b/my_atoi.c
new file mode 100644
index 0000000..c5b0642
--- /dev/null
+++ b/my_atoi.c
@@ -0,0 +1,192 @@
+// TODO: add decimal point hex and octal support
+// TODO: add limit to maximum imput allowed
+#include <stdio.h> //printf(), fprintf()
+#include <assert.h> //assert()
+#include <stdlib.h> //exit()
+#include <stdbool.h> //_Bool, false, true
+#include "my_atoi.h"
+
+#define ASCIIFIRST 48
+#define ASCIILAST 57
+#define NULL '\0'
+
+double my_atoi(char* str)
+{
+ int i = 0, start = 0, base = 10, floatIndex;
+ double num2Convert = 0;
+ _Bool boolHex = false, boolOctal = false, boolNegative = false, boolFloat = false, priorZero = false;
+
+//017 -017 no decimals for hex or octal NULL, -NULL, .NULL, 0xNULL, 0XNULL, -.NULL, -0xNULL, -0XNULL, 0x., -0x., 0X., -0X., -0[8,9,a-f,A-F], xX can only be in the second or third index 8-9, a-f, A-F, -, ., xX octal: - 0-7 decimal: - . 0-9 hex: 0-9 a-f A-F - xX
+
+if (str[0] == '-') {
+ boolNegative = 1;
+ ++start;
+ ++i;
+}
+
+do {
+ switch (str[i]) {
+ case '0':
+ if (!priorZero) {
+ priorZero = true;
+ if (i == 0 || (i == 1 && boolNegative)) {
+ if (str[i + 1] == NULL) {
+ return 0;
+ } else if (str[i + 1] == '.') {
+ boolFloat = 1;
+ floatIndex = i = 1;
+ ++i;
+ } else {
+ boolOctal = 1;
+ ++start;
+ }
+ }
+ }
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ break;
+ case '8':
+ case '9':
+ if (boolOctal) {
+ fprintf(stderr, "ERROR: %c is an invalid input for octal numbers\n", str[i]);
+ exit(-1);
+ }
+ break;
+ case 'a':
+ case 'A':
+ case 'b':
+ case 'B':
+ case 'c':
+ case 'C':
+ case 'd':
+ case 'D':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ if (!boolHex) {
+ fprintf(stderr, "ERROR: %c is an invalid input for octal and/or decimal numbers\n", str[i]);
+ exit(-1);
+ }
+ break;
+ case '.':
+ if (boolFloat) {
+ fprintf(stderr, "ERROR: String contains more than one '.'\n");
+ exit(-1);
+ } else if (boolHex || boolOctal) {
+ fprintf(stderr, "ERROR: Currently not accepting hexidecimal or octal floating point numbers.\n");
+ exit(-1);
+ } else {
+ boolFloat = 1;
+ floatIndex = i;
+ }
+ break;
+ case NULL:
+ if (i == 0 || str[i - 1] == '-' || str[i - 1] == 'x' || str[i - 1] == 'X'){
+ fprintf(stderr, "ERROR: Entered an empty number.\n");
+ exit(-1);
+ }
+ break;
+ case 'x':
+ case 'X':
+ if (i != 1 && i != 2 && str[i - 1] != 0) {
+ fprintf(stderr, "ERROR: 'x or X' characters can only be included once and must be preceeded by a 0.\n");
+ exit(-1);
+ }
+ boolOctal = 0;
+ boolHex = 1;
+ ++start;
+ break;
+ default:
+ fprintf(stderr, "ERROR: Invalid character included.\n");
+ exit(-1);
+ }
+ ++i;
+} while (str[i] != NULL); //when this is done I will be the number of characters including null termination
+
+
+ if (boolHex) {
+ for (int j = i - 1, multi = 1, base = 16; j > start - 1; multi *= base, --j) {
+ switch (str[j]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ num2Convert += (multi * (str[j] - ASCIIFIRST));
+ break;
+ case 'a':
+ case 'A':
+ num2Convert += multi * 10;
+ break;
+ case 'b':
+ case 'B':
+ num2Convert += multi * 11;
+ break;
+ case 'c':
+ case 'C':
+ num2Convert += multi * 12;
+ break;
+ case 'd':
+ case 'D':
+ num2Convert += multi * 13;
+ break;
+ case 'e':
+ case 'E':
+ num2Convert += multi * 14;
+ break;
+ case 'f':
+ case 'F':
+ num2Convert += multi * 15;
+ break;
+ default:
+ fprintf(stderr, "ERROR: out of bounds character for hexadecimal. Only use 0-9,Aa-Ff\n");
+ }
+ }
+ } else if (boolOctal) {
+ for (int j = i - 1, multi = 1, base = 8; j > start - 1; multi *= base, --j) {
+ if (str[j] > ASCIILAST - 2) {
+ fprintf(stderr, "ERROR: out of bounds range for octal number. Only use 0-7.\n");
+ } else {
+ num2Convert += multi * (str[j] - ASCIIFIRST);
+ }
+ }
+ } else if (boolFloat) {
+ fprintf(stderr, "NEED TO FIGURE OUT HOW TO CONVERT FLOATS STILL\n");
+ //count distance from end -1 to floatIndex and take that number and divide it by the appropriate multiple of 10
+ //then do the portion to the left of the decimal the exact same as usual
+ {
+ double multi = .1;
+ for (int j = floatIndex + 1, base = 10; j < i; multi /= base, ++j) {
+ num2Convert += multi * (str[j] - ASCIIFIRST);
+ }
+ }
+ for (int j = floatIndex - 1, multi = 1, base = 10; j >= start; multi *= base, --j) {
+ num2Convert += multi * (str[j] - ASCIIFIRST);
+ }
+ } else {
+ for (int j = i - 1, multi = 1, base = 10; j >= start; multi *= base, --j) {
+ num2Convert += multi * (str[j] - ASCIIFIRST);
+ }
+ }
+
+ if (boolNegative) {
+ num2Convert *= -1;
+ }
+
+ printf("boolHex: %d, boolOctal: %d, boolFloat: %d, boolNegative: %d, \n", boolHex, boolOctal, boolFloat, boolNegative);
+
+ return num2Convert;
+
+}