Introducción al lenguaje C. E/S Básica

Elementos de un programa C. Tipos básicos de datos. E/S básica. Sentencias de control. Funciones. Asignación dinámica de memoria. Ficheros. Ficheros indexados: la interfase Btrieve. Compilación y enlazado. Biblioteca de funciones de Turbo C

  • Enviado por: Juan
  • Idioma: castellano
  • País: España España
  • 22 páginas
publicidad
publicidad

4

E/S básica

Tipos de E/S

Ya quedó dicho en el Capítulo 1 que C no tiene palabras reservadas específicas que se encarguen de la E/S. Estas operaciones se realizan mediante funciones de biblioteca. Estas funciones realizan operaciones de E/S que se clasifican del siguiente modo:

  • E/S de alto nivel, definida por el estándar ANSI. También se denomina sistema de archivos con búffer.

  • E/S de bajo nivel, o E/S de tipo UNIX.

  • E/S por consola.

Los dos estándares ANSI y UNIX son redundantes. Turbo C admite los dos, pero no deben utilizarse dentro de un mismo programa funciones de ambos.

En el presente capítulo se estudiarán operaciones básicas de E/S por consola, entendiendo por ello las operaciones realizadas sobre la E/S estándar del sistema, por defecto teclado y pantalla. Veremos también que tanto la entrada como la salida puede redireccionarse a otros dispositivos, y cómo hacerlo, y también cómo realizar operaciones de salida a impresora. Por último, estudiaremos cómo realizar cierto control sobre la pantalla en modo texto (color, posicionamiento, etc.). Las operaciones de E/S a ficheros se estudiarán en los Capítulos 10 y 11.

E/S de caracteres

Funciones getche() y getch()

Son las dos funciones básicas que capturan caracteres simples por teclado. Los programas que utilizan estas funciones deben incluir el archivo de cabecera conio.h mediante una sentencia #include. Ambas funciones devuelven el carácter leído del teclado (sin esperar a pulsar la tecla ). La función getche() muestra en pantalla el carácter tecleado. No así la función getch(). El uso correcto de estas funciones es mediante sentencias del tipo

char a; /* También puede declararse como int */

...

...

a = getche (); /* o bien a = getch (); */

Estas funciones no tienen argumentos. No es obligatorio capturar en una variable el carácter leído. Así, es correcto escribir:

printf ("\nPulse una tecla para continuar ...");

getch ();

que detiene el programa hasta que haya un carácter disponible en el teclado.

//Ejemplo: Visualiza el código ASCII de un carácter tecleado

#include <stdio.h>

#include <conio.h>

void main ()

{

unsigned int caracter;

printf ("\nPulse una tecla: ");

caracter = getche ();

printf ("\nSu código ASCII es %u", caracter);

}

Este programa produce un resultado casi idéntico utilizando la función getch(). La única diferencia es la no visualización del carácter que se teclea. El código de formato %u se utiliza en printf() para visualizar números declarados unsigned.

Función putchar()

Para la presentación de caracteres en pantalla se puede usar, además de printf() con el código de formato %c, la función putchar(). Los programas que usen esta función deben incluir el archivo de cabecera stdio.h. El uso correcto de putchar() es

char a; /* También puede declararse como int */

...

...

putchar (a);

Si la variable a es de tipo int se visualiza en pantalla el carácter almacenado en el byte menos significativo. Las sentencias

char letra;

...

...

letra = 65;

putchar (letra);

provocan la visualización en pantalla del carácter A, cuyo código ASCII es 65. Es equivalente a

putchar ('A');

También son posibles sentencias como

putchar (getch ());

cuyo efecto es idéntico al que produce la función getche().

E/S de cadenas de caracteres

En C no hay un tipo de dato específico para declarar cadenas de caracteres. Como ya quedó dicho, una cadena de caracteres se define como un vector de caracteres terminado con el carácter nulo '\0'. Así, para declarar una cadena de hasta 30 caracteres se debe escribir

char cadena[31];

Aunque se profundizará en el estudio de las cadenas de caracteres en el Capítulo 7, es necesario adelantar que C no realiza ningún control de límites sobre matrices. Ese cometido queda en manos del programador.

Función gets()

La función básica de entrada de cadenas caracteres por teclado es gets(). Esta función lee caracteres del teclado hasta pulsar la tecla , almacenándolos en la cadena indicada en el argumento y añadiendo el carácter nulo al final.

char frase[31];

...

...

gets (frase);

La función gets() no hace comprobación del límite. En la secuencia anterior nada impedirá al usuario teclear más de 30 caracteres. La consecuencia de ello es imprevisible, aunque con toda seguridad el programa no funcionará correctamente.

Es importante tener en cuenta que no se permite la asignación de cadenas de caracteres mediante el operador =. Este tipo de operaciones se realizan mediante funciones de la biblioteca estándar. Alguna de ellas se estudiarán e el Capítulo 6.

frase = gets ();

Función puts()

La función básica de salida de cadenas de caracteres es puts(). Esta función escribe en pantalla la cadena de caracteres especificada en el argumento y provoca, además, un salto de línea. Es más rápida que printf() pero no permite formatear la salida.

Tanto gets() como puts() precisan la inclusión del fichero stdio.h.

//Ejemplo con gets() y puts()

#include <stdio.h>

void main ()

{

char frase[31];

puts ("\nTeclee una frase: ");

gets (frase);

printf ("\nUsted ha tecleado: %s", frase);

}

En el ejemplo anterior el código de formato %s se refiere a cadenas de caracteres. Un efecto similar al programa anterior lo produce la sentencia

puts (gets (frase));

E/S formateada

La E/S con formato se realiza por medio de las funciones scanf() y prinft() que ya conocemos. Las estudiaremos ahora con más detalle.

Función printf()

Como ya hemos visto, esta función precisa la inclusión del archivo de cabecera stdio.h y su formato general es:

printf (cadena de control, lista de argumentos);

La cadena de control determina como se presentarán el resto de argumentos mediante los caracteres de formato. Por cada carácter de formato de la cadena de control debe haber un argumento en la lista. En caso contrario el resultado no será correcto. Los caracteres de formato válidos vienen especificados en la tabla siguiente.

TIPO DE

ARGUMENTO

CARÁCTER

DE FORMATO

FORMATO DE

SALIDA

Numérico

%d

signed decimal int

%i

signed decimal int

%o

unsigned octal int

%u

unsigned decimal int

%x

unsigned hexadecimal int (con a, ..., f)

%X

unsigned hexadecimal int (con A, ..., F)

%f

[-]dddd.dddd

%e

[-]d.dddd o bien e[+/-]ddd

%g

el más corto de %e y %f

%E

[-]d.dddd o bien E[+/-]ddd

%G

el más corto de %E y %f

Carácter

%c

carácter simple

%s

cadena de caracteres

%%

el carácter %

Punteros

%n

se refieren a punteros y se

%p

estudiarán en el Capítulo 7

Mediante los caracteres de formato pueden controlarse ciertos aspectos de la presentación de los datos, como la longitud, el número de decimales y la justificación a izquierda o derecha.

Para indicar la longitud de un campo basta incluir un número entero entre el signo % y el carácter de formato. Así, %5d indica que se va a presentar un número entero en un campo de 5 posiciones, justificando a la derecha (mientras no se indique lo contrario la justificación es siempre a la derecha). Así,

printf ("\n[%5d]", 47); visualiza [°°°47]

printf ("\n[%4d]", 47); visualiza [°°47]

printf ("\n[%3d]", 47); visualiza [°47]

donde el símbolo ° representará el resto del capítulo un espacio en blanco. Los corchetes se ponen sólo para ver el efecto de los caracteres de formato.

Si se desea justificación a la izquierda, se indica con un signo menos.

printf ("\n[%-5d]", 47); visualiza [47°°°]

printf ("\n[%-4d]", 47); visualiza [47°°]

printf ("\n[%-3d]", 47); visualiza [47°]

Cuando se presenta un valor numérico justificando a la derecha, puede hacerse que el campo se rellene con ceros en lugar de espacios en blanco, poniendo un 0 antes del indicador de tamaño. Así, la sentencia

printf ("\n[%05d]", 47); visualiza [00047]

Este efecto no se produce si se solicita justificación izquierda

printf ("\n[%-05d]", 47); visualiza [47°°°]

Cuando el dato sobrepasa el tamaño del campo, se imprime completo

printf ("\n[%3d]", 1234); visualiza [1234]

Si lo dicho anteriormente se aplica a cadenas de caracteres, el resultado es el que se indica a continuación:

printf ("\n[%5s]", "ABC"); visualiza [°°ABC]

printf ("\n[%05s]", "ABC"); visualiza [°°ABC]

printf ("\n[%-5s]", "ABC"); visualiza [ABC°°]

printf ("\n[%-05s]", "ABC"); visualiza [ABC°°]

printf ("\n[%5s]", "ABCDEF"); visualiza [ABCDEF]

Aplicado a caracteres simples

printf ("\n[%3c]", 'A'); visualiza [°°A]

printf ("\n[%-3c]", 'A'); visualiza [A°°]

Si se quiere dar formato a un número con parte decimal se utiliza el código de formato

%m.nf

siendo m la longitud total del campo (incluyendo el punto) y n el número de decimales. Así, el especificador de formato %7.2f define un campo de 7 posiciones del siguiente modo: 4 para la parte entera, 1 para el punto y 2 para los decimales.

printf ("\n[%7.2f]", 12.3); visualiza [°°12.30]

printf ("\n[%07.2f]", 12.3); visualiza [0012.30]

printf ("\n[%-7.2f]", 12.3); visualiza [12.30°°]

Cuando el número de decimales es mayor que n, se redondea la última cifra

printf ("\n[%7.2f]", 12.348); visualiza [°°12.35]

printf ("\n[%7.2f]", 12.342); visualiza [°°12.34]

Si este formato se aplica a cadenas de caracteres o números enteros, n especifica el tamaño máximo del campo. Así, %3.5s define un campo de presentación para una cadena de al menos 3 caracteres y no más de 5. Si la cadena sobrepasa el tamaño máximo, se trunca.

printf ("\n[%3.5s]", "ABC"); visualiza [ABC]

printf ("\n[%-3.5s]", "ABC"); visualiza [ABC]

printf ("\n[%3.5s]", "ABCDEFG"); visualiza [ABCDE]

printf ("\n[%3.5s]", "AB"); visualiza [°AB]

printf ("\n[%5.3s]", "ABCDE"); visualiza [°°ABC]

Pueden utilizarse modificadores de formato para visualizar enteros short y long, poniendo, respectivamente, h y l antes de d, u, o, x, X.

%hd para visualizar variables short int

%ld para visualizar variables long int

%hu para visualizar variables unsigned short int

%lu para visualizar variables unsigned long int

El modificador l también se puede aplicar a e, f, g, E, G.

%lf para visualizar variables long double

Función scanf()

Es la función de entrada de datos con formato de propósito general que hemos visto en el Capítulo 1. La sintaxis es similar a la de printf():

scanf (cadena de control, lista de argumentos);

aunque aquí la cadena de control no debe interpretarse igual que en printf().

Clasificaremos los caracteres que pueden aparecer en la cadena de control en 6 categorías:

  • Especificadores de formato

  • Caracteres blancos

  • Caracteres no blancos

  • Carácter *

  • Modificadores de longitud

  • Juego de inspección

Especificadores de formato: Son los mismos que en printf() salvo %g y %u y añadiendo %h. Así, la sentencia

char a; /* También se puede declarar como int */

...

...

scanf ("%c", &a);

captura un carácter y lo almacena en la variable a. El operador & es necesario en scanf() para simular las llamadas por referencia, y hace que la función trabaje internamente con la dirección de la variable. No es necesario cuando el dato a capturar es una cadena de caracteres.

char cadena[80];

...

...

scanf ("%s", cadena);

aunque tendría el mismo efecto la sentencia

scanf ("%s", &cadena);

La razón por la que no es necesario el operador & cuando se trata de cadenas, es que el nombre de una cadena (en general, de una matriz) sin índices identifica la dirección del primer elemento.

Caracteres blancos: Son separadores de datos de entrada. Se entiende como carácter blanco cualquiera de los siguientes:

  • Espacio(s) en blanco

  • Tabulador(es)

  • Return, Intro o salto de línea ()

Cuando se especifica un carácter blanco en la cadena de control, scanf() lee, pero no guarda, cualquier número de caracteres blancos hasta que encuentre el primero que no lo sea. La sentencia

scanf ("%c %d %s", &a, &b, &c);

almacena en a, b y c, respectivamente, datos introducidos de cualquiera de los siguientes modos:

Y Y <TAB> 19 Y 19 Hola

19 Hola

Hola

y cualquier combinación similar.

Hay que tener precauciones con el uso de los espacios en blanco. Una sentencia como

scanf ("%s ", cadena);

no volverá hasta que no se teclee un carácter no blanco, puesto que el espacio que hay después de %s hace que se lean y descarten espacios, tabuladores y saltos de línea.

Caracteres no blancos: Se toman como separadores de los datos de entrada. Por ejemplo, en la sentencia

scanf ("%dHOLA%c", &num, &car);

se lee un entero y se almacena en num, los caracteres HOLA y se descartan (es necesario teclearlos), y un carácter cualquiera y se almacena en car. Debido a ello hay que poner especial cuidado en no usar la cadena de control de scanf() como en printf(), y NO ESCRIBIR sentencias como:

scanf ("Teclee un número: %d", &num);

Carácter *: Cuando se coloca un * entre el símbolo % y el carácter de formato, se lee el tipo de dato especificado pero no se asigna a ninguna variable. La sentencia

scanf ("%d %*c %d", &num1, &num2);

lee un entero y lo almacena en num1, lee un carácter y lo descarta (no se asigna a ninguna variable, y lee otro entero y lo guarda en num2. De este modo, si a una sentencia como la anterior se responde tecleando algo como

10-20

se almacenaría el valor 10 en num1 y el valor 20 en num2.

Modificadores de longitud: Es posible limitar el número de caracteres que se admiten en un campo escribiendo un número después del símbolo % del carácter de formato. Así, la sentencia

scanf ("%5s", frase);

captura cualquier cadena de caracteres tecleada, pero sólo almacena en frase los 5 primeros. Sin embargo el resto de caracteres no se descartan, sino que quedan en el búffer del teclado disponibles para ser leídos por otra sentencia scanf(). El siguiente programa ilustra el uso de scanf() con modificadores de longitud.

//Ejemplo de scanf() con modificador de longitud

#include <stdio.h>

void main ()

{

long int n1, n2;

printf ("\nTeclee 2 números enteros: ");

scanf ("%5ld %5ld", &n1, &n2);

printf ("\nLos números tecleados son %ld y %ld", n1, n2);

}

Si en este programa a la sentencia scanf() se responde con

123456 ↵

se muestra en pantalla

Los números tecleados son 12345 y 6

Juego de inspección: Se utiliza sólo con %s y permite especificar qué caracteres se aceptarán. Se indican entre corchetes. Por ejemplo

char frase[30];

...

...

scanf ("%[abc]s", frase);

admite sólo los caracteres a, b, c. Cuando se teclea un carácter que no está en el juego de inspección finaliza la entrada para esa variable. Sin embargo, la sentencia continuará admitiendo caracteres hasta que se teclee , dejando los caracteres no capturados en el búffer del teclado, disponibles para otra sentencia scanf() posterior. Por ello, si se tienen dos sentencias como

scanf ("%[abc]s", frase);

scanf ("%s", cadena);

y se teclea, por ejemplo

abcbbapabcfgts ↵

en frase se almacenará la cadena abcbba, mientras que en cadena se almacenará abcfgts. El carácter p, primero diferente de [abc], actúa como finalizador de la entrada para la variable frase.

Pueden especificarse rangos. Por ejemplo

scanf ("%[a-z]s", frase);

admite cualquier carácter comprendido entre la a y la z. También, la sentencia

scanf ("%[0-9][p-t]s", frase);

admite cualquier dígito numérico y los caracteres pqrst.

Es posible definir juegos inversos de inspección mediante el carácter ^. Éste le indica a scanf() que debe aceptar cualquier carácter que no esté en el juego de inspección. Por ello, la sentencia

scanf ("%[^0-9]s", frase);

finaliza la entrada al teclear un dígito numérico.

La función fprintf()

Esta función es prácticamente idéntica a printf(). Pero fprintf() permite asociar la salida a diferentes dispositivos (pantalla, impresora, archivo de texto u otro). La sintaxis correcta para esta función es

fprintf (dispositivo, cadena de control, lista de argumentos);

es decir, incluye un primer argumento que relaciona la salida con un dispositivo. En realidad, ese primer argumento debe ser un puntero a una estructura predefinida en C llamada FILE, de la que hablaremos en el Capítulo 10. De cualquier modo, para nuestros propósitos actuales, nos basta con identificarlo de algún modo con un dispositivo.

Como veremos en su momento, C asocia los dispositivos a unas zonas o búffers de memoria denominados canales. Cuando un programa empieza a ejecutarse se abren automáticamente 5 canales, entre ellos el asociado a la impresora. A este dispositivo se le referencia mediante la palabra stdprn.

Por lo tanto, fprintf() direcciona su salida a la impresora cuando se escribe de la forma

fprintf (stdprn, cadena de control, lista de argumentos);

Todas las demás características de fprintf() son idénticas a las de printf().

Control de la pantalla de texto

El control de la pantalla puede establecerse por dos vías. En primer lugar, Turbo C proporciona gran número de funciones para controlar la pantalla tanto en modo texto como en modo gráfico. Estudiaremos en este apartado algunas funciones de control en modo texto básicas. Todas ellas necesitan que se incluya el archivo de cabecera conio.h. Otra forma de controlar la pantalla es por medio de secuencias de escape ANSI.

Funciones de biblioteca

Función clrscr(): Borra la pantalla y sitúa el cursor en la esquina superior izquierda. No necesita argumentos ni devuelve ningún valor.

Función clreol(): Borra una línea de la pantalla desde la posición del cursor hasta el final de dicha línea. Tampoco necesita argumentos ni devuelve valor alguno.

Funciones insline() y delline(): La función insline() inserta una línea en blanco debajo de la del cursor, desplazando el resto una línea hacia abajo. Análogamente, la función delline() elimina la línea en donde está el cursor, desplazando las de debajo hacia arriba.

Funciones gotoxy(), wherex() y wherey(): La función gotoxy() se encarga del posicionamiento del cursor. Se escribe

int fila, columna;

...

...

gotoxy (columna, fila);

Las funciones wherex() y wherey() devuelven las coordenadas de la posición actual del cursor:

int fila, columna;

...

...

columna = wherex ();

fila = wherey ();

En estas 3 funciones, las variables fila y columna deben declararse de tipo int.

Función movetext(): Copia texto de una zona de la pantalla a otra. La sintaxis de esta función es

int x1, y1, x2, y2, x3, y3;

...

...

movetext (y1, x1, y2, x2, y3, x3);

siendo:

  • x1, y1: columna, fila de la esquina superior izquierda de la zona de la pantalla a desplazar.

  • x2, y2: ídem de la esquina inferior derecha.

  • x3, y3: columna, fila de la esquina superior izquierda de la pantalla a donde se desplaza el texto.

La función no borra el texto de la posición original. Devuelve 0 si alguna coordenada está fuera de rango, y 1 en caso contrario.

Funciones highvideo(), lowvideo() y normvideo(): Las dos primeras ponen, respectivamente, el texto de la pantalla en alta y baja intensidad. La función normvideo() restaura la intensidad de la pantalla al estado en que se encontraba al iniciarse el programa.

Funciones textcolor(), textbackground() y textattr(): La función textcolor() establece el color del texto que se presenta a partir del momento en que se ejecuta la función.

textcolor (color_de_carácter);

El parámetro color_de_carácter es un número comprendido entre 0 y 15. Cada uno de estos números tiene asociado un color. Además, en el archivo conio.h se define una macro para cada color. Esto queda reflejado en la tabla siguiente:

VALOR

COLOR

MACRO

0

Negro

BLACK

1

Azul

BLUE

2

Verde

GREEN

3

Turquesa

CYAN

4

Rojo

RED

5

Morado

MAGENTA

6

Marrón

BROWN

7

Blanco

LIGHTGRAY

8

Gris

DARKGRAY

9

Azul intenso

LIGHTBLUE

10

Verde intenso

LIGHTGREEN

11

Turquesa intenso

LIGHTCYAN

12

Rojo intenso

LIGHTRED

13

Morado intenso

LIGHTMAGENTA

14

Amarillo

YELLOW

15

Blanco intenso

WHITE

128

Parpadeo

BLINK

Teniendo esto en cuenta, para conseguir que un texto se presente, por ejemplo, en color verde, previamente a su escritura debe hacerse

textcolor (2);

o bien

textcolor (GREEN);

Sin embargo, esto no tiene efecto si se utilizan las funciones printf(), puts(), gets() y putchar(). En su lugar, deben utilizarse las funciones cprintf(), cputs(), cgets() y putch(), respectivamente. Sigue siendo válida la función getche().

Para conseguir el parpadeo del carácter debe hacerse una operación OR entre el color y el valor 128 (BLINK). Por lo tanto, si queremos presentar un texto en amarillo parpadeante debemos escribir

textcolor (YELLOW | BLINK);

La función textbackground() establece el color de fondo para todo texto que se escriba en pantalla a continuación.

textbackground (color_de_fondo);

siendo color_de_fondo un valor comprendido entre 0 y 7, correspondiente a la tabla anterior.

La función textattr() establece el byte de atributo completo (color de carácter, color de fondo, parpadeo si/no e intensidad alta/baja). Se escribe

textattr (atributo);

donde atributo es un byte cuyo significado se muestra a continuación

7

6

5

4

3

2

1

0

P

F

F

F

I

C

C

C

donde CCC son los bits que codifican el color del carácter, I es el bit de intensidad, FFF indican color de fondo, y P es el bit de parpadeo. La forma más cómoda de usar esta función es la siguiente: se multiplica el número del color de fondo de la tabla por 16 y se hace una operación OR con el color de carácter. Si además se quiere que el texto parpadee, debe hacerse una operación OR con el valor 128 (BLINK). Así, para obtener un texto en amarillo parpadeando sobre fondo azul, debe hacerse:

textattr (YELLOW | BLINK | BLUE * 16);

Función textmode(): Asigna un determinado modo de vídeo a la pantalla de texto:

textmode (modo_de_vídeo);

Los valores permitidos para modo_de_vídeo y las macros asociadas se muestran en la tabla siguiente.

MODO DE

VÍDEO

DESCRIPCIÓN

MACRO

0

Blanco y negro, 40 columnas

BW40

1

Color, 40 columnas

CO40

2

Blanco y negro, 80 columnas

BW80

3

Color, 80 columnas

CO80

7

Monocromo

MONO

-1

Modo anterior

LASTMODE

Al asignar un modo de vídeo se inicializa la pantalla.

Secuencias de escape ANSI

El archivo ANSI.SYS es un controlador de pantalla y teclado que permite cambiar la presentación de textos y gráficos en pantalla, controlar el cursor y cambiar las asignaciones de las teclas. Cada una de estas funciones se define mediante una secuencia de escape ANSI, que es una cadena de caracteres que comienza por los caracteres ESC [, siendo ESC el carácter ESCAPE, de código ASCII 27 (033 octal). Estas secuencias de escape están descritas a continuación.

OPERACIÓN

SECUENCIA

DE ESCAPE

DESCRIPCIÓN

Desplazamientos del cursor

ESC[#;#H

Coloca el cursor en la posición de la pantalla señalada con #;# (el primer número indica la fila y el segundo la columna)

ESC[#A

Mueve el cursor # líneas hacia arriba

ESC[#B

Mueve el cursor # líneas hacia abajo

ESC[#C

Mueve el cursor # columnas hacia la derecha

ESC[#D

Mueve el cursor # columnas hacia la izquierda

ESC[s

Guarda la posición actual del cursor

ESC[u

Recupera la posición del cursor previamente guardada con la secuencia anterior

Borrado

ESC[2J

Borra la pantalla y coloca el cursor en la esquina superior izquierda de la pantalla

ESC[K

Borra todos los caracteres desde la posición actual del cursor hasta el final de la línea

Establecer modo de gráficos

ESC[#;...;#m

Llama a las funciones gráficas especificadas mediante los dígitos #. Estas funciones permanecen activas hasta la siguiente aparición de esta secuencia de escape. Los valores permitidos para # se muestran en la tabla de la página siguiente

Establecer modo de vídeo

ESC[=#h

Cambia el ancho o el tipo de pantalla. Los valores permitidos para # se muestran en la tabla de la página siguiente

ESC[=#l

Restablece el modo utilizando los mismos valores que utiliza la secuencia anterior, salvo el modo 7 que desactiva el ajuste automático de línea. El último carácter de la secuencia es la L minúscula

Reasignación de cadenas para el teclado

ESC[#;cad;#p

Permite cambiar la definición de las teclas a una cadena específica. El símbolo # representa el código o códigos generados por la tecla a reasignar. cad es el código ASCII correspondiente a un solo carácter o a una cadena entre comillas.

Ejemplo 1º:

ESC[65;66p convierte la A en B.

Ejemplo 2º:

ESC[0;59;"CLS";13p Asigna a la tecla F1 (que genera los códigos 0 y 59) la cadena CLS junto con (código 13).

Valores permitidos

ATRIBUTOS

0

Desactiva todos los atributos

para # en la

DE TEXTO

1

Alta intensidad activada

secuencia de escape

4

Subrayado (monitor monocromo)

ESC[#;...;#m

5

Parpadeo activado

7

Vídeo inverso activado

8

Oculto activado

COLOR DE

30

Negro

CARÁCTER

31

Rojo

32

Verde

33

Amarillo

34

Azul

35

Magenta

36

Violeta

37

Blanco

COLOR DE

40

Negro

FONDO

41

Rojo

42

Verde

43

Amarillo

44

Azul

45

Magenta

46

Violeta

47

Blanco

Valores permitidos

0

40x25 monocromo (texto)

para # en la

1

40x25 color (texto)

secuencia de escape

2

80x25 monocromo (texto)

ESC[=#h

3

80x25 color (texto)

4

320x200 color (gráficos)

5

320x200 monocromo (gráficos)

6

640x200 monocromo (gráficos)

7

Activa ajuste automático de línea

13

320x200 color (gráficos)

14

640x200 color (gráficos 16 colores)

15

640x350 mono (gráficos 2 colores)

16

640x350 color (gráficos 16 colores)

17

640x480 mono (gráficos 2 colores)

18

640x480 color (gráficos 16 colores)

19

320x200 color (gráficos 256 colores)

Una secuencia de escape ANSI se envía, por ejemplo, mediante la función printf(). Con ello no se visualizan los caracteres de la secuencia de escape, sino que se consigue el efecto descrito para cada una de ellas. Pero para que estas secuencias tengan el efecto esperado es necesario instalar el controlador ANSI.SYS en el archivo CONFIG.SYS mediante una sentencia DEVICE o DEVICEHIGH. La sintaxis de la instalación de este controlador es:

DEVICE = [unidad:] [ruta] ANSI.SYS

de modo que si el archivo ANSI.SYS está en el directorio \DOS de la unidad C:, en el fichero CONFIG.SYS debe haber una línea

device = c:\dos\ansi.sys

o, si se desea instalar en memoria superior

devicehigh = c:\dos\ansi.sys

Veamos algunos ejemplos que ilustran el uso de estas secuencias de escape.

Posicionamiento del cursor: La secuencia de escape para posicionar el cursor es

ESC [f;cH (f = fila, c = columna)

Para situar el cursor en la fila 5, columna 20, se hace

printf ("\033[5;20H");

y produce exactamente el mismo efecto que

gotoxy (20, 5);

No obstante para este tipo de operaciones es más conveniente definir una función que reciba en los parámetros las coordenadas:

pon_cursor (int fila, int columna)

{

printf ("\033[%d;%dH", fila, columna);

}

En un programa se llamaría a esta función, por ejemplo, mediante

pon_cursor (5, 20);

Borrado de pantalla: La secuencia ANSI que borra la pantalla es

ESC [2J

Por tanto, la sentencia

printf ("\033[2J");

produce el mismo efecto que la función de biblioteca clrscr(). Se puede abreviar la escritura de esta secuencia mediante una macro como

#define CLS printf ("\033[2J")

y utilizar en el programa sentencias

CLS;

Redefinición de teclas: Mostraremos el uso de esta secuencia mediante un ejemplo que asigna a la tecla F1 (que al ser pulsada genera los códigos 0 y 59) la cadena de caracteres DIR C:/P ↵. Esto se consigue con la secuencia

ESC [0;59;"DIR C:/P";13p

Con una función printf() esto se escribe

printf ("\033[0;59;\"DIR C:/P\";13p");

o también

printf ("\033[0;59;%c%s%c;13p", 34, "DIR C:/P", 34);

donde hay que tener en cuenta que el código ASCII del carácter comilla doble (") es 34.

Redireccionamiento de la E/S

Las operaciones de E/S realizadas por funciones referidas a la consola (printf(), scanf(), ...) pueden redirigirse a otros dispositivos mediante los operadores

> redirección de la salida

< redirección de la entrada

Redirección de la salida

Sea el programa de la página 2, compilado y linkado como DOCENA.EXE. Si desde el indicador del DOS escribimos:

C:\> docena >prn ↵

la frase "Una docena son 12 unidades" no se muestra en pantalla, sino que se dirige al dispositivo prn (impresora). Se puede también redireccionar la frase a un fichero de texto llamado, por ejemplo, FRASE.TXT, mediante

C:\> edad >frase.txt ↵

Esta orden crea en el directorio raíz un fichero de texto llamado FRASE.TXT que almacena la frase "Una docena son 12 unidades". Si el fichero ya existe, se pierde su contenido anterior.

Cada vez que se redirecciona la salida a un fichero, éste se crea de nuevo. Así, la secuencia

C:\> prog1 >fich.txt ↵

C:\> prog2 >fich.txt ↵

crea un archivo FICH.TXT que almacena la salida únicamente de PROG2. Si se desea añadir la salida de un programa a un fichero existente sin destruir su contenido, se utiliza el operador >>. La secuencia

C:\> prog1 >fich.txt ↵

C:\> prog2 >>fich.txt ↵

almacena en FICH.TXT la salida de ambos programas PROG1 y PROG2.

Redirección de la entrada

Sea ahora el programa PIES.C de la página 5 compilado y linkado como PIES.EXE. Creemos un fichero de texto llamado DATO.DAT que almacene el número 3. Esto se consigue desde el indicador del DOS mediante la secuencia

C:\> copy con dato.dat ↵

3 ↵

^Z ↵

C:\>

Si escribimos

C:\> pies <dato.dat ↵

la sentencia scanf() del programa ya no lee el dato del teclado. Al estar la entrada redireccionada, lo toma del archivo DATO.DAT. Veríamos entonces en pantalla los mensajes generados por printf(). Algo como

¿Pies?:

3 pies = 0.925200 metros

Redirección de la entrada y de la salida

Se puede redireccionar a la vez tanto la entrada como la salida. Si escribimos

C:\> pies <dato.dat >mensajes.txt ↵

no veremos en pantalla nada, y se crea un fichero de texto en el directorio raíz llamado MENSAJES.TXT que almacena los mensajes generados por las dos sentencias printf().

Ejercicios

1. Escribe un programa que lea del teclado un código ASCII (entero comprendido entre 0 y 255) y presente en pantalla el carácter correspondiente.

2. Escribe un programa que lea del teclado un carácter cualquiera y presenta en pantalla su código ASCII en decimal, octal y hexadecimal.

3. Escribe un programa que lea del teclado dos números en coma flotante cuya parte entera se asume que no supera 3 dígitos, y muestre en pantalla su suma ajustada a la derecha. Por ejemplo, si los números son 23.6 y 187.54 el programa debe mostrar:

23,60

187,54

----------

211,14

4. Escribe un programa que lea 2 números enteros de 3 dígitos e imprima su producto. Por ejemplo, si los números son 325 y 426 se presentará en el formato

325

x 426

------------

1950

650

1300

------------

138450

5. La fecha de Pascua corresponde al primer Domingo después de la primera Luna llena que sigue al equinoccio de Primavera, y se calcula con las siguientes expresiones:

A = resto de (año / 19)

B = resto de (año / 4)

C = resto de (año / 7)

D = resto de (19 * A + 24) / 30

E = resto de (2 * B + 4 * C + 6 * D + 5) / 7

N = 22 + D + E

en el que N indica el número del día del mes de Marzo (Abril si N > 31, en cuyo caso el día es N - 31) correspondiente al Domingo de Pascua. Escribe un programa que acepte un año por teclado y muestre en pantalla la fecha del primer Domingo de Pascua con el formato dd/mm/aaaa.

6. Escribe un programa que lea del teclado los siguientes datos de 2 personas: nombre, edad, altura y peso. El programa enviará a impresora un listado con el formato:

NOMBRE EDAD ALTURA PESO

xxxxxxxxxxxxxxxxxxxxxx xx xx,x xxx,xx

xxxxxxxxxxxxxxxxxxxxxx xx xx,x xxx,xx

Media: xx,xx xx,xx xxx,xx