// TODO: add decimal point hex and octal support // TODO: add limit to maximum imput allowed #include //printf(), fprintf() #include //assert() #include //exit() #include //_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; }