22/09/2019, 02:08:23 pm *
Bienvenido(a), Visitante. Por favor, ingresa o regístrate.
¿Perdiste tu email de activación?

Ingresar con nombre de usuario, contraseña y duración de la sesión
Noticias: Renovado el procedimiento de inserción de archivos GEOGEBRA en los mensajes.
 
 
Páginas: [1]   Ir Abajo
  Imprimir  
Autor Tema: (C) Funciones confortables de Entrada/Salida  (Leído 1969 veces)
0 Usuarios y 1 Visitante están viendo este tema.
argentinator
Consultar la FIRMAPEDIA __________________________________________________________________________________________________________________
Administrador
Pleno*
*****

Karma: +0/-0
Desconectado Desconectado

Sexo: Masculino
Argentina Argentina

Mensajes: 7.275

Vean mis posts activos en mi página personal


Ver Perfil WWW
« : 19/08/2013, 02:26:48 pm »

Librería NBIO.H

Estos días estuve jugando con un programa acá en el foro,
que calculaba el m.c.d. de dos números,
pero que derivó en un análisis de cómo mejorar la interacción con el usuario.

Programando en C,
muchas veces surgen dudas cuando usamos scanf() o gets(), y funciones similares.

Voy a colgar acá una librería que resuelve en forma básica varios problemas que surgen en la práctica sobre este tema, en forma recurrente.



Problema 1: ¿Cómo detectar si una string está compuesta sólo por caracteres "blancos"?

Spoiler: Solución 1 (click para mostrar u ocultar)



Problema 2: ¿Cómo detectar si un caracter pertenece a un conjunto dado de caracteres?

Spoiler: Solución 2 (click para mostrar u ocultar)



Problema 3: ¿Cómo asignarle un valor a una variable string?

Spoiler: Solución 3 (click para mostrar u ocultar)



Problema 4: ¿Cómo frenar el programa antes de que termine?

Spoiler: Solución 4 (click para mostrar u ocultar)



Problema 5: ¿Cómo leer desde la entrada estándar una string en forma segura?

Spoiler: Solución 5 (click para mostrar u ocultar)



Problema 6: ¿Cómo se hace para saber si una lectura del tipo scanf(), fscanf(), sscanf() ha producido o tenido un error?

Spoiler (click para mostrar u ocultar)



Problema 7: ¿Cómo pasar parámetros de un tipo concreto a una macro?

Spoiler: Solución 7 (click para mostrar u ocultar)



(Nuevo)

Problema 8: ¿Cómo crear una macro tipo "bloque" y que sea "segura"?

Spoiler: Solución 8 (click para mostrar u ocultar)

:sonrisa:
En línea

argentinator
Consultar la FIRMAPEDIA __________________________________________________________________________________________________________________
Administrador
Pleno*
*****

Karma: +0/-0
Desconectado Desconectado

Sexo: Masculino
Argentina Argentina

Mensajes: 7.275

Vean mis posts activos en mi página personal


Ver Perfil WWW
« Respuesta #1 : 19/08/2013, 02:27:38 pm »

Problema 9: ¿Cómo manejar la entrada de datos por teclado de una manera "confortable"?

Spoiler: Solución 9 (click para mostrar u ocultar)

¿Cómo ponemos todo esto en una librería?
Así:

Spoiler: Librería NBIO.H, versión 1.00 (click para mostrar u ocultar)

(Modificación: He cambiado las llaves del cuerpo de la macro por la técnica explicada en el Problema 8)
En línea

argentinator
Consultar la FIRMAPEDIA __________________________________________________________________________________________________________________
Administrador
Pleno*
*****

Karma: +0/-0
Desconectado Desconectado

Sexo: Masculino
Argentina Argentina

Mensajes: 7.275

Vean mis posts activos en mi página personal


Ver Perfil WWW
« Respuesta #2 : 19/08/2013, 04:59:08 pm »

Algunas ideas:

* El buffer podría declararse como variable temporal dentro del bloque de sentencias de la macro NB_scanf(), y luego descartarlo al final del bloque.

* La estructura anónima que colecta los errores podría dejar de ser anónima y pasarse como parámetro a la macro "por referencia", para luego ser modificada internamente en forma más "seguro", evitando efectos colaterales.

Ahora que hemos encontrado el modo de usar macros como funciones, podemos tratarlas casi de la misma manera.

Una diferencia esencial es que nuestra implementación de las macros en formato de bloques encerrados por llaves {  } impide que se retorne un valor, como lo haría una función.

En línea

argentinator
Consultar la FIRMAPEDIA __________________________________________________________________________________________________________________
Administrador
Pleno*
*****

Karma: +0/-0
Desconectado Desconectado

Sexo: Masculino
Argentina Argentina

Mensajes: 7.275

Vean mis posts activos en mi página personal


Ver Perfil WWW
« Respuesta #3 : 19/08/2013, 06:00:17 pm »

Para evitar efectos "colaterales", y para que la macro NB_scanf() se comporte del mismo modo que lo haría una función, se han hecho los siguientes cambios:

* Ahora hay una struct nb_s que define un tipo para colectar errores de NB_scanf() en una llamada a dicha macro. (El programador tiene que declarar una variable de ese tipo para poder colectar dichos errores, y más aún, para que NB_scanf() siquiera funcione).

* El tipo struct nb_s viene a reemplazar la variable global nb_input que había antes, la cual ha sido eliminada. Más aún, se le ha quitado el campo buffer.

* Hay un nuevo parámetro por "referencia" en la macro, de nombre ERR. Le "exigimos" que sea de tipo (struct nb_s *), con las técnicas que aprendimos arriba (ver problema 7). Esto permite tratarlo internamente como un parámetro "por referencia".

* Ahora el buffer para leer datos está declarado explícitamente dentro de la macro, como un array  de duración temporal, sólo durante el tiempo que dure el bloque de la macro. Se llama __buffer[], y tiene el mismo tamaño de siempre: __INPUT_STR_LEN (que fijamos en 130).

* Hemos cambiado, consecuentemente, los comentarios asociados a la estructura nb_s y a la macro NB_scanf().

Los cambios son estos:

Spoiler: nb_s (click para mostrar u ocultar)

Spoiler: Comentarios previos de NB_scanf() (click para mostrar u ocultar)

Spoiler: La macro NB_scanf() (click para mostrar u ocultar)

Para quien quiera usar la librería, aquí la copio completa:

Spoiler: NBIO0101.H (click para mostrar u ocultar)

(Modificación: He cambiado las llaves del cuerpo de la macro por la técnica explicada en el Problema 8)
En línea

Páginas: [1]   Ir Arriba
  Imprimir  
 
Ir a:  

Impulsado por MySQL Impulsado por PHP Powered by SMF 1.1.4 | SMF © 2006, Simple Machines LLC XHTML 1.0 válido! CSS válido!