Last active
December 5, 2016 05:31
-
-
Save iamarkdev/95827fc2f49d46a42eb44dcce0c7675e to your computer and use it in GitHub Desktop.
ATOF with support for scientific notation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#define MAX_LINE_LENGTH 100 | |
enum PositionState { | |
POSITION_STATE_WHOLE, | |
POSITION_STATE_DECIMAL, | |
POSITION_STATE_NOTATION | |
}; | |
int mygetline(char line[], int max) { | |
int c, i; | |
for (i = 0; i < max && (c = getchar()) != EOF && c != '\n'; i++) { | |
line[i] = c; | |
} | |
if (i >= max) { | |
i = i - 1; | |
} | |
line[i] = '\0'; | |
return i; | |
} | |
int isDigit(char input) { | |
return (input >= '0' && input <= '9') ? 1 : 0; | |
} | |
long power(int base, int exponent) { | |
long result = (exponent > 0) ? base : 0; | |
for (int i = 0; i < exponent - 1; i++) { | |
result *= base; | |
} | |
return result; | |
} | |
float atof(char input[]) { | |
int sign = 1; | |
int whole = 0; | |
float decimal = 0; | |
int decimalCount = 0; | |
int notationExponents = 0; | |
int notationSign = 1; | |
int i = 0; | |
while ((input[i] < '0' || input[i] > '9') && input[i] != '+' && input[i] != '-') { | |
i++; | |
} | |
if (input[i] == '+' || input[i] == '-') { | |
sign = (input[i++] == '-') ? -1 : sign; | |
} | |
enum PositionState state = POSITION_STATE_WHOLE; | |
while (input[i] != '\n' && input[i] != ' ' && input[i] != '\t' && input[i] != '\0') { | |
// Return 0 for invalid characters. | |
if ((input[i] < '0' || input[i] > '9') && input[i] != 'e' && input[i] != 'E' && input[i] != '-' && input[i] != '+' && input[i] != '.') { | |
fprintf(stderr, "Invalid char \"%c\" found in atof() input.\n", input[i]); | |
return 0; | |
} | |
// Handle whole numbers | |
if (state == POSITION_STATE_WHOLE) { | |
if (isDigit(input[i])) { | |
whole = whole * 10 + (input[i] - '0'); | |
} | |
} | |
// Handle decimals | |
if (state == POSITION_STATE_DECIMAL) { | |
if (isDigit(input[i])) { | |
decimalCount++; | |
decimal = decimal * 10 + (input[i] - '0'); | |
} | |
} | |
state = (input[i] == '.') ? POSITION_STATE_DECIMAL : state; | |
// Handle notation | |
if (state == POSITION_STATE_NOTATION) { | |
if (input[i] == '-') { | |
notationSign = -1; | |
i++; | |
} | |
if (isDigit(input[i])) { | |
notationExponents = notationExponents * 10 + (input[i] - '0'); | |
} | |
} | |
state = (input[i] == 'e' || input[i] == 'E') ? POSITION_STATE_NOTATION : state; | |
// Next char in input | |
i++; | |
} | |
// Calculate result | |
double result = whole; | |
if (decimalCount > 0) { | |
result += decimal / power(10, decimalCount); | |
} | |
if (notationExponents > 0) { | |
if (notationSign > 0) { | |
result *= power(10, notationExponents); | |
} else { | |
result /= power(10, notationExponents); | |
} | |
} | |
return sign * result; | |
}; | |
int main() { | |
int c; | |
char line[MAX_LINE_LENGTH]; | |
while (mygetline(line, MAX_LINE_LENGTH)) { | |
printf("%f\n", atof(line)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How about this for a power() implementation?
then instead of this code:
it could simply be:
where notationExponents can be a negative, positive, or zero value