Quote:
> I'm a complete newbie to C programming. It is very exciting! I've
> put together a small function to get a float from the user. It seems
> to work fine on my Linux system with gcc 2.95.3, but I'm wondering
> about the style and possibly portability. If it wouldn't be too much
> trouble for the more experienced programmers to comment, I'd
> appreciate it. Here it is:
> # include <stdio.h>
> # include <stdlib.h>
> # include <string.h>
> int main (void)
> {
> char *ptr1, String[50], Letters[85] =
;:/?>,<";
> float FloatNumber;
> int x = 0, Length;
> while (x == 0)
> {
> printf("Enter your number : ");
> fgets(String, 50, stdin); /*Check to see if the user*/
> Length = strlen(String) - 1; /*input nothing*/
> if (Length == 0)
> {
> printf("No input. Try again\n");
> x = 0;
> }
> else if (Length == 1)
> {
> printf("One digit input can't be a float. Try again.\n");
> x = 0;
> }
> else if (strpbrk(String,Letters) != NULL) /*Check String*/
> { /*for characters above*/
> printf("Input contains non-numeric characters. Try Again.\n");
> x = 0;
> }
> else
> x = 1;
> }
> FloatNumber = strtod(String, &ptr1);
> printf("Your result is %3.3f\n", FloatNumber);
> return 0;
> }
Your first problem is that Letters is neither sound nor complete: it contains
implementation's character set; and, likewise, there are characters in the
implementation's character set which aren't in Letters. This is a serious
portability problem.
This is not really a good way to do it anyway; strtod() performs its own
error-detection, so you end up scanning the string twice.
Another problem is that you immediately subtract one from the length of
String. This gives you erroneous results: an empty string will have Length
-1 (which you don't catch). There are other problems associated with the
Length: a string length 1 (Length 0) is valid; a string of length 2 (Length
1) is valid; but you dismiss them both.
Also, there are other miscellaneous problems: if stdout is line-buffered,
your prompt likely won't be displayed before the input is read; using a
variable (x) to trigger exit from the loop is IMHO less elegant than a simple
break; floats should almost never be used (use doubles unless you are
creating huge arrays and need to save memory).
If you want to do the error-detection yourself, you might then try rewriting
it as so, with the aformentioned problems solved:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int
main(void)
{
double FloatNumber;
char String[50], char *end_str;
goto read_number;
do {
fprintf(stderr, "Bad input. Try again\n");
read_number :
printf("Enter your number: ");
fflush(stdout);
if (! fgets(String, sizeof String, stdin)) {
/* either an EOF or error: deal with it */
}
/* chop the newline off the end of the String */
size_t Length = strlen(String);
if (String[Length - 1] == '\n')
String[--Length] = 0;
errno = 0;
FloatNumber = strtod(String, end_str);
/*
* if *end_str is not the null character, then it doesn't point to
* the end of the string, and thus there was some bad input was given
*
* if FloatNumber == HUGE_VAL and errno is set, the number overflowed
* (is too large to fit into a double)
*
*/
} while (*end_str || FloatNumber == HUGE_VAL && errno);
printf("Your result is %3.3f\n", FloatNumber);
return 0;
Quote:
}
Something to keep in mind is that functions in the standard library almost
always return to you useful information and error conditions. e.g. in this
example I've checked the error conditions returned to me by fgets() and
strtod(), which helped me out a lot.
--
/"\ m i k e b u r r e l l
X AGAINST HTML MAIL,
/ \ AND NEWS TOO, dammit