471,599 Members | 1,765 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,599 software developers and data experts.

checking and verifying input line in a C program

In a C program I am required to enter three numbers (integers) e.g. 256
7 5 on execution of the program.

C:\> 256 7 5

There should be spaces between the three numbers and on pressing
"enter", further processing is done. The problem requires me to check
whether three numbers have actually been entered in the input line and
to warn if less or more numbers have been entered.

The actual program is required to do something else. But I'm stuck at
this initial input verification. If I use 3 variables x,y & z to store
these numbers and use scanf() e.g. scanf("%d%d%d",&x,&y,&z) then the
problem remains that the input process is not interactive. If excess
arguments are given, anything beyond the third argument will be
discarded by scanf(). If someone gives less than 3 arguments and press
"enter", the cursor goes to the next line and waits.

I guess, the problem requies me to make this process more interactive.
It will warn if less than 3 or more than 3 numbers are keyed by the
user in the input line. Evidently scanf() cannot handle it.

How to implement it in the least complicated manner?

Jan 29 '06 #1
7 2467
Hulo wrote:
In a C program I am required to enter three numbers (integers) e.g.
256 7 5 on execution of the program.

C:\> 256 7 5

There should be spaces between the three numbers and on pressing
"enter", further processing is done. The problem requires me to check
whether three numbers have actually been entered in the input line and
to warn if less or more numbers have been entered.
if you search this newsgroup, I believe that recently there was a thread
discussing somewhat similar problems (look for strtok()). See also my
comments below.

The actual program is required to do something else. But I'm stuck at
this initial input verification. If I use 3 variables x,y & z to store
these numbers and use scanf() e.g. scanf("%d%d%d",&x,&y,&z) then the
problem remains that the input process is not interactive. If excess
arguments are given, anything beyond the third argument will be
discarded by scanf(). If someone gives less than 3 arguments and press
"enter", the cursor goes to the next line and waits.
Do not use scanf() (for detailed discussion of why, search this
newsgroup). If you have to, use fgets()/sscanf() combination. Look them
up in your manual/textbook.

I guess, the problem requies me to make this process more interactive.
It will warn if less than 3 or more than 3 numbers are keyed by the
user in the input line. Evidently scanf() cannot handle it.

How to implement it in the least complicated manner?


You could also try to get your line with fgets() (again, do not use
gets() -- it's dangerous as it can create buffer overflows, see
elsewhere in this newsgroup for detailed discussion), and process it
with strtok(). Look it up in your manual/textbook, and there was also a
thread here recently which discussed strtok() in some detail.

Once you read up on these, give it a go by writing a simple program. If
you get specific problems in your code, do come back here and ask.

Cheers

Vladimir

Jan 29 '06 #2

Hulo wrote:
In a C program I am required to enter three numbers (integers) e.g. 256
7 5 on execution of the program.

C:\> 256 7 5

There should be spaces between the three numbers and on pressing
"enter", further processing is done. The problem requires me to check
whether three numbers have actually been entered in the input line and
to warn if less or more numbers have been entered.

The actual program is required to do something else. But I'm stuck at
this initial input verification. If I use 3 variables x,y & z to store
these numbers and use scanf() e.g. scanf("%d%d%d",&x,&y,&z) then the
problem remains that the input process is not interactive. If excess
arguments are given, anything beyond the third argument will be
discarded by scanf(). If someone gives less than 3 arguments and press
"enter", the cursor goes to the next line and waits.

I guess, the problem requies me to make this process more interactive.
It will warn if less than 3 or more than 3 numbers are keyed by the
user in the input line. Evidently scanf() cannot handle it.

How to implement it in the least complicated manner?


use fgets() to read the whole line, then sscanf() to parse the line.
sscanf()
indicates how many items it read.
--
Nick Keighley

Jan 29 '06 #3
On 29 Jan 2006 04:36:06 -0800, in comp.lang.c , "Hulo"
<sa*************@gmail.com> wrote:
The actual program is required to do something else. But I'm stuck at
this initial input verification. If I use 3 variables x,y & z to store
these numbers and use scanf() e.g. scanf("%d%d%d",&x,&y,&z) then the
problem remains that the input process is not interactive. If excess
arguments are given, anything beyond the third argument will be
discarded by scanf(). If someone gives less than 3 arguments and press
"enter", the cursor goes to the next line and waits.


fgets, then sscanf, then handle too many/ not enough data points.
Mark McIntyre
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Jan 29 '06 #4
Hulo wrote:
In a C program I am required to enter three numbers (integers) e.g. 256
7 5 on execution of the program.

C:\> 256 7 5

There should be spaces between the three numbers and on pressing
"enter", further processing is done. The problem requires me to check
whether three numbers have actually been entered in the input line and
to warn if less or more numbers have been entered.


You've hit what is a surprisingly non trivial thing to do in C. A truly
robust bullet proof program will allow the user to do some things like
entering 00000000000000000000000000000000000000012,
potentially exhausting any fixed with input buffer. The fgets/sscanf
combination can fail because of that and sscanf's %d invokes
undefined behaviour if it receives an integer which is outside the
range of int.

One way is to write a routine that excepts an arbitrary large
input line by dynamically allocating space for it (samples have been
posted to clc on numerous occasions), and then parse that input
using strtol (making use of the 'end' pointer).

If you're willing to flag multiple leading zeros as an error, then you
can fix your buffer to a compile time fixed limit. The following is
not checked, but is a rough guide...

#define BIG_ENOUGH_FOR_INT \
( (int) (sizeof(int) * CHAR_BIT + 11) / 3) )

const char format[100 + BIG_ENOUGH_FOR_INT*3];
char n1[BIG_ENOUGH_FOR_INT];
char n2[BIG_ENOUGH_FOR_INT];
char n3[BIG_ENOUGH_FOR_INT];
char c;
int r;
long l1, l2, l3;

sprintf(format, "%%%d[0123456789]"
"%%*[ \t]%%%d[0123456789]"
"%%*[ \t]%%%d[0123456789]"
"%%c",
BIG_ENOUGH_FOR_INT,
BIG_ENOUGH_FOR_INT,
BIG_ENOUGH_FOR_INT);

scanf("%*[ \t]"); /* ignore leading whitespace */
r = scanf(format, n1, n2, n3, &c);
if (r == 3 || r == 4 && c == '\n')
{
errno = 0;
l1 = strtol(n1, NULL, 10);
l2 = strtol(n2, NULL, 10);
l3 = strtol(n3, NULL, 10);
... further validations...
}

Another alternative is to write your own routine to parse input that
reads a
single integer and does the conversion to int (avoiding overflow),
without
ignoring leading whitespace.

--
Peter

Jan 30 '06 #5
Peter Nilsson wrote:
Hulo wrote:
In a C program I am required to enter three numbers (integers) e.g. 256
7 5 on execution of the program.

C:\> 256 7 5

There should be spaces between the three numbers and on pressing
"enter", further processing is done. The problem requires me to check
whether three numbers have actually been entered in the input line and
to warn if less or more numbers have been entered.

You've hit what is a surprisingly non trivial thing to do in C. A truly
robust bullet proof program will allow the user to do some things like
entering 00000000000000000000000000000000000000012,
potentially exhausting any fixed with input buffer. The fgets/sscanf
combination can fail because of that and sscanf's %d invokes
undefined behaviour if it receives an integer which is outside the
range of int.

One way is to write a routine that excepts an arbitrary large
input line by dynamically allocating space for it (samples have been
posted to clc on numerous occasions), and then parse that input
using strtol (making use of the 'end' pointer).

If you're willing to flag multiple leading zeros as an error, then you
can fix your buffer to a compile time fixed limit. The following is
not checked, but is a rough guide...

#define BIG_ENOUGH_FOR_INT \
( (int) (sizeof(int) * CHAR_BIT + 11) / 3) ) ( (int) (sizeof(int) * CHAR_BIT + 5) / 3) )
is enough for signed, isn't it?
I wonder why you are using two more places...
const char format[100 + BIG_ENOUGH_FOR_INT*3];
char n1[BIG_ENOUGH_FOR_INT];
char n2[BIG_ENOUGH_FOR_INT];
char n3[BIG_ENOUGH_FOR_INT];


Xavier
Jan 31 '06 #6
Peter Nilsson wrote:
.... snip ...
You've hit what is a surprisingly non trivial thing to do in C. A
truly robust bullet proof program will allow the user to do some
things like entering 00000000000000000000000000000000000000012,
potentially exhausting any fixed with input buffer. The fgets/sscanf
combination can fail because of that and sscanf's %d invokes
undefined behaviour if it receives an integer which is outside
the range of int.

One way is to write a routine that excepts an arbitrary large
input line by dynamically allocating space for it (samples have
been posted to clc on numerous occasions), and then parse that
input using strtol (making use of the 'end' pointer).

If you're willing to flag multiple leading zeros as an error, then
you can fix your buffer to a compile time fixed limit.

.... snip ...

Try these, after suitable #includes. No buffers needed. Build int
input routines around them. The only nuisance for that is a
guaranteed method of negating values without creating an integer
overflow.

/* --------------------------------------------------------------
* Skip to non-blank on f, and return that char. or EOF. The next
* char that getc(f) will return is unknown. Local use only,
* because it violates the principle of leaving the terminating
* char in the input stream.
*/
static int ignoreblks(FILE *f)
{
int ch;

do {
ch = getc(f);
} while ((' ' == ch) || ('\t' == ch));
/* while (isblank(ch)); */ /* for C99 */
return ch;
} /* ignoreblks */

/*--------------------------------------------------------------
* Read an unsigned value. Signal error for overflow or no
* valid number found. Returns 1 for error, 0 for noerror, EOF
* for EOF encountered before parsing a value.
*
* Skip all leading blanks on f. At completion getc(f) will
* return the character terminating the number, which may be \n
* or EOF among others. Barring EOF it will NOT be a digit. The
* combination of error, 0 result, and the next getc returning
* \n indicates that no numerical value was found on the line.
*
* If the user wants to skip all leading white space including
* \n, \f, \v, \r, he should first call "skipwhite(f);"
*
* Peculiarity: This specifically forbids a leading '+' or '-'.
*/
int readxwd(unsigned int *wd, FILE *f)
{
unsigned int value, digit;
int status;
int ch;

#define UWARNLVL (UINT_MAX / 10U)
#define UWARNDIG (UINT_MAX - UWARNLVL * 10U)

value = 0; /* default */
status = 1; /* default error */

ch = ignoreblks(f);

if (EOF == ch) status = EOF;
else if (isdigit(ch)) status = 0; /* digit, no error */

while (isdigit(ch)) {
digit = ch - '0';
if ((value > UWARNLVL) ||
((UWARNLVL == value) && (digit > UWARNDIG))) {
status = 1; /* overflow */
value -= UWARNLVL;
}
value = 10 * value + digit;
ch = getc(f);
} /* while (ch is a digit) */

*wd = value;
ungetc(ch, f);
return status;
} /* readxwd */

--
"The power of the Executive to cast a man into prison without
formulating any charge known to the law, and particularly to
deny him the judgement of his peers, is in the highest degree
odious and is the foundation of all totalitarian government
whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
Jan 31 '06 #7
On Tue, 31 Jan 2006 14:31:31 +0100, serrand <xa************@free.fr>
wrote:
Peter Nilsson wrote:

#define BIG_ENOUGH_FOR_INT \
( (int) (sizeof(int) * CHAR_BIT + 11) / 3) )

( (int) (sizeof(int) * CHAR_BIT + 5) / 3) )
is enough for signed, isn't it?
I wonder why you are using two more places...

That's enough for _unsigned_. Signed requires one more.

But he has two more. In some situations that might allow for a decimal
point (redundant for integer) or a currency symbol, but for just a
number it isn't needed.

- David.Thompson1 at worldnet.att.net
Feb 13 '06 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

7 posts views Thread by JR | last post: by
10 posts views Thread by Doug O'Leary | last post: by
5 posts views Thread by William Payne | last post: by
7 posts views Thread by William L. Bahn | last post: by
99 posts views Thread by Mikhail Teterin | last post: by
27 posts views Thread by Aaron Hsu | last post: by
2 posts views Thread by XIAOLAOHU | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.