Given that you want to recognize 2 7 A BUL
, you cannot safely use:
int e,m;
char id[1], modelo[3];
sscanf(frase[i], "%d %d %s %s", &e, &m, &id, &modelo);
First, you shouldn't pass char (*)[]
values where a char *
is expected; do not take the address of an array; pass id
and modelo
only. GCC will warn you about that if you turn on warnings. If you're learning C, you can't afford not to have the warnings turned on (use -Wall
at minimum; -Wall -Wextra
if at all possible).
Next, the first %s
will read an arbitrary number of characters and null-terminate the result. This is going to overwrite the end of the id
array. And you can't safely read 3 characters into modelo
either. Because of this, you have two stack overflow problems.
You should write either:
int e, m;
char id[2], modelo[4];
if (sscanf(frase[i], "%d %d %1s %3s", &e, &m, id, modelo) != 4)
...oops...
or perhaps:
int e, m;
char id;
char modelo[4];
if (sscanf(frase[i], "%d %d %c %3s", &e, &m, &id, modelo) != 4)
...oops...
Or, you could use char id[1];
and %c
, but that is dangerous; the result is not a null-terminated string.
Your primary input loop is suspect too. You can use feof()
as you did, immediately after the fgets()
, but it is much more conventional to test the result of fgets()
itself; it tells you whether it succeeded or not. That code should probably be:
char frase[20][12];
for (int linha = 0; i < sizeof(frase) / sizeof(frase[0]); i++)
{
if (fgets(frase[linha] ,sizeof(frase[linha]), stdin) == 0)
break;
}
This avoids repeating the 20 or the 12 but protects you from too many lines. It does not protect you from overlong lines; you could add:
size_t len = strlen(frase[linha]);
assert(len != 0);
if (frase[len-1] != '\n')
...input was too long...
to the loop.
You could also think about doing the sscanf()
and call to enfila()
in the main input loop; you would not then need the frase
array to be multi-dimensional.
Putting all the changes together:
char frase[4096];
while (fgets(frase, sizeof(frase), stdin) != 0)
{
int e;
int m;
char id[2];
char modelo[4];
if (sscanf(frase, "%d %d %1s %3s", &e, &m, id, modelo) == 4)
enfila(e, m, id, modelo, l); // l is the parameter to the function
else
...report error...
}
Using fgets()
and sscanf()
was definitely the correct way to go. It means that error reporting can show the whole line of input, rather than whatever mangled remains scanf()
left behind as unreadable.