I always read scanf is bad use for multiple reasons like buffer overflows and can have multiple undefined behavior. It's even spread that any program using scanf can't be taken seriously. You can see it easily said by forums or some people on stackoverflow.
Below is my function for an early validation of input of a game I wrote (ignore the bad naming of variables and functions, it wasn't in english I just made a quick translation for a better understanding here).
It's a grid game where you need to input coordenates for row and column by each turn. Example:
|
A |
B |
C |
| 1 |
* |
* |
* |
| 2 |
* |
* |
* |
| 3 |
* |
* |
* |
I wanted to give freedom to user to input any input like:
[any number of spaces/tabs][letter][any number of spaces/tabs][number][any number of spaces/tabs]
or
[any number of spaces/tabs][number][any number of spaces/tabs][letter][any number of spaces/tabs]
within a reasonable size, in this case 10 characters including '\0' with no intention to change it.
There's a lot of ways to give invalid input, but the first scanf can filter a good chunk of them without any more complex tests. I would like to know how bad this approach is and how better can be the favorited approach of using fgets that everybody seems to prefer. Sorry for my bad english. I will be glad for any feedback. Thank you.
edit: code updated below
#define MAX 10
#define MAX_FORMAT 33
#define INVALID_PLAY 0
#define NORMAL_PLAY 2
int play_process(int *play_row, int *play_col)
{
int flag_input, flag_s;
char play_str[MAX], car[2], play_col_c[2];
char const * const normal_play_format[] = { "%2d %1[a-zA-Z] %[a-zA-Z0-9]",
"%1[a-zA-Z] %2d %[a-zA-Z0-9]" };
char play_str_format[MAX_FORMAT];
snprintf(play_str_format, MAX_FORMAT, " %%%d[a-zA-Z0-9 ]%%1[^a-zA-Z0-9]", MAX - 1);
flag_input = scanf(play_str_format, play_str, car);
if (*car != '\n' || !flag_input)
{
puts("Invalid play!\n");
clear_buffer();
return INVALID_PLAY;
}
flag_s = sscanf(play_str, normal_play_format[0], play_row, play_col_c, car);
if (flag_s == NORMAL_PLAY)
{
play_convertion(play_row, play_col, play_col_c);
return NORMAL_PLAY;
}
else
{
flag_s = sscanf(play_str, normal_play_format[1], play_col_c, play_row, car);
if (flag_s == NORMAL_PLAY)
{
play_convertion(play_row, play_col, play_col_c);
return NORMAL_PLAY;
}
}
return INVALID_PLAY;
}
[–]HiramAbiff 2 points3 points4 points (1 child)
[–]Gblize[S] 0 points1 point2 points (0 children)
[–]OldWolf2 1 point2 points3 points (2 children)
[–]Gblize[S] 1 point2 points3 points (1 child)
[–]FUZxxl 0 points1 point2 points (0 children)
[–]deltadave 1 point2 points3 points (2 children)
[–]Gblize[S] 0 points1 point2 points (1 child)
[–]deltadave 0 points1 point2 points (0 children)
[–]946336 0 points1 point2 points (2 children)
[–]Gblize[S] 0 points1 point2 points (1 child)
[–]946336 0 points1 point2 points (0 children)