Anybody know how I would code an error statement when a user inputs an invalid input.

J

jeff regoord

A user inputs a float value. The scanf() function gets the value.
However, I need to create an error handler with an if else statement
saying invalid input if the input is not a number. Does anybody know
how I could do this?
 
P

pete

jeff said:
A user inputs a float value. The scanf() function gets the value.
However, I need to create an error handler with an if else statement
saying invalid input if the input is not a number. Does anybody know
how I could do this?

/* BEGIN new.c */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define STRINGLENGTH 1000
#define str(x) # x
#define xstr(x) str(x)

int main(void)
{
char string[STRINGLENGTH + 1] = {'\0'};
int rc;

fputs("Enter a floating point value: ", stdout);
fflush(stdout);
rc = scanf("%" xstr(STRINGLENGTH) "[^\n]%*[^\n]", string);
getchar();
while (rc) {
double number;
char *endptr;

number = strtod(string, &endptr);
if (errno) {
puts("Value out of range.");
errno = 0;
} else if (*endptr && !isspace((int)*endptr)) {
puts("\nI'm sorry Dave. I'm afraid I can't do that.\n");
} else {
printf("The number is %f\n", number);
}
fputs("Enter a floating point value: ", stdout);
fflush(stdout);
rc = scanf("%" xstr(STRINGLENGTH) "[^\n]%*[^\n]", string);
getchar();
}
return 0;
}

/* END new.c */
 
A

Arthur J. O'Dwyer

A user inputs a float value. The scanf() function gets the value.
However, I need to create an error handler with an if else statement
saying invalid input if the input is not a number. Does anybody know
how I could do this?

Try to be more specific. At the most basic level, you could write

int ret;
...

input_the_number:
ret = scanf("%d", &number);

if (ret != 1) {
printf("That was not a number; try again!\n");
goto input_the_number;
}
if (number < 0) {
printf("That was negative; try again!\n");
goto input_the_number;
}
...


(Or equivalent stuff with more advanced control-flow structures, but I'm
too tired to work out where everything would go in a 'while' loop.)

At a more advanced level, the concept of "error handling" is a pretty
interesting one. I myself am a fan of the following little function:


#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

static char *Argv0;

void do_error(const char *fmat, ...);

int main(int argc, char *argv[])
{
Argv0 = argv[0];

if (0 == 1) {
do_error("Oh dearie me: %d %d %d\n", 0, 1, 0==1);
}

return 0;
}

/** This is the interesting bit. */

void do_error(const char *fmat, ...)
{
va_list ap;
printf("%s: ", Argv0);
va_start(ap, fmat);
vprintf(fmat, ap);
va_end(ap);
exit(EXIT_FAILURE);
}


In case you can't figure it out from the code, the do_error function
takes a variable number of arguments, just like 'printf', but before
printing them, it tries to print the name of the executing program,
and then, once everything is printed, it terminates the program
directly. This is for those "no recovery possible" sorts of situations,
which may or may not apply to your problem.

As you may know, and unlike C++, C does *not* support exception handling
at the language level. (Anyone got a nice throw/catch sort of idiom for
standard C? :)

HTH,
-Arthur
 
K

Kevin Easton

Arthur J. O'Dwyer said:
As you may know, and unlike C++, C does *not* support exception handling
at the language level. (Anyone got a nice throw/catch sort of idiom for
standard C? :)

This might be a good start if you wanted to look into this area...

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

struct ehandler { jmp_buf env; };

struct ehandler next_up_handler;

#define INIT_EXCEPTIONS \
if (setjmp(next_up_handler.env)) { \
fprintf(stderr, "Uncaught exception, terminating.\n"); \
exit(EXIT_FAILURE); \
}

#define I_CATCH_EXCEPTIONS volatile int caught;

#define try { \
volatile struct ehandler saved_handler = next_up_handler; \
if (!(caught = setjmp(next_up_handler.env)))

#define catch \
next_up_handler = saved_handler; \
} if (caught) \

#define throw longjmp(next_up_handler.env, 1)

/* Exception-throwing version of malloc */
void *emalloc(size_t s)
{
void *r = malloc(s);
if (!r)
throw;
return r;
}

int bar()
{
throw;

return 0;
}

int foo()
{
I_CATCH_EXCEPTIONS
void * volatile j;

j = emalloc(100);
try {
bar();
} catch {
printf("foo caught exception, cleaning up...\n");
free(j);
throw;
}

printf("foo Normal function execution\n");
free(j);

return 0;
}

int main()
{
I_CATCH_EXCEPTIONS

INIT_EXCEPTIONS

try {
foo();
} catch {
fprintf(stderr, "main caught an exception, exiting\n");
return EXIT_FAILURE;
}

printf("program completed normally.\n");

return 0;
}

Obviously if you wanted to make this sort of thing more
production-quality you'd have to use a consistent namespace for
identifiers and that sort of thing - perhaps you'd want to allow
multiple kinds of exceptions too.

- Kevin.
 
K

Kevin Easton

I wrote:
[...]
#define I_CATCH_EXCEPTIONS volatile int caught;

#define try { \
volatile struct ehandler saved_handler = next_up_handler; \
if (!(caught = setjmp(next_up_handler.env)))

#define catch \

Come to think of it, it'd be better to put an empty statement in here:

; \

Just in case someone puts a catch immediately after a try without an
intervening statement. Alternatively it could just be specified that
there has to be a statement there - there's already other restrictions
like no return statements inside try blocks.
 
G

goose

Arthur J. O'Dwyer said:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

static char *Argv0;

void do_error(const char *fmat, ...);

int main(int argc, char *argv[])
{
Argv0 = argv[0];

if (0 == 1) {
do_error("Oh dearie me: %d %d %d\n", 0, 1, 0==1);
}

return 0;
}

/** This is the interesting bit. */

void do_error(const char *fmat, ...)
{
va_list ap;
printf("%s: ", Argv0);
va_start(ap, fmat);
vprintf(fmat, ap);
va_end(ap);
exit(EXIT_FAILURE);
}


In case you can't figure it out from the code, the do_error function
takes a variable number of arguments, just like 'printf', but before
printing them, it tries to print the name of the executing program,
and then, once everything is printed, it terminates the program
directly. This is for those "no recovery possible" sorts of situations,
which may or may not apply to your problem.

I normally do something along the lines of the following coupled with
returning an error code.

#define ERROR_CONTINUE(s) \
fprintf (stderr, "%s:%05i:%s\n", __FILE__, __LINE__, s)

#define ERROR_FATAL(s,e) \
(fprintf (stderr, "FATAL ERROR*"), ERROR_CONTINUE(s), exit(e))
As you may know, and unlike C++, C does *not* support exception handling
at the language level. (Anyone got a nice throw/catch sort of idiom for
standard C? :)

I've done a simplistic try/catch/throw with C using macros
extensively, but imho it looks very ugly indeed (although it
works as expected). i also toyed with the idea of doing an
error reporting mechanism via a few macros and a signal handling
function, along the lines of

#define THROW(e) raise(e)

this of course needs no try/catch statement, the signal handling
function has to take care of the errors. i found this to be unsuitable
as well, especially when i need to close files or free memory before
ending.

my current method is to write my code as a state machine using
function pointers:

struct error_t {
char *file;
int line;
char *mesg;
};

struct args_t {
...
};

typedef int (*fp) (struct error_t *, struct args_t *);

....
int main (void) {
struct error_t errors;
struct args_t args;
fp function_to_run;
...
while (function_to_run!=NULL) {
if (function_to_run (&errors, &args)) {
/* handle error here */;
}
}
...
}

unfortunately, this does not lend itself all that well to lots of
solutions, so i just stick with my first method above of reporting
file and line number (and error) and then returning values indicating
success or failure and letting the caller take care of it.

goose,
 
F

Fred L. Kleinschmidt

jeff said:
A user inputs a float value. The scanf() function gets the value.
However, I need to create an error handler with an if else statement
saying invalid input if the input is not a number. Does anybody know
how I could do this?

#include <stdio.h>
int main( int argc, char *argv[] ) {
char buffer[128];
int n;
double value;
char ch[2];
/* Should worry about entering string longer than buffer size,
* but for simplicity, ignore for now...
*/
while ( fgets( buffer, sizeof(buffer), stdin) ) {
n = sscanf( buffer, "%lf%1s", &value, ch );
if ( n == 1 ) {
printf( "Number entered: %lf\n", value );
}
else {
printf( "Invalid input\n");
}
}
}
 
M

Mark McIntyre

A user inputs a float value. The scanf() function gets the value.
However, I need to create an error handler with an if else statement
saying invalid input if the input is not a number. Does anybody know
how I could do this?

easy - don't use scanf. Its a dangerous and hard to control function
with limited error handling. Use fgets and either sscanf or strod.
 
J

jeff regoord

Mark McIntyre said:
easy - don't use scanf. Its a dangerous and hard to control function
with limited error handling. Use fgets and either sscanf or strod.


OK thank you all. Im a novice. How would I make an if else saying
invalid entry to this program. Maybe no number input
/* Currency Conversion. User inputs amount of Canadian dollars he or
she has. The program decides if */
/* valid entry was input by user. If valid entry occurs. Program
outputs conversion to U.S dollars */
/*If there is an invalid entry an error message is ouptut Not a valid
entry */

#include <stdio.h>


float cad = 0.0; /* CAD Canadian Dollar variable */
float usd = 0.0; /* USD U.S dollar variable */

int main() /* start main function */

{

printf( "\n \n ** Currency Conversion ** \n \n"); /* Print
name of program */

printf("Enter number of Canadian Dollars then press enter :
");/* Print statement informing user to input number of canadian
dollars */
scanf("%f", &cad); /* gets the value entered by user */

if(cad < 0.0)
printf("Not a valid entry");
else
usd = cad * 0.725415; /* Canadian dollars conversion to
U.S dollars*/
printf(" \n Your Canadian dollars are equal to $
%.2f", usd); /* Output to screen U.S value */
printf(" in U.S dollars.\n \n");


return 0; /* Return statement to turn control over to operating
system */
}
 
T

The Real OS/2 Guy

OK thank you all. Im a novice. How would I make an if else saying
invalid entry to this program. Maybe no number input
/* Currency Conversion. User inputs amount of Canadian dollars he or
she has. The program decides if */
/* valid entry was input by user. If valid entry occurs. Program
outputs conversion to U.S dollars */
/*If there is an invalid entry an error message is ouptut Not a valid
entry */

#include <stdio.h>


float cad = 0.0; /* CAD Canadian Dollar variable */
float usd = 0.0; /* USD U.S dollar variable */

It's a bad idea to hold monetary data in float. Float is not precise
enough to hold currencies. What give 1.00 / 0.37 ?
See what your float will give you. See what you bank will say to it.

use long or long long instead.
int main() /* start main function */

{

printf( "\n \n ** Currency Conversion ** \n \n"); /* Print
name of program */

printf("Enter number of Canadian Dollars then press enter :
");/* Print statement informing user to input number of canadian
dollars */
scanf("%f", &cad); /* gets the value entered by user */

I type abde
scanf returns 0 Your program calculates with the last input prior.

I type -1.3456789
scanf returns 1 but your program cries invalid number.

I type e4567

It will be accepted, even as the input should be 34567 and the user
had made a typing mistake.

I type 0.000000000456789
your program accepts it, even as a currency has only 2 decimal digits.

What occures with the input 1e3.47b2?

You have to do pernickety checking the input. None of the functions in
the standard C library is able to do that.
As you needs to check the input precise you should use getc() to read
the input and convert on the fly. The converted result will be fine
only when the whole line is guilty, else remove anything from the
input stream until '\n' is found and give an error message to the
user.

Use long or long long, calculate cents, not dollars, print out
dollars.cents
if(cad < 0.0)
printf("Not a valid entry");
else
usd = cad * 0.725415; /* Canadian dollars conversion to
U.S dollars*/
printf(" \n Your Canadian dollars are equal to $
%.2f", usd); /* Output to screen U.S value */
printf(" in U.S dollars.\n \n");

How precise is the result when someone type 17131713.13?

Gets you USD 0.0943039 when you tries to convert 0.13 CSD? Should you
not print 0.09?

Is 0.1235342274543357e37 a guilty currency member?

You have some work to print a value that is formatted like a currency
and not ony a mathematical value. But anyway the result will be really
worse when you lets a float or double falsyfy the result.

Do never trust a float/double when you have to calculate commercial.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top