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;
}