Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Only number input thru scanf()

Reply
Thread Tools

Only number input thru scanf()

 
 
Sandy Beech
Guest
Posts: n/a
 
      11-02-2010
Hello,

I want to restrict the input from the user only to numbers. How can i
do that with scanf()? Is there any other way i can do that ? Also i want
the scanf() to accept even the carriage return without entering
anything. How can i acheive that? Please help me out.
 
Reply With Quote
 
 
 
 
Michael Angelo Ravera
Guest
Posts: n/a
 
      11-02-2010
On Nov 2, 2:42*pm, Sandy Beech <(E-Mail Removed)> wrote:
> Hello,
>
> *I want to restrict the input from the user only to numbers. How can i
> do that with scanf()? Is there any other way i can do that ? Also i want
> the scanf() to accept even the carriage return without entering
> anything. How can i acheive that? Please help me out.


You need to create a specialized entry function or do something OS
specific in order to restrict input. In most cases, these specialized
entry functions simply ignore and refuse to echo input characters that
are not appropriate for the type of data input (and maybe even beep,
flash, or shout, if the user types something else).

In any case, scanf() is not your friend on this. I'm not saying that
you can't do what you want with some repeated and creative application
of scanf(), but scanf() certianly isn't written for this purpose.

 
Reply With Quote
 
 
 
 
Felix Palmen
Guest
Posts: n/a
 
      11-02-2010
* Sandy Beech <(E-Mail Removed)>:
> I want to restrict the input from the user only to numbers. How can i
> do that with scanf()? Is there any other way i can do that ? Also i want
> the scanf() to accept even the carriage return without entering
> anything. How can i acheive that? Please help me out.


You can't. Either check user input later, optionally telling the user
what went wrong and letting him repeat the input, or sacrifice
portability and do it yourself, using things like conio on windows or
raw terminal mode on *nix.

Regards,
Felix

--
Felix Palmen (Zirias) + [PGP] Felix Palmen <(E-Mail Removed)>
web: http://palmen-it.de/ | http://palmen-it.de/pub.txt
my open source projects: | Fingerprint: ED9B 62D0 BE39 32F9 2488
http://palmen-it.de/?pg=pro + 5D0C 8177 9D80 5ECF F683
 
Reply With Quote
 
Peter Nilsson
Guest
Posts: n/a
 
      11-03-2010
Sandy Beech <(E-Mail Removed)> wrote:
> *I want to restrict the input from the user only to numbers.
> How can i do that with scanf()?


Effectively, you can't.

> Is there any other way i can do that ? Also i want
> the scanf() to accept even the carriage return without
> entering anything.


Use fgets, then sscanf, or better still strtol.

--
Peter
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      11-03-2010
Sandy Beech <(E-Mail Removed)> writes:
> I want to restrict the input from the user only to numbers. How can i
> do that with scanf()? Is there any other way i can do that ? Also i want
> the scanf() to accept even the carriage return without entering
> anything. How can i acheive that? Please help me out.


What exactly do you mean by "restrict"? If the user types something
other than a number, what should happen?

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Peter 'Shaggy' Haywood
Guest
Posts: n/a
 
      11-03-2010
Groovy hepcat Felix Palmen was jivin' in comp.lang.c on Wed, 3 Nov 2010
9:17 am. It's a cool scene! Dig it.

> * Sandy Beech <(E-Mail Removed)>:
>> I want to restrict the input from the user only to numbers. How can i
>> do that with scanf()? Is there any other way i can do that ? Also i
>> want the scanf() to accept even the carriage return without entering
>> anything. How can i acheive that? Please help me out.

>
> You can't.


Nonsense! You certainly can do that. Of course, scanf() may not be the
best function for the job. The OP should read the FAQ for more on this.
I'd maybe use fgets() followed by sscanf(). This would also provide a
trivial way to determine whether the input contains only a newline.
But to give you some idea what can be done using only scanf() for
input, consider the following code:

#include <stdio.h>

int main(void)
{
int nfields, num;
char dummy[2];

fputs("Please enter a decimal integer: ", stdout);
fflush(stdout);

nfields = scanf("%d%1[^\n]", &num, dummy);
while(1 != nfields)
{
puts("Invalid input! Please try again.");
fputs("Enter a decimal integer (and nothing else): ", stdout);
fflush(stdout);

/* Consume remaining line of input. */
while(0 != scanf("%*[^\n]"))
;

nfields = scanf("%d%1[^\n]", &num, dummy);
}

printf("num = %d\n", num);
}

This code first prompts for a number, then attempts to read in two
fields: a decimal integer and a single character that is not a newline
(as indicated by the %1[^\n] conversion specifier). However, we want it
to fail to read the second field. There are several scenarios that can
be encountered:

1) no fields are read in, meaning there are no digits at the start of
the input, scanf() returns 0, and we enter the loop to try again (after
consuming the remaining line of input so we don't get stuck in an
endless loop);

2) a numerical field and an extra character field are read in, meaning
there are digits at the start of the input but there is some non-digit
character(s) after that, scanf() returns 2, and the loop is entered to
try again;

3) a numerical field is read, but no other characters are present, and
scanf() returns 1, meaning that only digits were entered, which is what
we want, so we don't enter the loop.

The last printf() statement then tells us what number was entered, and
the program ends.
To determine whether a newline has been entered is also trivial using
scanf(). The %c conversion specifier reads the next character, even if
it is white space. Regardez:

char ch;
scanf("%c", &ch);
if('\n' == ch)
{
/* Newline has been entered. */
}

Or you could use the %1[\n] conversion specifier to force scanf() to
read only a single newline. Note that this treats the input as a
string, even if it is only one character long (which it will be since
any character other than a single newline will be rejected), so you
need an array of at least two bytes (for the input and null).

char s[2];
if(1 == scanf("%1[\n]", s))
{
/* Newline has been entered. */
}

--
Dig the sig!

----------- Peter 'Shaggy' Haywood ------------
Ain't I'm a dawg!!
 
Reply With Quote
 
David RF
Guest
Posts: n/a
 
      11-03-2010
On 2 nov, 22:42, Sandy Beech <(E-Mail Removed)> wrote:
> Hello,
>
> *I want to restrict the input from the user only to numbers. How can i
> do that with scanf()? Is there any other way i can do that ? Also i want
> the scanf() to accept even the carriage return without entering
> anything. How can i acheive that? Please help me out.


If you are under a unix shell you can use termios

A little example (never tested in real production, any advice is
welcomed)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <termios.h>
#include <unistd.h>

#define KEY_TAB 0x0009 /* 9 */
#define KEY_ENTER 0x000a /* 10 */
#define KEY_ESCAPE 0x001b /* 27 */
#define KEY_BACKSPACE 0x007f /* 127 */

#define KEY_DELETE 0x0100 /* 256 */
#define KEY_HOME 0x0101
#define KEY_END 0x0102
#define KEY_REPAG 0x0103
#define KEY_AVPAG 0x0104
#define KEY_UP 0x0105
#define KEY_DOWN 0x0106
#define KEY_LEFT 0x0107
#define KEY_RIGHT 0x0108

/* Macros terminal */
#define cursorforward(x) printf("\033[%dC", (x))
#define cursorbackward(x) printf("\033[%dD", (x))
#define savecursor() printf("\033[s")
#define unsavecursor() printf("\033[u")
/* END Macros terminal */

static struct termios term, oterm;

static int getch(void);
static int kbhit(void);
static int kbesc(void);
static int kbget(void);

static int getch(void)
{
int c = 0;

tcgetattr(0, &oterm);
memcpy(&term, &oterm, sizeof(term));
term.c_lflag &= ~(ICANON | ECHO);
term.c_cc[VMIN] = 1;
term.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &term);
c = getchar();
tcsetattr(0, TCSANOW, &oterm);
return c;
}

static int kbhit(void)
{
int c = 0;

tcgetattr(0, &oterm);
memcpy(&term, &oterm, sizeof(term));
term.c_lflag &= ~(ICANON | ECHO);
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 1;
tcsetattr(0, TCSANOW, &term);
c = getchar();
tcsetattr(0, TCSANOW, &oterm);
if (c != -1) ungetc(c, stdin);
return ((c != -1) ? 1 : 0);
}

static int kbesc(void)
{
int c;

if (!kbhit()) return KEY_ESCAPE;
c = getch();
if ((c == '[') || (c == 'O')) {
switch (getch()) {
case 'A':
c = KEY_UP;
break;
case 'B':
c = KEY_DOWN;
break;
case 'C':
c = KEY_LEFT;
break;
case 'D':
c = KEY_RIGHT;
break;
case 'F':
c = KEY_END;
break;
case 'H':
c = KEY_HOME;
break;
case '1':
if (getch() == '~') c = KEY_HOME; else c = 0;
break;
case '3':
if (getch() == '~') c = KEY_DELETE; else c = 0;
break;
case '4':
if (getch() == '~') c = KEY_END; else c = 0;
break;
case '5':
if (getch() == '~') c = KEY_REPAG; else c = 0;
break;
case '6':
if (getch() == '~') c = KEY_AVPAG; else c = 0;
break;
default:
c = 0;
break;
}
} else {
c = 0;
}
if (c == 0) while (kbhit()) getch();
return c;
}

static int kbget(void)
{
int c;

c = getch();
return (c == KEY_ESCAPE) ? kbesc() : c;
}

char *inputfn(size_t size, int (*fn)(int))
{
int c, pos = 0, len = 0;
char *entry;

entry = calloc(size + 1, sizeof(char));
if (entry == NULL) {
fprintf(stderr, "Aargh ...");
exit(EXIT_FAILURE);
}
for (; {
c = kbget();
if (
c == KEY_ENTER || c == KEY_ESCAPE ||
c == KEY_TAB || c == KEY_REPAG || c == KEY_AVPAG ||
c == KEY_UP || c == KEY_DOWN
) break;
if (c == KEY_BACKSPACE) {
if (pos > 0) {
pos--;
putchar('\b');
c = KEY_DELETE;
} else continue;
}
if (c == KEY_DELETE) {
if (pos < len) {
memmove(&entry[pos], &entry[pos + 1], (size_t)(len - pos));
len--;
savecursor();
printf("%s ", &entry[pos]);
unsavecursor();
}
} else
if (c == KEY_HOME) {
if (pos > 0) {
cursorbackward(pos);
pos = 0;
}
} else
if (c == KEY_END) {
if (pos < len) {
cursorforward(len - pos);
pos = len;
}
} else
if (c == KEY_RIGHT) {
if (pos > 0) {
pos--;
putchar('\b');
}
} else
if (c == KEY_LEFT) {
if (pos < len) {
putchar(entry[pos++]);
}
} else
if (fn && fn((unsigned char)c)) {
/* Si es el primer caracter de la cadena borra todo */
/* if first char delete all */
if (pos == 0 && len > 1) {
memset(entry, 0, (size_t)len);
savecursor();
printf("%*s", len, "");
unsavecursor();
len = 0;
}
if (pos == len) {
if (len == size) continue;
len++;
}
entry[pos++] = (char)c;
putchar(c);
}
}
return entry;
}

int main(void)
{
char *entry;

printf("Input number: ");
entry = inputfn(5, isdigit);
/* where 5 is max input and isdigit a filter (you can use any ctype
or you own) */
printf("\nYour number is %s\n", entry);
free(entry);

return 0;
}
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      11-06-2010
Peter 'Shaggy' Haywood <(E-Mail Removed)> writes:
> Groovy hepcat Felix Palmen was jivin' in comp.lang.c on Wed, 3 Nov 2010
> 9:17 am. It's a cool scene! Dig it.
>
>> * Sandy Beech <(E-Mail Removed)>:
>>> I want to restrict the input from the user only to numbers. How can i
>>> do that with scanf()? Is there any other way i can do that ? Also i
>>> want the scanf() to accept even the carriage return without entering
>>> anything. How can i acheive that? Please help me out.

>>
>> You can't.

>
> Nonsense! You certainly can do that. Of course, scanf() may not be the
> best function for the job. The OP should read the FAQ for more on this.

[snip]

It depends on just what the OP is trying to accomplish. In particular,
it depends on what the OP means by "restrict". (I asked, and I haven't
seen a response.)

Here's an example of something the OP *might* have meant, something
that can't be done in portable and/or standard C. I once wrote a
numeric input routine that would accept only well-formed numeric
input. If the user typed a character that could not be part of
a number, it was discarded, not even echoed. For example, if the
user typed "12xyz34", only "1234" would appear on the screen, and
the input value would be 1234.

If you're not going to play that kind of trick to disallow invalid
input, you have to decide how to respond when the user enters something
other than a number. I suspect the OP hasn't thought about that.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
David Thompson
Guest
Posts: n/a
 
      11-16-2010
On Wed, 03 Nov 2010 19:27:29 +1100, Peter 'Shaggy' Haywood
<(E-Mail Removed)> wrote:

> But to give you some idea what can be done using only scanf() for
> input, consider the following code:


> nfields = scanf("%d%1[^\n]", &num, dummy);
> while(1 != nfields)
> {
> puts("Invalid input! Please try again.");
> fputs("Enter a decimal integer (and nothing else): ", stdout);
> fflush(stdout);
>

Loops infinitely for persistent I/O error or EOF -- although this
clearly is intended only to handle input from an interactive device
like a keyboard, and keyboard EOF often (usually?) isn't sticky.
(Also the message wording might be off for this case.)

> /* Consume remaining line of input. */
> while(0 != scanf("%*[^\n]"))
> ;
>

Don't need while, just one call since %dftwidth[ = unbounded.
(Like %s but unlike %c which defaults to 1.)

> nfields = scanf("%d%1[^\n]", &num, dummy);
> }
>

Personally I would either put the repeated scanf attempt in the while
condition, or make this an n.5 loop explicitly (with break), rather
than duplicating the code. But that's 'merely' style.

> printf("num = %d\n", num);
> }
>

<snip rest>
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Order notes starting at C thru B rather than A thru G Max Williams Ruby 3 01-06-2009 11:37 AM
RDP thru Cisco VPN client and thru 501 Failure curttampa@gmail.com Cisco 21 08-26-2008 03:11 PM
Can't access Web Service thru DLL (but can thru Windows App) THTB ASP .Net Web Services 0 05-17-2007 06:43 PM
why does form with only 1 text input and 1 button input submit on enter? Guy HTML 5 12-13-2003 06:44 AM
Reading Input thru console (strange error?) perpetuallyfrozen Java 6 10-02-2003 06:04 AM



Advertisments