diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cb77d18 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.dSYM diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..02fddc7 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "fsm", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/fsm", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "lldb" + } + ] +} \ No newline at end of file diff --git a/fsm b/fsm new file mode 100755 index 0000000..70a7254 Binary files /dev/null and b/fsm differ diff --git a/fsm.c b/fsm.c new file mode 100644 index 0000000..2f58270 --- /dev/null +++ b/fsm.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include + +#define ARR_LEN(X) (sizeof(X) / sizeof(X[0])) + +typedef enum { + START_STATE, + DECIMAL_STATE, + NUM_STATE, + FRACTION_STATE, + EXPONENT_STATE, + EXP_SIGN_STATE, + POWER_STATE, + END_STATE, + INVALID_STATE, +} states; + +states handle_start(char input); +states handle_decimal(char input); +states handle_num(char input); +states handle_fraction(char input); +states handle_exponent(char input); +states handle_exp_sign(char input); +states handle_power(char input); + +states state_machine(states current, char input); + +bool check_number(const char *num); + +const char *inputs[] = { + "0000000", // INVALID + "01", // INVALID + "f0", // INVALID + "1f", // INVALID + "1.f", // INVALID + "1.0f", // INVALID + "8987", // VALID + "9.5", // VALID + " 7", // VALID + " 7.8", // VALID + "732.9834e", // INVALID + "732.9834e-", // INVALID + "732.9834e+", // INVALID + "732.9834e-g", // INVALID + "732.9834e-8", // VALID + "732.9834e+8", // VALID +}; + +int main(int argc, char *argv[]) { + for (int i = 0; i < ARR_LEN(inputs); ++i) { + printf("%s is %s\n", inputs[i], + check_number(inputs[i]) ? "VALID" : "INVALID"); + } + + return EXIT_SUCCESS; +} + +states handle_start(char input) { + if (isspace(input)) { + return START_STATE; + } else if (input == '0') { + return DECIMAL_STATE; + } else if (isdigit(input)) { + return NUM_STATE; + } + + return INVALID_STATE; +} + +states handle_decimal(char input) { + if (input == '.') { + return FRACTION_STATE; + } + + return INVALID_STATE; +} + +states handle_num(char input) { + if (isdigit(input)) { + return NUM_STATE; + } else if (input == '.') { + return FRACTION_STATE; + } else if (isspace(input)) { + return END_STATE; + } + + return INVALID_STATE; +} + +states handle_fraction(char input) { + if (isdigit(input)) { + return FRACTION_STATE; + } else if (isspace(input)) { + return END_STATE; + } else if (input == 'e' || input == 'E') { + return EXPONENT_STATE; + } + + return INVALID_STATE; +} + +states handle_exponent(char input) { + if (isdigit(input)) { + return POWER_STATE; + } else if (input == '+' || input == '-') { + return EXP_SIGN_STATE; + } + + return INVALID_STATE; +} + +states handle_exp_sign(char input) { + if (isdigit(input)) { + return POWER_STATE; + } + + return INVALID_STATE; +} + +states handle_power(char input) { + if (isdigit(input)) { + return POWER_STATE; + } else if (isspace(input)) { + return END_STATE; + } + + return INVALID_STATE; +} + +states state_machine(states current, char input) { + switch (current) { + case START_STATE: + return handle_start(input); + case DECIMAL_STATE: + return handle_decimal(input); + case NUM_STATE: + return handle_num(input); + case FRACTION_STATE: + return handle_fraction(input); + case EXPONENT_STATE: + return handle_exponent(input); + case EXP_SIGN_STATE: + return handle_exp_sign(input); + case POWER_STATE: + return handle_power(input); + case END_STATE: + case INVALID_STATE: + return current; + } +} + +bool check_number(const char *num) { + states current = START_STATE; + + for (const char *c = &(num[0]); *c != '\0'; ++c) { + current = state_machine(current, *c); + + if (current == INVALID_STATE) { + return false; + } + } + + return current == END_STATE || current == NUM_STATE || + current == FRACTION_STATE || current == POWER_STATE; +}