lunes, 22 de noviembre de 2010

.: Entrada Estandar de C :.

:: Problemas con el Scanf de C ::



Materia. Lab de Leng de Progr
Hora. V1 (Jueves)

Aquí les compartiré uno de mis últimos conocimientos interesantes inculcado sobre lenguaje C. A pesar de que ya deberíamos saberlo, lo interesante es que puede ser nuevo para muchos de nosotros.
¿Se han preguntado por que al capturar nombres completos y mandarlos imprimir sólo muestra el primer nombre?
Esto se debe a que el scanf sólo lee o guarda la cadena hasta donde encuentra el valor nulo de una cadena de caracteres: “\0”
Comprobación.
El siguiente código:
#include <stdio.h>

#define TAM 30

int main(int argc, char** args) {
    char nombre[TAM];
   
    printf("Entrada -> ");
   
    scanf("%s", &nombre);
   
    printf("\n\nSalida -> %s", nombre);
   
    return 0;
}
Me muestra:
Entonces la solución planteada fue utilizar una subrutina en la cual se usa la función getchar(), la cual ira obtenido carácter por carácter y lo ira guardando en una cadena sin importar que coloquemos espacio.
Cuando demos un ENTER dejara de funcionar esta subrutina, esa es la condición para dejar de leer.
Veamos la implementación:
void captura(char* texto, int largo) {
  char simbolo;
  int pos;

  pos = 0;
  printf("Entrada -> ");
 
  while (1) {
    simbolo = getchar(); --->> Leemos un carácter y se asigna a
                               simbolo
    if (simbolo == '\n') { -->> Condición para dejar de capturar
      texto[pos] = '\0';   
      break;
    }
    if (pos < largo) { --->> Cond. para almacenar en la cadena
      texto[pos++] = simbolo; -->> Colocamos en la posición de la
                                   cadena
    }
  }
   
  return;
}
Al momento de dar ENTER, la última posición de la cadena tendrá su valor nulo o valor final de una cadena de caracteres, se invalida el WHILE con el break y dejamos de capturar para pasar a regresar el valor o contenido actual de la cadena.
Recuerden que una cadena de caracteres es sólo un arreglo de tipo carácter.
Esto lo recuerdo por dos motivos:
Porque cada carácter lo estamos posicionando en una posición específica de la cadena.
Porque al mandar la variable de la cadena, se envía de la misma manera como un arreglo. Recordemos que maneja la sintaxis de un puntero en los parámetros que recibe la función de captura por una razón: los arreglos son punteros, y las cadenas de caracteres son arreglos; entonces las cadenas también son punteros.
Demostración de la solución.
Consideren que si se sobrepasa el límite de la cadena de caracteres, los valores que ingresemos más allá de la cadena, ya no se imprimirán.
Nuestro ejemplo tiene una cadena de tamaño 30. Ahora capturemos lo mismo con una longitud de 10.
¿Ven a que me refiero?
Conclusiones:
De alguna manera he comprendido que scanf es un completo MUGRERO para leer cadenas de caracteres.
NOTA. Esta entrada es sólo una introducción de los defectos de scanf, hay más, pero con la pena, les deberé esa información.
Espero haberles abierto más las ideas con esta entrada al momento de hablar de cadenas de caracteres.
Aquí les dejo el código.
Saludos a todos.

2 comentarios:

  1. Bueno, lo que pasa es que la funcion scanf tiene una tipo clase en donde se derivan otras, para asi capturar lo que se nos pide por ejemplo scanf no es para leer cadena de caracteres, para eso se utiliza me parece sscanf y para la lectura de archivos fscanf, cada una tiene una funcion difrente.

    ResponderEliminar
  2. El método de sscanf también sufre del problema que necesitas saber el largo de la cadena. A mí me gustan los ciclos de getchar() por ejemplo para asegurar que la entrada sea numérica, convertir en minúscula, reemplazar caracteres, eliminar espacios, etc. Uno tiene mayor control sobre qué pasa leyendo caracter por caractar. Seis para Crispin y uno de participación para el otro Roberto.

    ResponderEliminar