Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - AlbertoBSD

#411
Tengo que decirles que después de meditarlo un poco, encontre la solución, se puede deducir leyendo la memoria que acabamos de leer, esto en el caso de Usar Fgets  ;-) ;-)

Si bien han usado en su momento fgets, recordaran que este guarda en la misma cadena que acaba de leer el "Enter" esto es un byte de valor 0xA (10 en decimal)

Esto siempre y cuando la longitud del texto leído no supere el tamaño del arreglo donde vamos a guardar nuestra cadena leida.

Vemos un ejemplo con Codigo:


#include<stdio.h>
#include<string.h>

int main() {
int len,i = 0;
char temporal[10];
printf("Ingrese una cadena: ");
fgets(temporal,10,stdin);
len = strlen(temporal);
printf("Cadena Leida: %s",temporal);
printf("La longitud de la cadena leida es de %i\n",len);
while(i<10) printf("%.2X",temporal[i++]);
printf("\n");
}



Aqui unas cuantas salidas.



1er caso de la imagen: ingresar mas de 9 letras "A", obvio hay datos en el buffer de stdin esperando ser leeidos,
2do caso de la imagen: Al ingresar exactamente 9 letras A, el ultimo byte del buffer el byte 10 es el valor nulo '\0' En este caso queda un Enter en el buffer de datos de stdin
3er caso de la imagen: Al ingresar exactamente 8 letras A, strlen sigue considerando 9 espacios usados ya que el Enter (0xA) esta el la posición temporal[8] y en temporal[9] esta el byte nulo '\0'
4to caso de la imagen: Al ingresar exactamente 7 letras A, strlen marca una longitud de 8 espacios mismo caso que el anterior sigue considerando el "Enter" como un valor valido de la cadena.

En conclusión, si al usar fgets correctamente, el valor de nuestro arreglo en su posición strlen(temporal) - 1 es igual 0xA entonces no queda nada en nuestro buffer de STDIN, en caso contrario si queda Algo, ya sea solo el Enter o Texto restante + Enter.

En cualquier caso después de realizar esta evaluación si detectamos el caso de que aun quede buffer pendiente por leer, podemos leerlo asi:

while ((c = getchar()) != 0xA);


Saludos
#412
Solución

Se encontraron 2 soluciones

  • Detectar en la memoria previamente leida por fgets si el buffer de destino tiene el retorno de linea, si esi ya no hay nada en STDIN, en caso contrario aun quedan datos.
  • realizar fseek al stdin para que avance hasta el final del archivo. (Solucion gracias a MAFUS)


    #include<stdio.h>
    #include<string.h>

    int main() {
    int len,i = 0;
    char temporal[10];
    char c;
    printf("Ingrese una cadena: ");
    fgets(temporal,10,stdin);
    printf("Cadena Leida: %s\n",temporal);
    len = strlen(temporal);
    if(temporal[len - 1 ]  != 0xA) {
    while ((c = getchar()) != 0xA);
    }
    printf("Ingrese otra cadena: ");
    fgets(temporal,10,stdin);
    printf("Cadena Leida: %s\n",temporal);
    }



    con fseek:


    #include <stdio.h>
         
        int main() {
            char c;
            while(1) {
                printf("> ");
                c = getchar();
                fseek(stdin, 0, SEEK_END);
                printf("Caracter: %c\n", c);
            }
        }




    Post Original

    Muy buen dia aun que la pregunta en el titulo de este post parece una pregunta totalmente N00b. No lo es.

    El objetivo del post es Dejar de utilizar fflush

    fflush(stdin);

    Yo no lo utilizo, o por lo menos trato de nunca recomendarlo, solo que ayer se lo recomendé a alguien y no me convence su implementación.  :silbar:

    La verdad es que quiero dar por terminado el tema de la función fflush para el Buffer de entrada.

    Todo esto en Lenguaje C  ;-)

    La idea de este post viene de preguntas hechas en el foro similares a ¿Como filtrar todo tipo de datos de entrada en un programa?

    Revisando algunas links en internet me encuentro con:
    https://es.stackoverflow.com/questions/82431/saber-si-el-b%C3%BAfer-de-entrada-stdin-est%C3%A1-vac%C3%ADo-en-c-est%C3%A1ndar
    http://man7.org/linux/man-pages/man3/fflush.3.html
    http://www.cplusplus.com/reference/cstdio/fflush/

    Sin embargo en todos ellos hablan de que el comportamiento de fflush para el stdin es Inesperado, por lo cual repetidamente dicen que no se debe de usar.

    ¿Cual es la solución para limpiar el buffer de entrada, si es que realmente queda algo en el?

    Intente con feof, sin embargo al parecer NUNCA llega el fin del archivo para STDIN

    #include<stdio.h>
    #include<string.h>

    int main() {
    char temporal[10];
    printf("Ingrese menos de 10 o mas de 10 caracteres\npara ver el comportamiento de feof(stdin): ");
    fgets(temporal,10,stdin);
    temporal[strcspn(temporal,"\n\r")] = '\0';
    printf("Valor leido %s\n",temporal);
    if(feof(stdin)) {
    printf("stdin llego al final del archivo\n");
    }
    else {
    printf("stdin NO llego al final del archivo\n");
    }
    }


    El problema de todo esto radica que cuando estamos leyendo multiples valores desde el teclado, aun que lo delimitemos con fgets para la cantidad de datos que se guardaran en cada variable, el fgets , al igual que otras funciones de entrada deja los caracteres restantes en el buffer de entrada y son tomados automaticamnete por cualquier funcion de entrada de texto.




    Como ven en la imagen, en la segunda entrada de las AAAAAAAAAAAAA, se salto el segundo "Ingrese una cadena."

    #include<stdio.h>
    #include<string.h>

    int main() {
    char temporal_1[10];
    char temporal_2[10];
    printf("Ingrese una cadena: ");
    fgets(temporal_1,10,stdin);
    temporal_1[strcspn(temporal_1,"\n\r")] = '\0';
    printf("Ingrese una cadena: ");
    fgets(temporal_2,10,stdin);
    temporal_2[strcspn(temporal_2,"\n\r")] = '\0';
    printf("Valor leido %s\n",temporal_1);
    printf("Valor leido %s\n",temporal_2);
    }


    Este problema tambien se presenta en C++ con funciones de entrada tipo cin>>

    Ejemplo:



    Codigo:

    Código (cpp) [Seleccionar]
    #include<iostream>

    using namespace std;
    int main() {
    int numero_1,numero_2;
    cout<<"Ingrese un numero: ";
    cin>>numero_1;
    cout<<"Ingrese un numero: ";
    cin>>numero_2;
    cout<<"Valor leido "<<numero_1<<endl;
    cout<<"Valor leido "<<numero_2<<endl;
    }


    Entonces pregunto:

    ¿Cual es la solución para limpiar el buffer de entrada, si es que realmente queda algo en el?
    ¿Como se si es que realmente queda algo en el buffer de entrada, sin consumirlo.?



    https://albertobsd.blogspot.com/2018/11/queda-algo-en-el-buffer-de-entrada-stdin.html
#413
Seguramente es por que la variable Suma, solo se inicializa antes del ciclo, y no dentro de el mismo.

Asi en la segunda vuelta su valor ya no es  0 antes de hacer cualquier calculo.

saludos!
#414
En teoría eso datos son públicos y conociendo el formato no debe de existir problema en leerlo.

En lo personal no he trabajado con ese tipo de archivos pero debe de existir un Documento que te indique en donde se encuentra cada campo dentro del archivo.

Saludos
#415
Cita de: aimnotabot en 24 Noviembre 2018, 13:10 PM
Ese tipo de filtros si sabía hacerlos, pero me gustaria hacer uno sencillo para todo carácter que no sea un número positivo. Por ejemplo, imagina que el usuario introduce una arroba, un guión o un símbolo de dollar. ¿Si se pudiese hacer de manera sencilla como lo haria?

Lo que aimnotabot necesita es otro lenguaje de programación. Que tenga una funcion magica que sea inteligente y pasa de precedir cualquier input......, O espera esto es C y C++ puedes programar una funcion que haga cualquier cosa!!!!

Puedes usar todas las respuestas que ya te dieron y meterlas en una funcion creada por ti que se adapte a tus necesidades.

Realmente el C basico no hay manera facil de hacerlo, tal vez con C++ y varias de sus funciones como las que te mencionan de regex en el primero reply, podrías lograr algo mas sencillo, pero si seria de investigar un poco mas ya que hay muchas funciones "nuevas" que no conozco de C++.

Cita de: Rave1996 en 24 Noviembre 2018, 04:38 AM
Tu mejor opción sería emplear expresiones regulares (regex).

Puedes consultar la siguiente fuente donde viene bastante información...


El mejor de los casos que seria programar una función que haga lo que quieres de una forma que tu comprendas.


int i;
i = funcion_leer("Ingrese un numero positivo\n",CONSTANTE_PARA_POSITIVOS);


Y por otro lado tendrias.


int funcion_leer(char *s,int tipo) {
int valor;
int entrar_1 = 1;
int entrar_2 = 1;
char temporal[50];
char *ptr;
do {
entrar_2 = 1;
do{
printf(s);
fgets(temporal,50,stdin);
fflush(stdin);
valor = strtol(temporal,&ptr,10);
switch(ptr[0]) {
case '\n':
case '\r': //No recuardo cual de los 2 es el bueno, esto depende del sistema operativo segun recuerdo, favor de corregirme si estoy en un error
case '\0':
entrar_2 = 0; //Salimos por que la cadena no tiene caracteres extraños
break;
default:
break;
}
}while(entrar_2);//De aqui no salimos hasta que strtol confirme que no tenemos ningun caracter raro, esto es cuando ptr apunte solo a '\r' o '\n' o '\0';
switch(tipo){ //Ahora evaluamos que el dato sea lo que buscamos
case NUMERO_ENTERO: //Cualquier Numero
entrar_1 = 0;
break;
case NUMERO_NATURAL: // > 0
if(valor > 0) {
entrar_1 = 0;
}
break;
case NUMERO_NEGATIVO:
if(valor < 0) {
entrar_1 = 0;
}
break;
case NUMERO_PAR:
if(valor %2 == 0) {
entrar_1 = 0;
}

break;
case NUMERO_IMPAR:
if(valor % 2 == 1) {
entrar_1 = 0;
}
break;
//etc...
}
}while(entrar_1);
return valor;
}


Obviamente tienes que tener declaradas X cantidad de constantes, no es algo tan sencilla la funcion completa, pero es lo mejor validado que podrás encontrar.

Aqui esta el ejemplo de salida.




Saludos
#416
Bases de Datos / Re: Defina el termino relacion
24 Noviembre 2018, 13:41 PM
Si lo quieres ver de esa manera es algo asi. La tupla seria seria como una lista ligada de registros que son elementos de un struct, los valores serian los campos de dicho struct. Y las relaciones entre ellos si es que las hay serian... no se un valor o campo "Genero" de una tupla  llamada "Empleado" que tenga posibles valores de uno y dos, uno para Femenino y dos para Masculino. Entonces existe una Tupla llamada Genero que contiene los valores antes mencionados.

Nos podriamos poner mas estrictos y realizar una tupla para campo una para puros nombres, una para puros apeidos, una para nombres de puestos de trabajo. Etc... y al final cada una de estas tendria una relacion con la Tupla de Empleados, la cual solo terminaria guardando puros numeros que indicarian el index del registro en las otras tuplas
#417
Bases de Datos / Re: Defina el termino relacion
24 Noviembre 2018, 08:20 AM
Hola

Es la teoria del Modelo relacional de las Bases de Datos, en lenguaje matematico.

https://es.m.wikipedia.org/wiki/Modelo_relacional
https://es.m.wikipedia.org/wiki/Tupla

Imaginate a las Tuplas como Tablas y los Valores como los campos de dicha tabla.

Ahora hay un conjunto de Relaciones entre las tablas. A1 A2 ...

Al decir de un Ejemplo o formalice un Esquema de relacion puedes Dar un ejemplo de una base de datos con N tablas y como se relacionan entre ellas.

Saludos, No tienes algun texto de bases de datos como Guia?
#418
La forma correcta de realizar esto es procesar todo como texto o cadena de carectares al momento de la entrada y procesar los tipos de datos directamente con las funciones apropias como strtol o strtof

Codigo para C


int dato_entero;
float dato_flotante;
char temp[10];
//Capturamos variable_entera
do {
printf("Capture variable_entera: ");
fgets(temp,10,stdin);
dato_entero= strtol(temp,NULL,10); //Solo procesamos numeros BASE 10

/*En la funcion anterior se pude cambiar el NULL, por un apuntador y asi deteminar en que momento se para la funcion strtol, si el apuntador Apunta, a un '\n' significa que leyo hasta un Enter, si apunta a alguna letra o simbolo significa que trataron de ingresar caracteres distintos a los esperados*/

}while(dato_entero >= 0); // Salimos del DO solo si el valor leido es negativo


do {
printf("Capture variable_flotante: ");
fgets(temp,10,stdin);
dato_flotante= strtof(temp,NULL);

/*En la funcion anterior se pude cambiar el NULL, por un apuntador y asi deteminar en que momento se para la funcion strtol, si el apuntador Apunta, a un '\n' significa que leyo hasta un Enter, si apunta a alguna letra o simbolo significa que trataron de ingresar caracteres distintos a los esperados*/



}while(dato_flotante == 0.0); // Salimos del DO solo si el valor leido distinto de 0


Para C++ deben de existir formas diferentes de procesarlos datos
#419
No te deja hacer el delete directamente?


delete(temp);


Y como comentario no existe tal cosa como LENGUAJE VISUAL STUDIOS 2017 C++.
Es C o C++.
Ya aparte mencionar el IDE en este caso se entiende que es Visual Studio.

Saludos!
#420
Hola que tal , es un poco inexacto lo que haces.

Si te interesa el programa funcional date una vuleta por este tema:

Plantillas programas escolares en C

Los errores de tu codigo acontinuacion:

struct registro {
char nombre[100];
int numpaciente;
char obraSocial[50];
};


void carga(struct registro datos2 ,int n);


debes de escribir primero el struct, antes de ponerlo como parametro en cualquier prototipo de funcion.

La funcion Carga solo recibie un Registro, no un arreglo de registro.

Aqui lo declaras que solo recibe uno:

void carga(struct registro datos2,int n);

Y aqui le pasas un arreglo de 50 registros:


carga(datos ,n);  

Eso no se puede hacer.

Luego tambien no es preciso

printf("Ingrese la cantidad de pacientes:  ");
scanf("%d",&n);


Ya que si n es mayor que 50 te saldras del limite de arreglos que declaraste.

Hay otros detalles que hay que validar pero si no arreglas esos primeros te vas a revolver.

Si lo manejas como apuntador podrias pasar el parametro directamente:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct registro {
char nombre[100];
int numpaciente;
char obraSocial[50];
};


void carga(struct registro *datos,int n);

int main() {
struct registro datos[50];
int n;
printf("Ingrese la cantidad de pacientes:  ");
scanf("%d",&n);
if(n < 50)
carga(datos ,n);
}

void carga(struct registro *datos,int n ) {
int i;
for (i=0;i<n;i++) {  
_flushall();
printf("ingrese el nombre del paciente");
gets(datos[i].nombre);
printf("ingrese el numeros del pas:");
scanf("%d",&datos[i].numpaciente);
printf("ingrese su obra social : ");
gets(datos[i].obraSocial);
}
return 0;
}


Hay mucha cosas inseguras en tu codigo por ejemplo gets puedes meter la cantidad de caracteres que quieras si metes mas de 100 caracteres el código tronar, mas específicamente caes en un buffer overflow.

Revisa el link que te pase, maneja correctamente los limites.

Saludos!