Hi,
I am trying to validate user input from the scanf function. I have managed to ensure the input is an integer between the limits of 2 and 1000, but I haven't managed to get the program to only allow one value at input. Can I do this with scanf of should I be using something different like sscanf?

Here's the piece of code where my problem is:

/*Asks user for an input for the size of the lattice*/
	printf("Input size of square lattice:	");
	scanf("%d", &row);
	
	/*Input Validation*/
	while (valid_input == 0)

	{
		/*Checks input is only one number*/
		if (scanf("%d", &row) == EXPECTED_ARGS)
		valid_input = 1;
		
		else
		{
			printf("Only one value required to determine square lattice size\n");
			printf("Enter a single value to determine the size of square lattice:	");
			scanf("%d", &row);
		}

		while (exit_flag == 0)
		{
			/*Checks input is in the accepted range	and is an integer*/
			if ((row <= MAX_NUMBER) && (row >= MIN_NUMBER))
			exit_flag = 1;

			else
			{
				valid_input = 0;
				printf("Lattice must be an integer between 2 and 1000\n");
				printf("Enter new lattice size in this range:	");
				scanf("%d", &row);
			}

			
		}
	}

Recommended Answers

All 10 Replies

I think it would be easier to validate user input by getting it as a string then validating the string. For example, if I type "122abv234", scanf() will only pick up the first three characters and ignore the rest with no warning. But if you validate that as an array of characters your program can easily detect that it contains invalid characters.

So will sscanf do this? Because when I try sscanf I get a seg fault. I can only make my program accept command line arguments with sscanf

> So will sscanf do this? Because when I try sscanf I get a seg fault.
Then you're using it (or something) wrong.

You would need to post an example which crashes for us to tell you exactly how it's wrong.

Also, if you want proper validation, then you should use
strtol()
strtoul()
strtod()
None of the *scanf numeric conversions detect overflow for example.

I have only really used sscanf for command line arguments, in int main I would put int main(argc, char* argv[]) , then for each sscanf I would put sscanf(argv[n], %d, %number . I haven't really been taught how to use sscanf in any other way so I'm kind of experimenting.

I tried this:

int main (argc, char* argv[])
{
	int i, j, k, **lattice = 0, row, col, sum = 0, pcntlatt;
	int table[16][2], startlim, valid_input = 0, exit_flag = 0;
	char v[2] = "v", m[5] = "m(e)";

	FILE         *output;
	const char    out_fn[]="0604632_proj2.out";
	
	/*Asks user for an input for the size of the lattice*/
	printf("Input size of square lattice:	");
	
	
	/*Input Validation*/
	while (valid_input == 0)
	{
		sscanf(argv[1], "%d", &row);
		/*Checks input is only one number*/
		if (argc == EXPECTED_ARGS)
			valid_input = 1;
		
		else
		{
			printf("Only one value required to determine square lattice size\n");
			printf("Enter a single value to determine the size of square lattice:	");
		}
	
		while (exit_flag == 0)
		{
			/*Checks input is in the accepted range	and is an integer*/
			if ((row <= MAX_NUMBER) && (row >= MIN_NUMBER))
				exit_flag = 1;

			else
			{
				valid_input = 0;
				printf("Lattice must be an integer between 2 and 1000\n");
				printf("Enter new lattice size in this range:	");
			}

			
		}
	}

and I got a seg fault, I presume because it expecting command line or something. I have never used the functions you have mentioned so I will look them up now

> sscanf(argv[1], "%d", &row);
Yeah, before you even look at argv, you need to check what value is in argc.

If there are no command line parameters, then use argc to tell you that. Looking at argv for parameters which are missing will just segfault (or worse).

Some addition:
Don't forget: the scanf functions returns a counter of successufully processed format descriptors. It's the first stage of an input validation:

if (scanf("%d",&row) != 1) {
    /* 100% bad input */
}

The second validation stage depends on input values, for example:

#define MAXROWS	100
...
if (row < 1 || row > MAXROWS) {
    /* It's an integer but out of range error */
}

Nothing seemed to be working and I haven't really used strtol/strtod before so I am not to confident with them, so I tried fgets.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/*Value defining the number of expected terms
at input plus 1 for the NULL character*/
#define EXPECTED_ARGS	2
/*Values defining the limits for lattice size*/
#define MAX_NUMBER  1000
#define MIN_NUMBER	2

int main (int argc, char* argv[])
{
	int i, j, k, **lattice = 0, row, col, sum = 0, pcntlatt;
	int table[16][2], startlim, valid_input = 0;
	int args;
	char v[2] = "v", m[5] = "m(e)", line[5];

	FILE         *output;
	const char    out_fn[]="0604632_proj2.out";
	
	/*Asks user for an input for the size of the lattice*/
	printf("Input size of square lattice:	");
	fgets(line, sizeof(line), stdin);
	sscanf(line, "%d", &row);
	
	/*Input Validation*/
	while (valid_input < 2)
	{
		valid_input = 0;
		
		/*Checks input is only one number*/
		if (line == EXPECTED_ARGS)
			valid_input++;

		else
		{
			printf("Only one value required to determine square lattice size\n");
			printf("Enter a single value to determine the size of square lattice:	");
		}
	printf("test0.1\n");
		/*Checks input is in the accepted range	and is an integer*/
		if ((row <= MAX_NUMBER) && (row >= MIN_NUMBER))
			valid_input++;

		else
		{
			printf("Lattice must be an integer between 2 and 1000\n");
			printf("Enter new lattice size in this range:	");
		}
	}

My only problem now is I don't know what to compare EXPECTED_ARGS to in the first if statement. If you still think I am going about this the wrong way please do tell me

A sscanf way, and a strtol way

if ( fgets( buff, sizeof buff, stdin ) != NULL ) {

        int     n, result, pos;
        n = sscanf( buff, "%d%n", &result, &pos );
        if ( n == 1 ) {
            /* look at buff[pos] if you care about what followed the int */
            /* or perhaps guess that if pos is too large, overflow MAY have */
            /* occurred, although it's far from fool-proof */
            /* result is the good-ish answer */
        } else {
            /* Not an integer */
        }
        
        long int    result;
        char*       endp;
        result = strtol( buff, &endp, 10 );
        if ( errno != 0 ) {
            /* errno should be ERANGE */
        } else
        if ( result == 0 && endp == buff ) {
            /* nothing useful was input */
        } else {
            /* a good answer in a long int */
            /* carefully cast it to an int if you need an int */
            /* and still care about overflow (for example) */
        }
    } else {
        /* end of file or error */
        /* use feof() and ferror() to find out which */
    }

Hi Thanks for that Salem. One question though. What is buff in your sscanf example? Is it in the standard library or something I have to cast myself. If so what should it be?

buff is just a generic name for a buffer.

I typically use char buff[BUFSIZ]; as BUFSIZ is a handy constant in stdio.h

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.