03 - entrada y salida en lenguaje c

66
1 03 – Entrada y salida en lenguaje C Diego Andrés Alvarez Marín Profesor Asociado Universidad Nacional de Colombia Sede Manizales

Upload: diego-andres-alvarez-marin

Post on 15-Jun-2015

187 views

Category:

Software


1 download

DESCRIPTION

Si quiere descargar la presentación y los códigos fuente, dirijase a: http://programaciondecomputadoresunalmzl.wikispaces.com/codigos_y_diapositivas Le agradecería si me reporta los errores que encuentre en la diapositiva (daalvarez arroba unal punto edu punto co)

TRANSCRIPT

Page 1: 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

Page 2: 03 - Entrada y salida en lenguaje C

2

Temario

● Buffer de memoria● Entrada/salida básica (stdio.h)● Entrada/salida avanzada (ncurses.h)

Page 3: 03 - Entrada y salida en lenguaje C

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.

Page 4: 03 - Entrada y salida en lenguaje C

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

Page 5: 03 - Entrada y salida en lenguaje C

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

Page 6: 03 - Entrada y salida en lenguaje C

6

int putchar(int ch);● Escribe un carácter en la pantalla (stdout)● Retorna ch

Page 7: 03 - Entrada y salida en lenguaje C

\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

Page 8: 03 - Entrada y salida en lenguaje C
Page 9: 03 - Entrada y salida en lenguaje C

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

Page 10: 03 - Entrada y salida en lenguaje C

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

Page 11: 03 - Entrada y salida en lenguaje C

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

Page 12: 03 - Entrada y salida en lenguaje C

12

%[banderas][ancho][.precisión][longitud]especificador

Introducido en C99

Introducido en C99Introducido en C99

Page 13: 03 - Entrada y salida en lenguaje C

13

%[banderas][ancho][.precisión][longitud]especificador%[flags][width][.precision][length]specifier

Page 14: 03 - Entrada y salida en lenguaje C

14

%[banderas][ancho][.precisión][longitud]especificador

Introducido en C99Introducido en C99Introducido en C99Introducido en C99

Introducido en C99

Page 15: 03 - Entrada y salida en lenguaje C

15

Page 16: 03 - Entrada y salida en lenguaje C

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

Page 17: 03 - Entrada y salida en lenguaje C

17Observe que el \b no borró el guión -

Page 18: 03 - Entrada y salida en lenguaje C

18

Imprimir tildes en C

#include<locale.h>

setlocale(LC_ALL, “spanish”);

Page 19: 03 - Entrada y salida en lenguaje C

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.

Page 20: 03 - Entrada y salida en lenguaje C

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.

Page 21: 03 - Entrada y salida en lenguaje C

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.

Page 22: 03 - Entrada y salida en lenguaje C

http://unicode-table.com/en/sections/miscellaneous-symbols/

0 1 2 3 4 5 6 7 8 9 A B C D E F

Page 23: 03 - Entrada y salida en lenguaje C

23

Unicode(no funciona en Windows)

Nota: estos caracteres especiales requiren más de un byte para su almacenamiento

Page 24: 03 - Entrada y salida en lenguaje C

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

Page 25: 03 - Entrada y salida en lenguaje C

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.

Page 26: 03 - Entrada y salida en lenguaje C

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

Page 27: 03 - Entrada y salida en lenguaje C

27

%[*][ancho][longitud]especificador

C99

C99

C99

Page 28: 03 - Entrada y salida en lenguaje C

28

%[*][width][length]specifier

(asteriscos porque la función scanf() espera punteros como argumentos)

Page 29: 03 - Entrada y salida en lenguaje C

29

Observe este comportamiento inesperado!!

Page 30: 03 - Entrada y salida en lenguaje C

30

|

Page 31: 03 - Entrada y salida en lenguaje C

31

int getchar(void);

Lee un caracter desde el teclado (mostrándolo).

A pesar de todo estoy leyendo en un char

Page 32: 03 - Entrada y salida en lenguaje C

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

Page 33: 03 - Entrada y salida en lenguaje C

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

Page 34: 03 - Entrada y salida en lenguaje C

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

Page 35: 03 - Entrada y salida en lenguaje C

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

Page 36: 03 - Entrada y salida en lenguaje C

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ó

Page 37: 03 - Entrada y salida en lenguaje C

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

Page 38: 03 - Entrada y salida en lenguaje C

38

Page 39: 03 - Entrada y salida en lenguaje C

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.

Page 40: 03 - Entrada y salida en lenguaje C

40

Page 41: 03 - Entrada y salida en lenguaje C

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.

Page 42: 03 - Entrada y salida en lenguaje C

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.

Page 43: 03 - Entrada y salida en lenguaje C

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

Page 44: 03 - Entrada y salida en lenguaje C

44

Los símbolos de printf() y scanf() definidos por inttypes.h

El N en cursiva es 8, 16, 32 o 64 bits

Page 45: 03 - Entrada y salida en lenguaje C

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.

Page 46: 03 - Entrada y salida en lenguaje C

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.

Page 47: 03 - Entrada y salida en lenguaje C

47Tomada de: http://dmcradio.sourceforge.net/

Page 48: 03 - Entrada y salida en lenguaje C

48

Page 49: 03 - Entrada y salida en lenguaje C

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

Page 50: 03 - Entrada y salida en lenguaje C

50

Configuración del PDCURSES en Codeblocks para Windows

Page 51: 03 - Entrada y salida en lenguaje C

51

Configuración del PDCURSES en Codeblocks para Windows

Page 52: 03 - Entrada y salida en lenguaje C

52

Configuración del PDCURSES en Codeblocks para Windows

Page 53: 03 - Entrada y salida en lenguaje C

53

Configuración del PDCURSES en Codeblocks para Windows

Page 54: 03 - Entrada y salida en lenguaje C

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.

Page 55: 03 - Entrada y salida en lenguaje C

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

Page 56: 03 - Entrada y salida en lenguaje C

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.

Page 57: 03 - Entrada y salida en lenguaje C

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

Page 58: 03 - Entrada y salida en lenguaje C

58

sin tener que dar ENTER

Page 59: 03 - Entrada y salida en lenguaje C

59

Page 60: 03 - Entrada y salida en lenguaje C

60

Colores con ncurses

Page 61: 03 - Entrada y salida en lenguaje C

61

Caracteresespeciales

Page 62: 03 - Entrada y salida en lenguaje C

62

Teclas no alfanuméricas

Page 63: 03 - Entrada y salida en lenguaje C

63

Uso del mouse con ncurses.h

Ver el código:http://programaciondecomputadoresunalmzl.wikispaces.com/file/detail/03_mouse_curses.c

Page 64: 03 - Entrada y salida en lenguaje 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);

Page 65: 03 - Entrada y salida en lenguaje C

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/

Page 66: 03 - Entrada y salida en lenguaje C

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