473,326 Members | 2,126 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

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

Input Verification

Hello all,

As stated in another message, it's been a long time since I've done any
C coding and I'm not feeling comfortable that I'm doing this correctly.
Basically, I'd like to verify that my supplied input is alphanumeric.
White space and opening/closing parenthesis are also permitted.
Nothing more, nothing less.

Additionally, despite having read my documentation for scanf(), I'm
uncertain how --if it's even possible-- to have a variable input width.
This isn't so much a big deal; but, it would be nice to only have to
modify my symbolic constant rather than keeping track of two maximum
buffer lengths.

Lastly, the code needs to be portable. I understand that there are
probably better platform-specific methods for flushing the input buffer;
however, I'll have to implement these on an individual basis. Assuming
I have no disguised bugs in the FLUSH_IN() macro that you believe I'm
missing, I'm perfectly content with its current implementation.

On a side note, the input will rarely, if ever, actually be supplied by
a user as this is actually planned to be part of an embedded system
project (robot) I'm building in my free time. Ideally, I'll have some
form of GUI or whatever that automatically sends the proper commands
through the serial port. But this is still a good test to get myself
back in the swing of things.

--- Start Code ---
#include <stdio.h>

#define LINE_LIMIT 80
#define MAX_INPUT_SIZE 60
#define PROMPT "%> "

#define FLUSH_IN(fp) do { \
int ch; \
while((ch = fgetc(fp)) != EOF && ch != '\n'); \
} while(0)

void get_command(void);

int main(void)
{
get_command();
return 0;
}

void get_command(void)
{
int ret;
char input[MAX_INPUT_SIZE];

printf("%s", PROMPT);
while ((ret = scanf("%60[a-z[A-Z[0-9[()[ ]", input)) == EOF || ret == 0)
{
printf("Invalid input...\n");
FLUSH_IN(stdin);
}

printf("%s\n", input);
}

--- End Code ---

Any comments are welcome.

Thank you in advance,

--
Sean
Nov 15 '05 #1
3 2813
>As stated in another message, it's been a long time since I've done any
C coding and I'm not feeling comfortable that I'm doing this correctly.
Basically, I'd like to verify that my supplied input is alphanumeric.
White space and opening/closing parenthesis are also permitted.
Nothing more, nothing less.

Additionally, despite having read my documentation for scanf(), I'm
uncertain how --if it's even possible-- to have a variable input width.
Use fgets(). Then you can use a function like the one below to
check the input:

#include <ctype.h>
int verify_input(char *s)
{
/* returns 1 on valid input, 0 on invalid input */
char *p;

for (p = s; *s; s++) {
if(isalnum((unsigned char)*s) ||
isblank((unsigned char) *s) || *s == '('
|| *s == ')' || *s == '\n') {
/* ok */
} else {
return 0; /* invalid input */
}
}
return 1; /* all input was valid */
}

If you read ALL the input from one line, then check it, you don't
have to worry about flushing. You need to allow a newline (or lop
it off beforehand) if you're getting input from fgets(). If you really
need scanf() parsing, use sscanf() on the line you got from fgets().
This isn't so much a big deal; but, it would be nice to only have to
modify my symbolic constant rather than keeping track of two maximum
buffer lengths.

Lastly, the code needs to be portable. I understand that there are
probably better platform-specific methods for flushing the input buffer;
however, I'll have to implement these on an individual basis. Assuming
I have no disguised bugs in the FLUSH_IN() macro that you believe I'm
missing, I'm perfectly content with its current implementation.
If a user typed it, the program should pay attention to it, if only
to parse over it.
On a side note, the input will rarely, if ever, actually be supplied by
a user as this is actually planned to be part of an embedded system
project (robot) I'm building in my free time. Ideally, I'll have some
form of GUI or whatever that automatically sends the proper commands
through the serial port. But this is still a good test to get myself
back in the swing of things.

--- Start Code ---
#include <stdio.h>

#define LINE_LIMIT 80
#define MAX_INPUT_SIZE 60
#define PROMPT "%> "

#define FLUSH_IN(fp) do { \
int ch; \
while((ch = fgetc(fp)) != EOF && ch != '\n'); \
} while(0)
You don't need FLUSH_IN() if you use fgets() for input consistently.

void get_command(void);

int main(void)
{
get_command();
return 0;
}

void get_command(void)
{
int ret;
char input[MAX_INPUT_SIZE];

printf("%s", PROMPT);
while ((ret = scanf("%60[a-z[A-Z[0-9[()[ ]", input)) == EOF || ret == 0)
A significant problem with scanf() for this kind of use is that if
the user types an illegal character after some valid input, it
terminates the valid input immediately. For those familiar with
SQL, this can be a disaster: consider "delete from table where
account = 9749879191873" when you accidentally send the command
right after the 'table' part. Bye, bye data.

I recommend reading all the data, THEN checking it. Especially if
the input can be simply described as "a line of input", with other
constraints to be checked later.
{
printf("Invalid input...\n");
FLUSH_IN(stdin);
}

printf("%s\n", input);
}

--- End Code ---

Any comments are welcome.


Gordon L. Burditt
Nov 15 '05 #2
Gordon Burditt wrote:
As stated in another message, it's been a long time since I've done any
C coding and I'm not feeling comfortable that I'm doing this correctly.
Basically, I'd like to verify that my supplied input is alphanumeric.
White space and opening/closing parenthesis are also permitted.
Nothing more, nothing less.

Additionally, despite having read my documentation for scanf(), I'm
uncertain how --if it's even possible-- to have a variable input width.

Use fgets(). Then you can use a function like the one below to
check the input:


Funny thing is that I actually started out with fgets and opted to go
against it because (for whatever reason) I thought it would be easier
using scanf() since I wouldn't have to remove the trailing '\n'. Little
was I aware that what little I saved by not having to remove one extra
character, lead to an excessive amount of code to verify valid input.
By taking your advise and using fgets(), I don't think it took me more
than 10 - 15 minutes to code all of the necessary parsing code, which,
in the end, worked better than my original scanf() code that took me
about an hour to work on (granted I did have to read the documentation
for scanf() again).

[...]
If you read ALL the input from one line, then check it, you don't
have to worry about flushing. You need to allow a newline (or lop
it off beforehand) if you're getting input from fgets(). If you really
need scanf() parsing, use sscanf() on the line you got from fgets().


Another nice thing about scanf() was the ability to check for valid
input using regular expressions. But, in the end, I determined that I
was doing so much parsing, anyhow, that the benefits of using regular
expressions were almost non-existent.
This isn't so much a big deal; but, it would be nice to only have to
modify my symbolic constant rather than keeping track of two maximum
buffer lengths.

Lastly, the code needs to be portable. I understand that there are
probably better platform-specific methods for flushing the input buffer;
however, I'll have to implement these on an individual basis. Assuming
I have no disguised bugs in the FLUSH_IN() macro that you believe I'm
missing, I'm perfectly content with its current implementation.

If a user typed it, the program should pay attention to it, if only
to parse over it.


Again, I like your advise. Although it's doubtful that anybody other
than I will ever do anything with this robot, it's still good practice.
If this were a product I bought off the shelf, I would certainly hope
that the programmers built some form of validation code.

[...]

Thank you much for your input. I like the new design a lot more than I
did my original.

--
Sean
Nov 15 '05 #3
A few nits in addition to the other (good) answers:

On Wed, 03 Aug 2005 13:44:23 -0400, "Fao, Sean"
<en**********@yahoo.comI-WANT-NO-SPAM> wrote:
#define LINE_LIMIT 80
#define MAX_INPUT_SIZE 60
#define PROMPT "%> " int ret;
char input[MAX_INPUT_SIZE];

printf("%s", PROMPT);
while ((ret = scanf("%60[a-z[A-Z[0-9[()[ ]", input)) == EOF || ret == 0)


To use *scanf %[ or %s or %Nc safely you need a count _one less_ than
the array size: %59[etc] for char input[60]. It's somewhat fragile to
do this with a #define for one (perhaps off in a header file) and the
other written inline; one mildly ugly fix(?) is:

#define MAXIN 60 /* must be a single integer, NOT an expression */

char buff [MAXIN + 1];
#define XSTR(x) #x
#define XSTR2(x) XSTR(x)
.... scanf ("%" XSTR(MAXIN) "[etc]", etc) ...

Note that fgets(), which you report you have already switched to, does
not have this problem: char buf[N] and fgets (buf, N, fd) is correct.

Also, the range notation a-z is NOT standard C although it is a common
extension, and you do NOT use more left-brackets [ to "continue" the
charclass: what you wrote allows (on most implementations) a-z A-Z 0-9
parens space AND left-bracket (redundantly), which is not what you
asked for; to get that you would use %60[a-zA-Z90-9() ] or in standard
%60[abc<etc. to>XYZ0123456789() ]

Also note that "whitespace" in computer terminology, especially
Internet, doesn't mean only the space character, it also includes tab,
carriage-return and linefeed or newline (latter especially in C), and
form-feed and vertical-tab where those exist. If you really meant
"whitespace" add those to your charclass or similar logic; if you've
changed to parsing the fgets'ed line explicitly and use isspace() from
<ctype.h> it already handles all these. If you really meant only
"space" say exactly that for clarity.

- David.Thompson1 at worldnet.att.net
Nov 15 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Boyd Reilly | last post by:
I have a form that has the user pick the type of question he will answer. The input field will be a text, numeric or date type. So, after the question is answered, I need to change the input...
13
by: Stumped and Confused | last post by:
Hello, I really, really, need some help here - I've spent hours trying to find a solution. In a nutshell, I'm trying to have a user input a value in form's textfield. The value should then be...
7
by: SOR | last post by:
Although this currently defeats the spam bots in some respects - isnt it just a mater of time before the spammers figure out a way to verify a signup via email using rotating disposable email...
5
by: google | last post by:
first, a little background... i have a C program which preprocesses some data, and then outputs the results into a text file. that text file, in turn, is used as input to a FORTRAN...
7
by: Hulo | last post by:
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",...
2
by: jackson2005 | last post by:
OK, I need to do three different things. On the ONLOAD event I would like a popup box to open. In this popup box I need two text boxes. One for the UserName and one for the BillingTo name. ...
0
by: pwilliams | last post by:
NCOALink Change of Address Verification Each year over 40 million Americans change their mailing addresses. This change is equivalent to every person in California deciding to change addresses...
13
by: Kal | last post by:
I have a small console app that started out in dotnet 1.1 in VS 2003. That version can be copied to a W2K3 server where it runs fine. I set up a new project in VS 2005 and copied the code files...
5
by: Mike P | last post by:
Does anybody know how to/have an example of using image verification of user input (i.e. the user has to enter the digits in an image as well as the normal input)? *** Sent via Developersdex...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

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.