I was just reviewing C
and I was making a program, I had the problem that when reading data with fgets()
it I had elements left in the standard input for the next reading when the character limit of the string was exceeded, this broke the program very easily. This of course is because it fgets()
only takes the x elements of the input that it needs (where x is : fgets(cadena, x, stdin)
), so if there are more than it needs, they will stay there. I created a solution, it is the following (also add doubly linked lists so that the elements that were left in the buffer would be seen) ...
#include <stdio.h>
#include <stdlib.h>
#define MAX_STR_LEN 5
// estructuras
typedef struct nodo {
int element;
struct nodo* siguiente;
struct nodo* anterior;
} nodo;
typedef struct lista {
nodo *cabeza;
} lista;
// prototipos
void limpiar_buffer();
lista *crear_lista();
nodo *crear_nodo(int element);
void mostrar_lista(lista *lista);
void agregar_elemento(lista *lista,nodo *nuevo_nodo);
void vaciar_lista(lista *lista);
void eliminar_nodo(nodo *nodo_a_eliminar);
void limpiar_buffer(){
char curr_char = getchar();
lista *elementos_restantes = crear_lista();
while ( curr_char != EOF && curr_char != '\n' ){
agregar_elemento(elementos_restantes, crear_nodo(curr_char));
curr_char = getchar();
}
mostrar_lista(elementos_restantes);
vaciar_lista(elementos_restantes);
}
void eliminar_nodo(nodo *nodo_a_eliminar){
nodo_a_eliminar->siguiente = nodo_a_eliminar->anterior = NULL;
free(nodo_a_eliminar);
}
void vaciar_lista(lista *lista){
if ( lista->cabeza == NULL){
// en caso de que no hayan elementos
return;
} else if ( lista->cabeza->siguiente == NULL ){
lista->cabeza = NULL;
} else {
nodo *nodo_actual = lista->cabeza;
nodo *nodo_anterior, *nodo_eliminable;
while ( nodo_actual->siguiente != NULL){
nodo_anterior = nodo_actual;
nodo_actual = nodo_actual->siguiente;
}
// llegamos hasta el final de la lista
while ( nodo_anterior != NULL){
nodo_eliminable = nodo_actual;
nodo_anterior = nodo_anterior->anterior;
nodo_actual = nodo_actual->anterior;
free(nodo_eliminable);
}
// eliminamos todos los elementos menos la cabeza
lista->cabeza = NULL;
}
}
lista *crear_lista(){
lista *nueva_lista = (lista *) malloc(sizeof(lista));
nueva_lista->cabeza = NULL;
return nueva_lista;
}
nodo *crear_nodo(int element){
nodo *nuevo_nodo= (nodo *) malloc(sizeof(nodo));
nuevo_nodo->element = element;
nuevo_nodo->siguiente = nuevo_nodo->anterior = NULL;
return nuevo_nodo;
}
void mostrar_lista(lista *lista){
if ( lista->cabeza == NULL ){
return;
} else {
nodo *nodo_actual = lista->cabeza;
printf("\n Elementos que quedaron en el buffer -> [ ");
while ( nodo_actual != NULL ){
if ( nodo_actual->siguiente != NULL ){
printf("%c, ", nodo_actual->element);
} else {
printf("%c ", nodo_actual->element);
}
nodo_actual = nodo_actual->siguiente;
}
printf(" ]\n");
}
}
void agregar_elemento(lista *lista,nodo *nuevo_nodo){
if ( lista->cabeza == NULL ){
lista->cabeza = nuevo_nodo;
lista->cabeza->siguiente = NULL;
lista->cabeza->anterior = NULL;
} else {
nodo *nodo_actual = lista->cabeza;
nodo *nodo_anterior;
while ( nodo_actual != NULL ){
nodo_anterior = nodo_actual;
nodo_actual = nodo_actual->siguiente;
}
nodo_anterior->siguiente = nuevo_nodo;
nodo_anterior->siguiente->anterior = nodo_anterior;
nodo_anterior->siguiente->siguiente = NULL;
}
}
int main(){
char cadena[MAX_STR_LEN];
while (1){
printf("Introduce tu nombre completo -> ");
fgets(cadena, MAX_STR_LEN, stdin);
printf("Tu nombre completo es %s\n", cadena);
limpiar_buffer();
}
return 0;
}
In case you have any suggestions for improving the code, I'm all ears. The problem is that when the character limit is not exceeded when reading ( MAX_STR_LEN
), for some reason the program stops and you have to hit again to enter
continue... Any explanation? Obviously it has something to do with the function limpiar_buffer
I use to run the cursor again at the end of the standard input... Thanks in advance :)
If it reads correctly,
stdin
there won't be a\n
, so your clean buffer function will remove a line that was valid input. All you have to do is check if the reading was correct using a function like this:Now when you read you do: