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 - MAFUS

#1321
Te voy a mostrar una serie de programa de pruebas que te mostrarán el funcionamiento de fgets y lo que ocurre con el buffer stdin.

Es una buena idea realizar estos programas cuándo estudias programación para saber que ocurre en cada situación.

Este primero te enseñará qué copia desde stdin a tu buffer cuando le das a fgets un tamaño inferior al tamaño de tu buffer. En este caso tenemos un buffer de 5 elementos y fgets solo puede copiar 3.


#include <stdio.h>
#include <ctype.h>

#define MAX_BUFF 5

void representar_char(int c) {
    printf("%i", c);
    if(isalnum(c))
        printf(" -> \'%c\'", c);
    else {
        switch(c) {
            case '\0':
                printf("  -> \'\\0\'");
                break;
            case '\n':
                printf(" -> \'\\n\'");
                break;
        }
    }
}
   
int main() {
    char mi_buffer[MAX_BUFF];
    int i;
    printf(">> ");
    fgets(mi_buffer, 3, stdin);
    for(i = 0; i < MAX_BUFF; ++i) {
        printf("mi_buffer[%i] : ", i);
        representar_char(mi_buffer[i]);
        putchar('\n');
    }
   
    return 0;
}


Si al ejecutar de damos como cadena de entrada el carácter 'A' obtenemos esta salida:


>> A
mi_buffer[0] : 65 -> 'A'
mi_buffer[1] : 10 -> '\n'
mi_buffer[2] : 0  -> '\0'
mi_buffer[3] : -86
mi_buffer[4] : -2


Vemos que en primer lugar se guarda el carácter 'a', seguidamente el carácter de nueva línea '\n' y finalmente el caracter nulo '\0'. A partir del cuarto elemento, mi_buffer[3], lo que hay es basura.

Ahora, si le das como entrada la cadena "AB" verás el siguiente resultado:


>> AB
mi_buffer[0] : 65 -> 'A'
mi_buffer[1] : 66 -> 'B'
mi_buffer[2] : 0  -> '\0'
mi_buffer[3] : -80
mi_buffer[4] : -3


Como puedes ver no se ha guardado en el mi_buffer el carácter de nueva línea, que sigue existiendo en el buffer stdin, como veremos más adelante. Para corroborar que el último carácter a guardar siempre será un '\0' puedes repetir el programa esta vez con la cadena "ABC".


>> ABC
mi_buffer[0] : 65 -> 'A'
mi_buffer[1] : 66 -> 'B'
mi_buffer[2] : 0  -> '\0'
mi_buffer[3] : -13
mi_buffer[4] : -2


Ahora, para ver que queda en el buffer hay que modificar un poco el programa anterior.

#include <stdio.h>
#include <ctype.h>

#define MAX_BUFF 5

void representar_char(int c) {
    printf("%i", c);
    if(isalnum(c))
        printf(" -> \'%c\'", c);
    else {
        switch(c) {
            case '\0':
                printf("  -> \'\\0\'");
                break;
            case '\n':
                printf(" -> \'\\n\'");
                break;
        }
    }
}
   
int main() {
    char mi_buffer[MAX_BUFF];
    int i;
    char c;
    printf(">> ");
    fgets(mi_buffer, 3, stdin);
    for(i = 0; i < MAX_BUFF; ++i) {
        printf("mi_buffer[%i] : ", i);
        representar_char(mi_buffer[i]);
        putchar('\n');
    }
    while((c = getchar()) != '\n') {
        printf("caracter en stdin : ");
        representar_char(c);
        putchar('\n');
    }
    printf("caracter en stdin : ");
    representar_char(c);
    putchar('\n');
    return 0;
}


Si le damos como cadena de entrada "ABCDEFGHI" da el siguiente resultado:

>> ABCDEFGHI
mi_buffer[0] : 65 -> 'A'
mi_buffer[1] : 66 -> 'B'
mi_buffer[2] : 0  -> '\0'
mi_buffer[3] : -79
mi_buffer[4] : -1
caracter en stdin : 67 -> 'C'
caracter en stdin : 68 -> 'D'
caracter en stdin : 69 -> 'E'
caracter en stdin : 70 -> 'F'
caracter en stdin : 71 -> 'G'
caracter en stdin : 72 -> 'H'
caracter en stdin : 73 -> 'I'
caracter en stdin : 10 -> '\n'


mi_buffer sigue recibiendo tantos caracteres como le hemos dicho a fgets, ver que uno de ellos es el carácter '\0' pues debe crear una cadena, lo demás se encuentra esperando en el buffer stdin.

Por último hay que ver que pasa si a fgets se le pasa un tamaño a copiar mayor que el tamaño de buffer de destino y la cadena a copiar también es mayor que el destino. Para ello modificamos de nuevo el programa:


#include <stdio.h>
#include <ctype.h>

#define MAX_BUFF 5

void representar_char(int c) {
    printf("%i", c);
    if(isalnum(c))
        printf(" -> \'%c\'", c);
    else {
        switch(c) {
            case '\0':
                printf("  -> \'\\0\'");
                break;
            case '\n':
                printf(" -> \'\\n\'");
                break;
        }
    }
}
   
int main() {
    char mi_buffer[MAX_BUFF];
    int i;
    char c;
    printf(">> ");
    fgets(mi_buffer, MAX_BUFF + 2, stdin);
   
    /* Qué hay dentro de mi_buffer */
    for(i = 0; i < MAX_BUFF; ++i) {
        printf("mi_buffer[%i] : ", i);
        representar_char(mi_buffer[i]);
        putchar('\n');
    }
   
    /* Cuidado aquí, esta parte de la memoria está fuera de todo contro */
    for(i = MAX_BUFF; i < MAX_BUFF + 2; ++i) {
        printf("*** mi_buffer[%i] : ", i);
        representar_char(mi_buffer[i]);
        putchar('\n');
    }
       
    /* Qué hay en stdin */
    while((c = getchar()) != '\n') {
        printf("caracter en stdin : ");
        representar_char(c);
        putchar('\n');
    }
    printf("caracter en stdin : ");
    representar_char(c);
    putchar('\n');
    return 0;
}


Al pasarle la cadena ABCDEFGHIJKL al programa obtenemos:


>> ABCDEFGHIJKL
mi_buffer[0] : 65 -> 'A'
mi_buffer[1] : 66 -> 'B'
mi_buffer[2] : 67 -> 'C'
mi_buffer[3] : 68 -> 'D'
mi_buffer[4] : 69 -> 'E'
*** mi_buffer[5] : 70 -> 'F'
*** mi_buffer[6] : 0  -> '\0'
caracter en stdin : 71 -> 'G'
caracter en stdin : 72 -> 'H'
caracter en stdin : 73 -> 'I'
caracter en stdin : 74 -> 'J'
caracter en stdin : 75 -> 'K'
caracter en stdin : 76 -> 'L'
caracter en stdin : 10 -> '\n'


Se puede ver que fgets sigue cumpliendo su trabajo, copia tantos caracteres como le hemos dicho, ha desbordado mi_buffer, pero trabaja como se espera de él. Los datos en marcados en *** están fuera de todo control y podrían darse otras situaciones como el cierre del programa, cuelgue del sistema, etc.
Para terminar se sigue viendo en en stdin está el resto de la cadena que no se ha copiado.
#1322
Fallos en tu código:
Línea 60
for(p = 0; p = x; p++)
Línea 65
for(p = x; p = 0; p--)
Estos fors están mal formulados, como puedes ver donde debe haber la comparación hay una asignación.

Por cierto, haciendo uso de operadores adecuados, como el de desplazamientos de bits y evitando funciones redundantes como la imprimeResultado y clean_stdin puedes reducir el tamaño del código menos de la mitad.
#1323
A mi me funciona el código.

A decir verdad me he inventado código para las funciones que no muestras, a lo mejor el problema está allí.

¿Porqué no muestras el código entero, #includes incluidos?


Por cierto, para escribir mensajes de error o cadenas de control para depurar el programa mejor hacerlo con fprintf(stderr, cadena_mensaje_error, ...);

La razón es que la escritura a stderr se muestra directamente por pantalla o donde sea que apunte stderr, mientras que si se escribe a stdout el mensaje se guarda en búffer y C lo libera cuándo cree conveniente. Y eso es la razón de la existencia de fflush(descriptor_del_flujo_de_salida), para forzar que se libere el buffer de forma inmediata.
#1324
Sobre la 1ª pregunta: Cuándo guardas un dato, eso es un nombre, una dirección, etc. éstos no tienen implícitos cambios de línea Es de buena práctica separar los datos de su presentación: el dato es la cadena, la presentación dicta si debe haber un salto de línea o no. Por consiguiente sí, es bueno quitar el salto de línea.

Sobre la 2ª pregunta: fgets copia los N primeros caracteres teniendo en cuenta siempre que el último carácter de la cadena destino será '\0' así que en verdad se copian N-1 caracteres; de esta forma fgets se asegura que en el destino hay una cadena con su final. Los caracteres que no fueron copiados se quedan en el búffer del teclado.
#1325
Sí, z cambia de dirección, es una cadena diferente. Lo puedes ver usando el argumento % p de printf.
#1326
Mucha:
El array contenido de un array, si es una variable automática, se guarda en la pila, en cambio en un puntero es este mismo el que se guarda en la pila y su contenido en el montón (heap) si se da su valor con malloc, calloc, realloc, etc. O en la zona de memoria de datos de sólo lectura si se le da el valor directamente con una cadena.
Si a un array se lo inicializa con una cadena, C crea código por debajo para copiar la cadena al array, en cambio el puntero guarda la cadena en memoria de solo lectura y apunta a ella.
A un array se le puede modificar el contenido, pero no sus características (zona a la que apunta su nombre,  el tamaño); al array se le puede cambiar la dirección a la que apunta, peri no su contenido si este es una cadena literal.
Con esto puedes ver que un array y un puntero,  aunque se vean muy parecidos, son dos cosas muy diferentes y debes elegir cual usar según el tratamiento que vayas a hacer de los datos.
Una cosa curiosa es que si dos arrays distintos los inicializas en el código con la misma cadena (sendas cadenas iguales), el compilador sólo guardará una cadena en memoria y los dos punteros apuntarán a ella. En cámbio,  si haces lo mismo pero con arrays cada uno de ellos guardará su propia copia de la cadena, así gastará el doble de espacio.
#1327
No se ve el código.
#1328
Bin0010, le pasas a setModelo una cadena cuando el método espera un entero.

Antes del inicio del main te sobra el último };
#1329
¿Qué error te dice el compilador que hay?

Por cierto, tienes pérdida de memoria en la linea *files = sTemp;
*files apunta a una zona a la que has adquirido memoria con calloc pero no la liberas antes de la nueva asignación.

Para solucionar eso, y saltarte un paso en ello, haz realloc sobre *files mismo; realloc se encargará de liberar la memoria y ocupar otra para *files, que para eso es su trabajo.
#1330
La función de Kaxperday solo funcionaría para tipos de datos no reales, ya que estos tienen una representación interna diferente.