472,958 Members | 2,584 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,958 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 2595
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: JR | last post by:
Hey all, I have read part seven of the FAQ and searched for an answer but can not seem to find one. I am trying to do the all too common verify the data type with CIN. The code from the FAQ...
10
by: Doug O'Leary | last post by:
Hey, all. I have a perl script which generates the html listed below. I cleaned it up a bit since the perl CGI module creates some really ugly html code. I've looked at this thing 8 ways to...
5
by: William Payne | last post by:
Hello, I am in the process of converting a C++ program to a C program. The user of the program is supposed to supply an integer on the command line and in the C++ version of the program I was using...
7
by: William L. Bahn | last post by:
I recently challenged one of my students to figure out a way to determine if fgets() actually received the entire contents of the input string. When he was having trouble figuring it out even after...
99
by: Mikhail Teterin | last post by:
Hello! Consider the following simple accessor function: typedef struct { int i; char name; } MY_TYPE; const char *
16
by: lawrence k | last post by:
I've made it habit to check all returns in my code, and usually, on most projects, I'll have an error function that reports error messages to some central location. I recently worked on a project...
1
by: halcyon943 | last post by:
have 4 folders that I watch and need to move files from to another location. Three constraints: -Finish time. Make sure the program stops transferring files at a specific time -Number of...
2
by: jou00jou | last post by:
Hi, I have trouble using sscanf and fgets to check for overflow. I will post the assignment specification so I could help whoever would kindly like to offer his/her help. ...
27
by: Aaron Hsu | last post by:
Hey all, After seeing the Secure version I/O functions thread, it occured to me that maybe not everyone agrees with the almost universal adage that I have heard. I have Always been told that...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
3
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
2
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

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.