#include #include #include #include #include #include int string_to_int(const char* s, int* n, int base); int string_to_unsigned(const char* s, unsigned int* n, int base); int string_to_long(const char* s, long int* n, int base); int string_to_unsigned_long(const char* s, unsigned long int* n, int base); int string_to_double(const char* s, double* n); /** * Convert a string to an int. If you pass in a base of * zero, the conversion will treat a leading "0x" prefix as * hexadecimal and a leading "0" prefix as octal. * * @param[in] s string to convert * @param[out] n conversion of s to an unsigned long * @param[in] base base to use for the conversion * @return 1 on success and 0 on error */ int string_to_int(const char* s, int* n, int base) { int rv = 0; long int tmp = 0; if (string_to_long(s, &tmp, base)) { if ((tmp >= INT_MIN) && (tmp <= INT_MAX)) { *n = (int)tmp; rv = 1; } } return rv; } /** * Convert a string to an unsigned. If you pass in a * base of zero, the conversion will treat a leading "0x" * prefix as hexadecimal and a leading "0" prefix as octal. * * @param[in] s string to convert * @param[out] n conversion of s to an unsigned int * @param[in] base base to use for the conversion * @return 1 on success and 0 on error */ int string_to_unsigned(const char* s, unsigned int* n, int base) { int rv = 0; unsigned long int tmp = 0; if (string_to_unsigned_long(s, &tmp, base)) { if (tmp <= UINT_MAX) { *n = (unsigned int)tmp; rv = 1; } } return rv; } /** * Convert a string to a long. If you pass in a base of * zero, the conversion will treat a leading "0x" prefix as * hexadecimal and a leading "0" prefix as octal. * * @param[in] s string to convert * @param[out] n conversion of s to a long int * @param[in] base base to use for the conversion * @return 1 on success and 0 on error */ int string_to_long(const char* s, long int* n, int base) { int rv = 0; long int tmp = 0; char* first_bad_char = NULL; const char* r = NULL; /* Remainder of the string. */ /* You have to manually check for an empty string. */ for ( ; *s != '\0' ; ++s) { if (!isspace(*s)) { break; } } if (*s == '\0') { goto done; } /* Do the conversion. */ errno = 0; tmp = strtol(s, &first_bad_char, base); /* Check for errors. */ if (errno) { goto done; } /* Allow trailing space. */ r = first_bad_char; for ( ; *r != '\0' ; ++r) { if (!isspace(*r)) { break; } } if (*r != '\0') { goto done; } /* Success. */ *n = tmp; rv = 1; done: return rv; } /** * Convert a string to an unsigned long. If you pass in a * base of zero, the conversion will treat a leading "0x" * prefix as hexadecimal and a leading "0" prefix as octal. * * @param[in] s string to convert * @param[out] n conversion of s to an unsigned long int * @param[in] base base to use for the conversion * @return 1 on success and 0 on error */ int string_to_unsigned_long(const char* s, unsigned long int* n, int base) { int rv = 0; int is_negative = 0; unsigned long int tmp = 0; char* first_bad_char = NULL; const char* r = NULL; /* Remainder of the string. */ /* You have to manually check for a leading minus sign or an empty * string. */ for ( ; *s != '\0' ; ++s) { if (!isspace(*s)) { break; } } if (*s == '\0') { goto done; } /* You want to allow "-0" to succeed. So we have to wait to see * how the conversion goes. */ if (*s == '-') { is_negative = 1; } /* Do the conversion. */ errno = 0; tmp = strtoul(s, &first_bad_char, base); /* Check for errors. */ if (errno) { goto done; } /* Allow trailing space. */ r = first_bad_char; for ( ; *r != '\0' ; ++r) { if (!isspace(*r)) { break; } } if (*r != '\0') { goto done; } /* Only "-0" is allowed. */ if (is_negative && (tmp != 0)) { goto done; } /* Success. */ *n = tmp; rv = 1; done: return rv; } /** * Convert a string to a double. The conversion will treat a leading * "0x" prefix as hexadecimal floating point and a leading "0" prefix * as octal floating point. * * @param[in] s string to convert * @param[out] n conversion of s to a double * @return 1 on success and 0 on error */ int string_to_double(const char* s, double* n) { int rv = 0; double tmp = 0.0; char* first_bad_char = NULL; const char* r = NULL; /* Remainder of the string. */ /* You have to manually check for an empty string. */ for ( ; *s != '\0' ; ++s) { if (!isspace(*s)) { break; } } if (*s == '\0') { goto done; } /* Do the conversion. */ errno = 0; tmp = strtod(s, &first_bad_char); /* Check for errors. */ if (errno) { goto done; } /* Allow trailing space. */ r = first_bad_char; for ( ; *r != '\0' ; ++r) { if (!isspace(*r)) { break; } } if (*r != '\0') { goto done; } /* Success. */ *n = tmp; rv = 1; done: return rv; } int main(int argc, char* argv[]) { int rv = 0; double n = 0; char* nl = NULL; /* new line character */ char line[1024]; while (fgets(line, sizeof(line), stdin) != NULL) { /* Remove trailing new line character. */ if ((nl = strrchr(line, '\n')) != NULL) { *nl = '\0'; } /* Look for the exit. */ if ((strcmp(line, "quit") == 0) || (strcmp(line, "exit") == 0)) { break; } /* Try to convert input. */ if (string_to_double(line, &n)) { printf("\"%s\" --> %.6g\n", line, n); } else { printf("Unable to convert: \"%s\"\n", line); } } return rv; }