03 - Entrada y salida en lenguaje C
-
Upload
diego-andres-alvarez-marin -
Category
Software
-
view
192 -
download
1
description
Transcript of 03 - Entrada y salida en lenguaje C
1
03 – Entrada y salida en lenguaje C
Diego Andrés Alvarez MarínProfesor Asociado
Universidad Nacional de ColombiaSede Manizales
2
Temario
● Buffer de memoria● Entrada/salida básica (stdio.h)● Entrada/salida avanzada (ncurses.h)
3
BufferUn buffer (de datos) es un espacio de memoria, en el que se almacenan datos para evitar que el programa o recurso que los requiere, ya sea hardware o software, se quede sin datos durante una transferencia.
Un buffer es como tener dinero en el banco (buffer), un trabajo (entrada) y unos gastos fijos (salida). Si tienes un trabajo inestable, mientras tengas ciertos ahorros, puedes mantener tus gastos fijos sin problemas, e ir ingresando dinero cuando puedas según vas trabajando. Si los ahorros son pequeños, en seguida que no tengas trabajo, no vas a poder acometer los gastos fijos. De la misma forma si escuchas música en Internet y tu programa de audio usa un buffer pequeño, en cuanto que haya alguna interrupción en la descarga (porque las descargas nunca tienen una velocidad constante), notarás cortes de sonido, ya que faltará información.
El buffer de teclado es una memoria intermedia en la que se van almacenando los caracteres que un usuario teclea, los cuales son tratados por el computador apenas se libere un recurso.
4
Funciones de salida/entrada de datos básicas
● Las provee la librería estándar stdio.h y no el lenguaje mismo.
● stdio.h significa "standard input-output header" (cabecera estandar E/S)– stdin = standard input = teclado
– stdout = standard output = pantalla
– stderr = standard error
5
Funciones básicas de salida a pantalla (stdout)
● Sin formato:– putchar() escribe un carácter a stdout
– puts() escribe una cadena de caracteres a stdout
● Con formato:– printf() escribe una cadena de caracteres con
formato a stdout
6
int putchar(int ch);● Escribe un carácter en la pantalla (stdout)● Retorna ch
\a \rBackspace \b \f
\t \”Escape (solo GNU) \e \n
\o \xBackslash \\ \'
\0 \?
Alerta (audible) Retorno de carroFormfeed
Tabulador horizontal ComillasCambio de linea=\r\f
Número octal (ej: \o32) Número hex (ej: \xF3)Apóstrofe
Nulo Pregunta
Algunos caracteres especiales
9
int puts(const char* str);Escribe la cadena str a stdout y agrega automáticamente un “\n”. La cadena str termina cuando se encuentra un carácter “\0”. El “\0” no se copia a stdout
10
int printf(const char* formato,...)
);
printf() retorna el número de caracteres impresos, o un valor negativo si ocurre un error.
printf() toma un número variable de entradas
11
int printf(const char* formato,...)formato en printf()
● Es una cadena de texto que indica el formato como se debe escribir lo deseado
● Sigue el siguiente prototipo:
%[banderas][ancho][.precisión][longitud]especificador
Ver detalles en:
http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
http://en.cppreference.com/w/cpp/io/c/fprintf
http://en.wikipedia.org/wiki/Format_string_attack
12
%[banderas][ancho][.precisión][longitud]especificador
Introducido en C99
Introducido en C99Introducido en C99
13
%[banderas][ancho][.precisión][longitud]especificador%[flags][width][.precision][length]specifier
14
%[banderas][ancho][.precisión][longitud]especificador
Introducido en C99Introducido en C99Introducido en C99Introducido en C99
Introducido en C99
15
16
Un bug en MinGWEn Windows existe un bug en las funciones printf() y scanf() con el formato tipo long o long long; por ejemplo:
scanf ("%llu \n", &x); o printf("%llu \n", x);
Generan el warning:warning: unknown conversion type character 'l' in format [-Wformat]
La solución es usar #include<inttypes.h> y scanf("%"SCNu64"",&x); // entre comillasprintf("%"PRIu64"",UINT64_MAX);
Más información en:http://stackoverflow.com/questions/10763854/printf-and-llx-in-gcc-under-windows-64x
17Observe que el \b no borró el guión -
18
Imprimir tildes en C
#include<locale.h>
setlocale(LC_ALL, “spanish”);
El estándar de codificación de caracteres UNICODE
Se diseñó para facilitar el tratamiento informático, transmisión y visualización de textos de múltiples lenguajes y disciplinas técnicas, además de textos clásicos de lenguas muertas. Unicode incluye sistemas de escritura modernos como: árabe, braille, copto, cirílico, griego, sinogramas (hanja coreano, hanzi chino y kanji japonés), silabarios japoneses (hiragana y katakana), hebreo y latino; escrituras históricas extintas, para propósitos académicos, como por ejemplo: cuneiforme, griego antiguo, fenicio y rúnico. Entre los caracteres no alfabéticos incluidos en Unicode se encuentran símbolos musicales y matemáticos, fichas de juegos como el dominó, flechas, iconos etc.
El estándar de codificación de caracteres UNICODE
● Se adoptó como norma ISO en 1993, como una extensión de los códigos ASCII.
● Se tiene espacio para 1'114.112 símbolos posibles (del 0x000000 al 0x10FFFF). Actualmente se usa la versión 6.3 (Septiembre de 2013). Esta versión define más de 110.000 símbolos.
● Los puntos de código se representan utilizando notación hexadecimal agregando el prefijo U+. El valor hexadecimal se completa con ceros hasta 4 dígitos hexadecimales cuando es necesario; si es de longitud mayor que 4 dígitos no se agregan ceros.
Los símbolos UNICODEhttp://www.unicode.org/charts/
● Se escriben como U+XXXXXX donde X es un hexadecimal (esto se llama el code point).
● En C se representa tal Unicode como \uXXXX (hasta 4 hexadecimales) o como \UXXXXXX (hasta 6 hexadecimales)
● En GNU/Linux se escribe con Ctrl+Shift+u+codepoint ENTER. Cuando esto se hace la letra u aparece subrayada. Se debe tener una fuente apropiada instalada.
● En MS Windows: ver la utilidad "charmap". Se debe tener una fuente apropiada instalada.
http://unicode-table.com/en/sections/miscellaneous-symbols/
0 1 2 3 4 5 6 7 8 9 A B C D E F
23
Unicode(no funciona en Windows)
Nota: estos caracteres especiales requiren más de un byte para su almacenamiento
24
Funciones básicas de entrada desde el teclado (stdin)
● Sin formato:– getchar() lee un carácter desde stdin
– gets() lee una cadena de caracteres desde stdin (C99 – desaconseja su uso, C11 – obsoleto)
– gets_s() lee una cadena de caracteres desde stdin (es el reemplazo de gets())
● Con formato:– scanf() lee una cadena de caracteres con formato
desde stdin
25
int scanf(const char* formato, ...);● Lee datos del teclado (stdin) y lo almacena de
acuerdo al formato dado, en las direcciones de memoria indicadas.
● De forma a similar a printf() puede leer un número variable de entradas; en este caso se supone que cada entrada está separada por un espacio en blanco
● Ignora los espacios en blanco● Retorna el número de items de la cadena de
argumentos exitosamente leídos o un EOF (constante igual a -1) si un error ocurre.
26
int scanf(const char* formato, ...);
● El formato está dado por:
%[*][ancho][longitud]especificador● Ver detalles en:
http://en.cppreference.com/w/cpp/io/c/fscanf
27
%[*][ancho][longitud]especificador
C99
C99
C99
28
%[*][width][length]specifier
(asteriscos porque la función scanf() espera punteros como argumentos)
29
Observe este comportamiento inesperado!!
30
|
31
int getchar(void);
Lee un caracter desde el teclado (mostrándolo).
A pesar de todo estoy leyendo en un char
32
char* gets (char* str);
● El C99 no recomienda usar este comando. El C11 lo vuelve obsoleto. La razón de esto es que este comando hace vulnerable el programa al ataque por hackers. Ver detalles en:– http://en.cppreference.com/w/c/io/gets
– http://en.wikipedia.org/wiki/Buffer_overflow
– http://c-faq.com/stdio/getsvsfgets.html
33
char* gets (char* str);
Buffer overflow!!
Dirección char hex0xbfd8935b 1 E 450xbfd8935c 2 j 6A0xbfd8935d 3 e 650xbfd8935e 4 m 6D0xbfd8935f 5 p 70
0xbfd89360 6 l 6C0xbfd89361 7 o 6F0xbfd89362 8 s 730xbfd89363 9 \0 00
7565164 = 0x00736F6C
m.buf
m.i
CodificaciónLittle-endiandel númeroentero m.i
34
char* gets_s(char *str, rsize_t n);
● Función sugerida en el C11, en reemplazo de gets()
● Lee a lo más n-1 caracteres de stdin en la cadena apuntada por str. Automáticamente agrega el \0 al final de la cadena
● No está implementada todavía en el gcc v.4.6, porque este aún no incorpora los cambios sugeridos en el C11
35
Otro reemplazo de gets(): fgets()
strchr() busca desde la dirección buf hasta que encuentra la primera aparición de un \n. Se retorna dicha dirección de memoria
36
¿Por qué este código aparentemente
correcto no funciona?
Se presionó 20 (ENTER) y nada más. El programa no me preguntó el nombre y terminó
37
Aquí el primer printf() pregunta la edad. Se escribe "20" y se presiona ENTER. El buffer del teclado contiene:2 0 \n
El scanf() lee el %d, es decir el 20 y lo guarda en la variable edad; sin embargo deja el '\n' en el buffer del teclado; ahora entra el fgets() lee el '\n' y no alcanza a leer el nombre. El problema es que scanf() dejó basura en el buffer del teclado (concretamente el \n).
Según http://c-faq.com/stdio/gets_flush2.html la solución es vaciar el buffer del teclado lo cual se puede hacer con alguno de los siguientes comandos:
● while((c = getchar()) != '\n' && c != EOF); //un ciclo vacío● __fpurge(stdin); //solo funciona con gcc/Linux (stdio_ext.h)● flushinp(); // si está manejando la librería curses.h
38
39
Nota con respecto a la entrada de datos desde el teclado
scanf() no es muy versátil que digamos y tiene problemas como el anteriormente mostrado. La mejor opción que se tiene si se requiere seguridad procesando la entrada es utilizar fgets(), sscanf() y/o alguna librería de regular expressions: http://en.wikipedia.org/wiki/Regular_expression
No existen librerías de expresiones regulares en el estándar de C, pero si algunas para ciertos sistemas como regex.h o PCRE para UNIX/Linux:http://www.lemoda.net/c/unix-regex/index.htmlhttp://www.pcre.org/
Se podría también utilizar una interface con el comando de consola grep.
40
41
Tomado de: http://xkcd.com/208/
NOTA: lenguajes como PERL, PYTHON, MATLAB tienen un muy buen soporte para expresiones regulares. Les aconsejo sinceramente aprender a manejar las expresiones regulares cuando tengan problemas con validar entradas de texto, o procesar una gran cantidad de datos en archivos. Es una herramienta que los puede sacar de apuros en más de una ocasión.
42
Preferiblemente no use scanf()http://c-faq.com/stdio/scanfprobs.html
Una buena interface debe permitir la posibilidad que el usuario entre errores: por ejemplo letras en un campo donde se piden números, más o menos caracteres que los esperados, etc. scanf() no es capaz de tratar este tipo de situaciones. Por lo tanto, se sugiere mejor utilizar fgets() y luego interpretar lo leído utilizando sscanf() y/o algunas otras técnicas como expresiones regulares. Funciones como strtol(), strtok(), y atoi() son bastante útiles.
43
La librería inttypes.h
Cuando se quieren imprimir (printf())o leer (scanf()) el tipo de números definidos en stdint.h, se deben ajustar las cadenas de texto con los formatos, para que funcionen con estos tipos de datos. inttypes.h se encarga de esto.
Tenga en cuenta que la librería inttypes.h llama automáticamente a stdint.h
44
Los símbolos de printf() y scanf() definidos por inttypes.h
El N en cursiva es 8, 16, 32 o 64 bits
45
Ejemplo con inttypes.h
Desde este punto de vista PRIx8 es un formato que se le agrega a printf() para que este muestre hexadecimales de 8 bits.
Observe que se utilizó implícitamente la concatenación de cadenas.
46
Funciones de salida/entrada de datos básicas <curses.h>
● curses.h es una biblioteca que provee rutinas de entrada/salida avanzadas y que permite al programador escribir interfaces basadas en texto.
● Fue creada por Ken Arnold para el sistema UNIX BSD. Sin embargo, existen implementaciones para Linux (ncurses.h) y para Windows (pdcurses.h).
● Permite manejar detalladamente la pantalla, manejar el mouse, crear interfaces de texto amigables.
47Tomada de: http://dmcradio.sourceforge.net/
48
49
Instalación en Windows de pdcurses
● Descargue de: http://pdcurses.sourceforge.net/● Lea las instrucciones de instalación.
● O si está utilizando el MinGW, simplemente en la línea de comandos escriba:
mingw-get install mingw32-libpdcurses mingw32-pdcurses
50
Configuración del PDCURSES en Codeblocks para Windows
51
Configuración del PDCURSES en Codeblocks para Windows
52
Configuración del PDCURSES en Codeblocks para Windows
53
Configuración del PDCURSES en Codeblocks para Windows
54
Configuración del PDCURSES en Codeblocks para Windows
Si le aparece este error copie el archivo libpdcurses.dll en la misma carpeta donde está el archivo .exe de su proyecto.
55
En Linux
● Instale la librería libncurses5-dev o similar, ej.:$ sudo apt-get install libncurses5-dev
● Verifique que los siguientes archivos existan:●
●
●
●
● Observe que en este caso ncurses.h y curses.h son el mismo archivo
56
Tutorial de ncurses.h
● Se sugiere mirar el siguiente tutorial:http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/
● Los siguientes programas están basados en dicho tutorial.
57
Un primer ejemplo
Si no se pone este comando, la consola se comportaráde modo extraño. En linux esto se arregla con el comando de consola reset. De todos modos se debe poner siempre endwin().
ncurses.h en linuxcurses.h en windows -lncurses en linux
-lpdcurses en windows
58
sin tener que dar ENTER
59
60
Colores con ncurses
61
Caracteresespeciales
62
Teclas no alfanuméricas
63
Uso del mouse con ncurses.h
Ver el código:http://programaciondecomputadoresunalmzl.wikispaces.com/file/detail/03_mouse_curses.c
64
Otros comandos de curses.h
● int addch(const chtype letra_char);● int mvaddch(int y, int x, const chtype letra_char);● int move(int y, int x);● chtype inch(void);● int mvprintw(int y, int x, char *format, ...);● int getstr(char* string);
65
Programación de juegos
Existen varias librerías especialmente diseñadas para programar juegos. Estas librerías contienen funciones para el manejo de gráficos 2D y 3D, sonidos, joystick, etc. Algunas de las más populares son:
Allegro: http://alleg.sourceforge.net/
ClanLib: http://clanlib.org/wiki/Main_Page
OpenGL: http://www.opengl.org/
SDL: http://www.libsdl.org/
SFML: http://www.sfml-dev.org/
Material basado en:
● http://www.slideshare.net/amraldo/introduction-to-c-programming-7898353
● http://www.slideshare.net/petdance/just-enough-c-for-open-source-programmers
● http://www.cplusplus.com/reference/cstdio/printf/
● http://www.cplusplus.com/reference/cstdio/scanf/
● http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1049157810&id=1043284351
● http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/
● Wikipedia