#define
con objeto de construir constantes, de forma similar a la siguiente:
#define PRESIDENTES 12 #define VICEPRESIDENTES 12 #define CONCIERTOS_ADMINISTRATIVOS 12 #define BARES 12De esta forma, al llegar la reorganización basta con cambiar los valores de estas constantes en un único lugar, y el compilador se encarga de realizar todos los cambios rápidamente y sin errores.
enum {lista_de_identificadores};Los identificadores irán separados mediante comas. Opcionalmente, cualquiera de los identificadores puede recibir un valor inicial entero. Esta definición da lugar a los identificadores incluidos, que toman valores enteros partiendo de cero salvo que se les den otros valores iniciales. Una vez efectuada esta declaración, se pueden emplear los identificadores en nuestro programa; véase un ejemplo:
#include<stdio.h> enum {pepe, juan}; int main(void) { printf("juan vale %d\n", juan); return 0; }Como se puede observar, el identificador
juan
pasa a estar disponible y toma automáticamente el valor 1. ¿Cuánto vale
pepe
? enum nombre_de_tipo {lista_de_identificadores};
enum nombre_de_tipo var_1, var_2,..., var_n;Por ejemplo, en el programa siguiente se crea un nuevo tipo enumerado llamado
mis_datos
, para luego declarar dos variables
x
e
y
de este tipo. El programa da valores a estas variables y los muestra en pantalla:
#include<stdio.h> enum mis_datos {pepe, juan}; enum mis_datos x, y; int main(void) { x = pepe; y = juan; printf("x vale %d\n", x); printf("y vale %d\n", y); return 0; }Comentarios.- ¿Cuánto valen
x
e
y
? ¿Se puede añadir
manolo
a la lista de valores del tipo
mis_datos
? ¿Cuánto vale? ¿Qué ocurre si se hace el cambio siguiente?:
enum mis_datos { pepe=33, juan, manolo};
#include <stdio.h> /* Este programa muestra la definición, declaración y utilización de tipos enumerados en C, enumeraciones. Las enumeraciones adoptan valores internos desde 0 en adelante, salvo indicación expresa en contra. */ /* Una enumeración anónima. */ enum {rojizo, verdoso, azulado} una; /* Un tipo enumerado */ enum arco_iris {rojo, anaranjado, amarillo, verde, azul, agnil, violeta}; /* Una variable de un tipo enumerado */ enum arco_iris p; /* Una enumeración con cambios arbitrarios en los valores */ enum aleatoria { primero = -7, segundo, tercero, cuarto = 25, quinto, sexto } ale; void main(void) { printf("E N U M E R A C I O N E S"); /* Manejo de enumeraciones anónimas */ printf("\n\nEnumeración anónima, enum (rojizo, verdoso, azulado) una;"); printf("\n\nEl tamaño de azulado es %d y su valor es %d", sizeof(azulado), azulado); una = verdoso; printf("\n\nEl tamaño de una (= verdoso) es %d y su valor es %d", sizeof(una), una); /* Manejo de tipos enumerados */ printf("\n\nEnumeración con nombre arco_iris =\n"); printf(" (rojo, anaranjado, amarillo, verde, azul, agnil, violeta)."); printf("\n\nEl tamaño de verde es %d y su valor es %d", sizeof(rojo), verde); p = violeta; printf("\n\nEl tamaño de p (= violeta) es %d y su valor es %d", sizeof(p), p); printf("\n\nEl tipo enumerado aleatoria es asi:\n\n"); printf("enum aleatoria { primero = -7, segundo, tercero, cuarto = 25, quinto, sexto } ale;\n"); printf("\n\nValores adoptados por los elementos de ale:\n"); printf("\n\nEl valor de primero es %d\n", primero); printf("\nEl valor de segundo es %d\n", segundo); printf("\nEl valor de tercero es %d\n", tercero); printf("\nEl valor de cuarto es %d\n", cuarto); printf("\nEl valor de quinto es %d\n", quinto); printf("\nEl valor de sexto es %d\n", sexto); printf("\n\nLas enumeraciones ocupan 1 byte, y admiten como máximo 256 elementos.\n"); printf("Las enumeraciones no se pueden leer ni escribir directamente, y aumentan\n"); printf("de uno en uno a partir del valor establecido para un elemento.\n"); printf("\n\nTerminación normal del programa.\n"); }
/* Construir un programa que muestre un menú y e indique la opción seleccionada, empleando una enumeración y una lista de cadenas. */ #include<stdio.h> #include<stdlib.h> #define NUM_OPCIONES 5 int main(int argc, char * argv[]) { enum {Nuevo, Abrir, Guardar, Cerrar, Salir}; char menu[][10] = {"Nuevo", "Abrir", "Guardar", "Cerrar", "Salir"}; char opcion; int i, caso; do { /* Visualizar menú y leer la opción */ printf("\nSeleccione una opción:\n\n"); for(i=0;i<NUM_OPCIONES;i++) printf("%s (%d) ", menu[i], i); printf(" : "); scanf("%c", &opcion); fpurge(stdin); /* Mostrar en pantalla la opción seleccionada */ caso = opcion - '0'; switch(caso) { case Nuevo: printf("\nSe ha seleccionado la opción %s\n", menu[caso]); break; case Abrir: printf("\nSe ha seleccionado la opción %s\n", menu[caso]); break; case Guardar: printf("\nSe ha seleccionado la opción %s\n", menu[caso]); break; case Cerrar: printf("\nSe ha seleccionado la opción %s\n", menu[caso]); break; case Salir: printf("\nSe ha seleccionado la opción %s\n", menu[caso]); break; default: printf("\n\nOpción incorrecta\n\n"); break; } } while(caso != Salir); printf("\n\nFin del programa\n\n"); return 0; } /* Seleccione una opción: Nuevo (0) Abrir (1) Guardar (2) Cerrar (3) Salir (4) : 0 Se ha seleccionado la opción Nuevo Seleccione una opción: Nuevo (0) Abrir (1) Guardar (2) Cerrar (3) Salir (4) : 1 Se ha seleccionado la opción Abrir Seleccione una opción: Nuevo (0) Abrir (1) Guardar (2) Cerrar (3) Salir (4) : 2 Se ha seleccionado la opción Guardar Seleccione una opción: Nuevo (0) Abrir (1) Guardar (2) Cerrar (3) Salir (4) : 3 Se ha seleccionado la opción Cerrar Seleccione una opción: Nuevo (0) Abrir (1) Guardar (2) Cerrar (3) Salir (4) : 4 Se ha seleccionado la opción Salir Fin del programa */
opcion
con '4' sino
caso
con
Salir
... y el método debe funcionar siempre, sin cambios. Obsérvese también que se capturan los posibles errores del usuario: si el valor de caso no aparece en la lista de sentencias case, se ejecuta el
default
correspondiente. Por último, el uso de
fpurge(stdin)
garantiza la eliminación de caracteres restantes en el búfer de teclado, quedando este limpio y preparado para nuevas lecturas. Esto tendrá importancia en aquellos programas en que la activación de una opción desencadene la lectura de datos a partir del teclado.
/* Construir una calculadora que permita convertir entre euros y pesetas, empleando una enumeración. */ #include<stdio.h> #include<stdlib.h> #define NUM_OPCIONES 3 int main(int argc, char * argv[]) { enum {Paso_a_Euros, Paso_a_Pesetas, Salir}; char menu[][20] = {"Pasar a Euros", "Pasar a Ptas", "Salir"}; char opcion; int i, caso; float numpesetas, numeuros; do { /* Visualizar menú y leer la opción */ printf("\nSeleccione una opción:\n\n"); for(i=0;i<NUM_OPCIONES;i++) printf("%s (%d) ", menu[i], i); printf(" : "); scanf("%c", &opcion); fpurge(stdin); /* Mostrar en pantalla la opción seleccionada */ caso = opcion - '0'; switch(caso) { case Paso_a_Euros: printf("\nEscriba el número de pesetas: "); scanf("%f", &numpesetas); numeuros = numpesetas / 166.386; printf("\n%10.3f Pesetas equivalen a %10.2f€\n", numpesetas, numeuros); fpurge(stdin); break; case Paso_a_Pesetas: printf("\nEscriba el número de euros: "); scanf("%f", &numeuros); numpesetas = numeuros * 166.386; printf("\n%10.2f€ equivale a %10.3f Pesetas\n", numeuros, numpesetas); fpurge(stdin); break; case Salir: printf("\nSaliendo...\n"); break; default: printf("\n\nOpción incorrecta\n\n"); break; } } while(caso != Salir); printf("\n\nFin del programa\n\n"); return 0; } /* Resultado de la ejecución: Seleccione una opción: Pasar a Euros (0) Pasar a Ptas (1) Salir (2) : 0 Escriba el número de pesetas: 166.386 166.386 Pesetas equivalen a 1.00€ Seleccione una opción: Pasar a Euros (0) Pasar a Ptas (1) Salir (2) : 1 Escriba el número de euros: 1.0 1.00€ equivalen a 166.386 Pesetas Seleccione una opción: Pasar a Euros (0) Pasar a Ptas (1) Salir (2) : 2 Saliendo... Fin del programa */Notas
/* Construir un programa que aplique distintas desgravaciones fiscales en función del estado civil del usuario. El programa recibirá como datos la base imponible y el estado del usuario, proporcionando como resultado la cantidad desgravada. */ #include<stdio.h> #include<stdlib.h> #define NUM_OPCIONES 6 int main(int argc, char * argv[]) { enum {Soltero, Casado, Viudo, Separado, Divorciado, Salir}; char menu[][20] = {"Soltero", "Casado", "Viudo", "Separado", "Divorciado", "Salir"}; float desgravacion[] = {1000.0, 2000.0, 3000.0, 4000.0, 5000.0}; float base_imponible, cantidad_final; char opcion; int i, caso; system("clear"); /* Para limpiar la pantalla antes empezar la ejecución */ fpurge(stdin); do { printf("\nEspecifique su estado civil (5 para salir):\n\n"); for(i=0;i<NUM_OPCIONES;i++) printf("[%d] %s", i, menu[i]); printf(" : "); scanf("%c", &opcion); fpurge(stdin); caso = opcion - '0'; switch(caso) { case Soltero: case Casado: case Viudo: case Separado: case Divorciado: { do { printf("\n\nEspecifique su base imponible (> 5000€): "); scanf("%f", &base_imponible); fpurge(stdin); } while (base_imponible < 5000.0); cantidad_final = base_imponible - desgravacion[caso]; printf("La cantidad final a pagar es de %10.2f€.\n\n", cantidad_final); break; } case Salir: printf("\nSaliendo...\n\n"); break; default: printf("\n\nOpción incorrecta\n\n"); break; } } while(caso != Salir); printf("\n\nFin del programa\n\n"); return 0; } /* Resultado de la ejecución: Especifique su estado civil (5 para salir): [0] Soltero[1] Casado[2] Viudo[3] Separado[4] Divorciado[5] Salir : 0 Especifique su base imponible (> 5000€): 5000 La cantidad final a pagar es de 4000.00€. Especifique su estado civil (5 para salir): [0] Soltero[1] Casado[2] Viudo[3] Separado[4] Divorciado[5] Salir : 1 Especifique su base imponible (> 5000€): 5000 La cantidad final a pagar es de 3000.00€. Especifique su estado civil (5 para salir): [0] Soltero[1] Casado[2] Viudo[3] Separado[4] Divorciado[5] Salir : 2 Especifique su base imponible (> 5000€): 5000 La cantidad final a pagar es de 2000.00€. Especifique su estado civil (5 para salir): [0] Soltero[1] Casado[2] Viudo[3] Separado[4] Divorciado[5] Salir : 3 Especifique su base imponible (> 5000€): 5000 La cantidad final a pagar es de 1000.00€. Especifique su estado civil (5 para salir): [0] Soltero[1] Casado[2] Viudo[3] Separado[4] Divorciado[5] Salir : 4 Especifique su base imponible (> 5000€): 5000 La cantidad final a pagar es de 0.00€. Especifique su estado civil (5 para salir): [0] Soltero[1] Casado[2] Viudo[3] Separado[4] Divorciado[5] Salir : 5 Saliendo... Fin del programa */Notas
switch()
que gobierna el programa se han agrupado varias todas las opciones que requieren indicar la base imponible. De este modo, si el usuario decide
Salir
, no se le pregunta más; si por el contrario decide calcular la cantidad final a ingresar (base imponible menos desgravación) entonces se le pregunta su estado civil y base imponible. No se admiten bases imponibles que dieran lugar a una cantidad a devolver.
Se ha seleccionado la opción Cortar del menú Edición.
/* Construir un programa dotado de un menú de Archivo, otro de Edición y otro de Texto. El menú Archivo ofrecerá las opciones Nuevo, Abrir, Guardar, Cerrar y Salir. El menú Edición ofrecerá las opciones Deshacer, Cortar, Copiar y Pegar. El menú Texto ofrecerá las opciones Menor, Medio y Mayor. El programa debe mostrar una barra con los menús Archivo, Edición y Texto; cuando el usuario seleccione uno de ellos, aparecerán las opciones correspondientes a ese menú y el usuario podrá seleccionar una de ellas. Hecho esto, el programa mostrará el menú y la opción seleccionados, en la forma siguiente: Se ha seleccionado la opción Cortar del menú Edición. */ #include<stdio.h> #include<stdlib.h> #define NUM_OPCIONES_BARRA 3 #define NUM_OPCIONES_ARCHIVO 5 #define NUM_OPCIONES_EDICION 5 #define NUM_OPCIONES_TEXTO 3 /* Enumeraciones varias. Disponemos de identificadores para todos los menús y todas las opciones de cada uno de ellos. */ enum {Archivo, Edicion, Texto}; enum {Nuevo, Abrir, Guardar, Cerrar, Salir}; enum {Deshacer, Cortar, Copiar, Pegar, Borrar}; enum {Menor, Medio, Mayor}; /* Listas de cadenas asociadas a las distintas enumeraciones. Es imprescindible que coincida el nombre de los identificadores y el orden en que aparecen estos en las enumeraciones. */ char barraMenus[][10] = { "Archivo", "Edicion", "Texto"}; char menuArchivo[][10] = { "Nuevo", "Abrir", "Guardar", "Cerrar", "Salir"}; char menuEdicion[][10] = { "Deshacer", "Cortar", "Copiar", "Pegar", "Borrar"}; char menuTexto[][10] = { "Menor", "Medio", "Mayor"}; int menu_seleccionado(void); int opcion_seleccionada(int numero_menu); int main(int argc, char * argv[]) { int num_menu, num_opcion; system("clear"); do { /* Visualizar menú y leer la opción */ num_menu = menu_seleccionado(); num_opcion = opcion_seleccionada(num_menu); switch(num_menu) { case Archivo: printf("\nSeleccionada la opción %s del menú %s\n", menuArchivo[num_opcion], barraMenus[num_menu]); break; case Edicion: printf("\nSeleccionada la opción %s del menú %s\n", menuEdicion[num_opcion], barraMenus[num_menu]); break; case Texto: printf("\nSeleccionada la opción %s del menú %s\n", menuTexto[num_opcion], barraMenus[num_menu]); break; } } while(!(num_menu == Archivo && num_opcion == Salir)); printf("\n\nFin del programa\n\n"); return 0; } int menu_seleccionado(void) { int i; int n; do { for(i=0;i<NUM_OPCIONES_BARRA;i++) printf("[%d] %s ", i, barraMenus[i]); scanf("%d", &n); fpurge(stdin); } while ( n< Archivo || n > Texto); return n; } int opcion_seleccionada(int numero_menu){ int i,n; switch(numero_menu) { case Archivo: do { for(i=0;i<NUM_OPCIONES_ARCHIVO;i++) printf("[%d] %s ", i, menuArchivo[i]); scanf("%d", &n); } while (n < Nuevo || n > Salir); break; case Edicion: do { for(i=0;i<NUM_OPCIONES_EDICION;i++) printf("[%d] %s ", i, menuEdicion[i]); scanf("%d", &n); } while (n < Deshacer || n > Borrar); break; case Texto: do { for(i=0;i<NUM_OPCIONES_TEXTO;i++) printf("[%d] %s ", i, menuTexto[i]); scanf("%d", &n); } while (n < Menor || n > Mayor); break; } return n; } /* Resultado de la ejecución del programa: [0] Archivo [1] Edicion [2] Texto 0 [0] Nuevo [1] Abrir [2] Guardar [3] Cerrar [4] Salir 0 Seleccionada la opción Nuevo del menú Archivo [0] Archivo [1] Edicion [2] Texto 0 [0] Nuevo [1] Abrir [2] Guardar [3] Cerrar [4] Salir 1 Seleccionada la opción Abrir del menú Archivo [0] Archivo [1] Edicion [2] Texto 0 [0] Nuevo [1] Abrir [2] Guardar [3] Cerrar [4] Salir 2 Seleccionada la opción Guardar del menú Archivo [0] Archivo [1] Edicion [2] Texto 0 [0] Nuevo [1] Abrir [2] Guardar [3] Cerrar [4] Salir 3 Seleccionada la opción Cerrar del menú Archivo [0] Archivo [1] Edicion [2] Texto 0 [0] Nuevo [1] Abrir [2] Guardar [3] Cerrar [4] Salir 4 Seleccionada la opción Salir del menú Archivo */Notas
menu_seleccionado()
y
opcion_seleccionada()
, que hacen más comprensible el programa. Otra posible solución sería construir una tabla de cadenas, en que cada fila correspondería a las opciones de un cierto menú; las columnas serían opciones homólogas de distintos menús. Esta organización se podría mantener en disco, con objeto de leerla en el momento del arranque y mostrar una u otra colección de menús y opciones en función de las preferencias del usuario. Podría ser algo así:
char tm[][6] = { {"Archivo", "Nuevo", "Abrir", "Cerrar", "Guardar", "Salir"}, {"Edicion", "Deshacer", "Cortar", "Copiar", "Pegar", "Borrar"}, {"Texto", "Menor", "Medio", "Mayor"}, };¿Sabría el lector adaptar este ejercicio a la nueva estructura de datos?
/* Construir un programa que admita el nombre de un usuario y lo muestre en mayúsculas o minúsculas a voluntad del usuario, que utilizará las opciones de un menú. */ #include<stdio.h> #include<stdlib.h> #include <ctype.h> /* Para poder efectuar el paso a mayúsculas o minúsculas */ #define NUM_OPCIONES 4 void pedir(char nombre[]); void mostrar_en_mayusculas(char nombre[]); void mostrar_en_minusculas(char nombre[]); int main(int argc, char * argv[]) { enum {Escribir, EnMayusculas, EnMinusculas, Salir}; char menu[][20] = {"Escribir nombre", "Ver en mayúsculas", "Ver en minúsculas", "Salir"}; int nombre_leido; char nombre[80]; char opcion; int i, caso; system("clear"); /* Suponiendo una ejecución en Unix. En otras plataformas es "cls" */ do { /* Visualizar menú y leer la opción */ printf("\nSeleccione una opción:\n\n"); for(i=0;i<NUM_OPCIONES;i++) printf("%s (%d) ", menu[i], i); printf(" : "); scanf("%c", &opcion); fpurge(stdin); /* Mostrar en pantalla la opción seleccionada */ caso = opcion - '0'; switch(caso) { case Escribir: pedir(nombre); nombre_leido = 1; break; case EnMayusculas: if (nombre_leido) mostrar_en_mayusculas(nombre); else printf("\n\nPor favor, escriba primero el nombre.\n"); break; case EnMinusculas: if (nombre_leido) mostrar_en_minusculas(nombre); else printf("\n\nPor favor, escriba primero el nombre.\n"); break; case Salir: printf("\nSaliendo...\n"); break; default: printf("\n\nOpción incorrecta\n\n"); break; } } while(caso != Salir); printf("\n\nFin del programa\n\n"); return 0; } void pedir(char nombre[]) { int n = 80; int i; printf("\nPor favor, escriba su nombre: "); fgets(nombre, n ,stdin); printf("\nGracias, %s\n", nombre); } void mostrar_en_mayusculas(char nombre[]) { int n = strlen(nombre); int i; printf("\n\nSu nombre en mayúsculas es: "); for(i=0;i<n;i++) printf("%c", toupper(nombre[i])); printf("\n\n"); } void mostrar_en_minusculas(char nombre[]) { int n = strlen(nombre); int i; printf("\n\nSu nombre en minúsculas es: "); for(i=0;i<n;i++) printf("%c", tolower(nombre[i])); printf("\n\n"); } /* Resultado de la ejecución del programa: Seleccione una opción: Escribir nombre (0) Ver en mayúsculas (1) Ver en minúsculas (2) Salir (3) : 0 Por favor, escriba su nombre: coti Gracias, coti Seleccione una opción: Escribir nombre (0) Ver en mayúsculas (1) Ver en minúsculas (2) Salir (3) : 1 Su nombre en mayúsculas es: COTI Seleccione una opción: Escribir nombre (0) Ver en mayúsculas (1) Ver en minúsculas (2) Salir (3) : 2 Su nombre en minúsculas es: coti Seleccione una opción: Escribir nombre (0) Ver en mayúsculas (1) Ver en minúsculas (2) Salir (3) : 3 Saliendo... Fin del programa */Notas
nombre_leido
, que impide que el usuario intente visualizar en mayúsculas o minúsculas un nombre antes de introducirlo. Las funciones
toupper()
y
tolower()
, declaradas en
ctype.h
, permiten efectuar la transformación deseada. Obsérvese tambien el uso de
fgets()
para garantizar que el número de caracteres leídos no supera las dimensiones del fragmento de memoria reservado al efecto. Se podría haber utilizado
gets()
, pero se deplora su uso por plantear precisamente este problema: la imposibilidad de asegurar que no se leerán más caracteres que los reservados al efecto. Otra solución consiste en determinar por anticipado el número de caracteres disponibles para su lectura, empleando la función
fgetln()
, descrita
aquí
, y de cuyo uso se muestra un ejemplo
aquí
./* Construir un programa que pida el nombre de un archivo de texto y muestre su contenido en pantalla o lo almacene en otro archivo, a voluntad del usuario. */ #include<stdio.h> #include<stdlib.h> #define NUM_OPCIONES 4 #define MAX_CHARS_NOMBRE 80 char archivo[MAX_CHARS_NOMBRE]; void nombrar(char n[]); void mostrar_en_pantalla(char n[]); void guardar_en_disco(char n[]); int main(int argc, char * argv[]) { enum {Nombrar, Pantalla, Disco, Salir}; char menu[NUM_OPCIONES][30] = {"Nombrar archivo", "Mostrar en pantalla", "Guardar en disco", "Salir"}; char opcion; int i, caso; do { /* Visualizar menú y leer la opción */ printf("\nSeleccione una opción:\n\n"); for(i=0;i<NUM_OPCIONES;i++) printf("%s (%d) ", menu[i], i); printf(" : "); scanf("%c", &opcion); fpurge(stdin); /* Ejecutar la opción seleccionada */ caso = opcion - '0'; switch(caso) { case Nombrar: nombrar(archivo); break; case Pantalla: mostrar_en_pantalla(archivo); break; case Disco: guardar_en_disco(archivo); break; case Salir: printf("\nSaliendo...\n", menu[caso]); break; default: printf("\n\nOpción incorrecta\n\n"); break; } } while(caso != Salir); printf("\n\nFin del programa\n\n"); return 0; } void nombrar(char n[]){ printf("\nPor favor, escriba el nombre del archivo que desea tratar (INTRO para salir): "); fgets(n,MAX_CHARS_NOMBRE, stdin); if (n[0] == '\n') { printf("\nPrograma interrumpido por el usuario... Saliendo.\n"); exit(1); } n[strlen(n)-1] = '\0'; printf("\nEl nombre del archivo seleccionado es : >%s<\n\n", n); }; void mostrar_en_pantalla(char n[]){ FILE * fp; char letra = 1; if (!(fp = fopen(n,"r"))) printf("\nEl archivo indicado no existe en este directorio.\n"); else { printf("\nEl archivo %s comienza en la línea siguiente a la flecha:\n\n------>\n", n); letra = fgetc(fp); while (letra != -1) { putc(letra, stdout); letra = fgetc(fp); } fclose(fp); printf("\n<--------\n\nEl archivo %s acaba en la línea anterior a la flecha.\n\n", n); } } void guardar_en_disco(char n[]){ char copia[MAX_CHARS_NOMBRE]; FILE * entrada, *salida; char letra = 1; printf("\nPor favor, escriba el nombre del archivo COPIA (INTRO para salir): "); fgets(copia,MAX_CHARS_NOMBRE, stdin); if (copia[0] == '\n') { printf("\nPrograma interrumpido por el usuario... Saliendo.\n"); exit(1); } copia[strlen(copia)-1] = '\0'; salida = fopen(copia, "a"); if (!salida) { printf("\nNo fue posible crear el archivo %s. Saliendo.\n\n", copia); exit(2); } printf("\nEl nombre del archivo copia es : >%s<\n\n", copia); if (!(entrada = fopen(n,"r"))) printf("\nEl archivo indicado no existe en este directorio.\n"); else { letra = fgetc(entrada); while (letra != -1) { putc(letra, salida); letra = fgetc(entrada); } fclose(entrada); fclose(salida); printf("\n\nEl proceso de copia en %s ha teminado.\n\n", copia); } } /* El resultado de la ejecución es como sigue: Seleccione una opción: Nombrar archivo (0) Mostrar en pantalla (1) Guardar en disco (2) Salir (3) : 0 Por favor, escriba el nombre del archivo que desea tratar (INTRO para salir): prueba.txt El nombre del archivo seleccionado es : >prueba.txt< Seleccione una opción: Nombrar archivo (0) Mostrar en pantalla (1) Guardar en disco (2) Salir (3) : 1 El archivo prueba.txt comienza en la línea siguiente a la flecha: ------> Esto es una prueba. <-------- El archivo prueba.txt acaba en la línea anterior a la flecha. Seleccione una opción: Nombrar archivo (0) Mostrar en pantalla (1) Guardar en disco (2) Salir (3) : 2 Por favor, escriba el nombre del archivo COPIA (INTRO para salir): copia.txt El nombre del archivo copia es : >copia.txt< El proceso de copia en copia.txt ha teminado. Seleccione una opción: Nombrar archivo (0) Mostrar en pantalla (1) Guardar en disco (2) Salir (3) : 3 Saliendo... Fin del programa */
nombrar()
tiene al misión de pedir al usuario el nombre del archivo que luego se mostrará en pantalla o se escribirá en disco. Si el usuario pulsa
INTRO
directamente, se entiende que desea salir de programa sin hacer nada. Esto se detecta comparando el primer carácter de n con '\n', que es lo que proporciona
fgets()
cuando se pulsa
INTRO
sin anteponer carácter alguno. Si se escribe algo que pudiera ser un nombre de archivo, se empieza por eliminar el '\n' que habrá proporcionado
fgets()
al final del nombre.
mostrar_en_pantalla()
se intenta abrir el archivo en modo de lectura; si no existe, se comunica este hecho al usuario y se abandona el programa. Si existe, se lee el archivo letra por letra y se va escribiendo en
stdin
, el flujo de pantalla. Finalmente, se cierra el flujo de entrada.
guardar_en_disco()
es necesariamente la más compleja. Comienza por solicitar un nombre para el archivo de copia. Si el nombre es válido (si el usuario no pulsa
INTRO
cuando se solicita el nombre) entonces se abre el archivo en modo de adición, como precaución, para no destruir nunca información. Si no fuera posible abrir el archivo, se notifica al usuario y se abandona el programa. A continuación, se intenta abrir el archivo original. Si no existe, se comunica al usuario y se abandona el programa. Si existe, se lee el flujo
entrada
letra por letra y se va escribiendo en el flujo
salida
. Finalmente, se cierran ambos flujos.
/* Construir un programa que muestre un menú adecuado para leer un fichero de texto y escribirlo en otro fichero en mayúsculas o en minúsculas.*/ #include<stdio.h> #include<stdlib.h> #define NUM_OPCIONES 4 #define MAX_CHARS_NOMBRE 80 char archivo[MAX_CHARS_NOMBRE]; enum {Nombrar, Minusculas, Mayusculas, Salir}; void nombrar(char n[]); void traducir(char n[], int paso); int main(int argc, char * argv[]) { char menu[NUM_OPCIONES][30] = {"Nombrar archivo", "Paso a minúsculas", "Paso a mayúsculas", "Salir"}; char opcion; int i, caso; do { /* Visualizar menú y leer la opción */ printf("\nSeleccione una opción:\n\n"); for(i=0;i<NUM_OPCIONES;i++) printf("%s (%d) ", menu[i], i); printf(" : "); scanf("%c", &opcion); fpurge(stdin); /* Ejecutar la opción seleccionada */ caso = opcion - '0'; switch(caso) { case Nombrar: nombrar(archivo); break; case Minusculas: traducir(archivo, Minusculas); break; case Mayusculas: traducir(archivo, Mayusculas); break; case Salir: printf("\nSaliendo...\n", menu[caso]); break; default: printf("\n\nOpción incorrecta\n\n"); break; } } while(caso != Salir); printf("\n\nFin del programa\n\n"); return 0; } void nombrar(char n[]){ printf("\nPor favor, escriba el nombre del archivo que desea tratar (INTRO para salir): "); fgets(n,MAX_CHARS_NOMBRE, stdin); if (n[0] == '\n') { printf("\nPrograma interrumpido por el usuario... Saliendo.\n"); exit(1); } n[strlen(n)-1] = '\0'; printf("\nEl nombre del archivo seleccionado es : >%s<\n\n", n); }; void traducir(char n[], int paso){ char traduccion[MAX_CHARS_NOMBRE]; FILE * entrada, *salida; char letra = 1; printf("\nPor favor, escriba el nombre del archivo TRADUCIDO (INTRO para salir): "); fgets(traduccion,MAX_CHARS_NOMBRE, stdin); if (traduccion[0] == '\n') { printf("\nPrograma interrumpido por el usuario... Saliendo.\n"); exit(1); } traduccion[strlen(traduccion)-1] = '\0'; salida = fopen(traduccion, "a"); if (!salida) { printf("\nNo fue posible crear el archivo %s. Saliendo.\n\n", traduccion); exit(2); } printf("\nEl nombre del archivo traducido es : >%s<\n\n", traduccion); if (!(entrada = fopen(n,"r"))) printf("\nEl archivo indicado no existe en este directorio.\n"); else { letra = fgetc(entrada); while (letra != -1) { if (paso == Minusculas) letra = tolower(letra); else letra = toupper(letra); putc(letra, salida); letra = fgetc(entrada); } fclose(entrada); fclose(salida); printf("\n\nEl proceso de traducción a %s en %s ha teminado.\n\n", paso==Minusculas ? "minúsculas":"mayúsculas", traduccion); } } /* Resultado de la ejecución Seleccione una opción: Nombrar archivo (0) Paso a minúsculas (1) Paso a mayúsculas (2) Salir (3) : 0 Por favor, escriba el nombre del archivo que desea tratar (INTRO para salir): prueba.txt El nombre del archivo seleccionado es : >prueba.txt< Seleccione una opción: Nombrar archivo (0) Paso a minúsculas (1) Paso a mayúsculas (2) Salir (3) : 1 Por favor, escriba el nombre del archivo TRADUCIDO (INTRO para salir): pruebamin.txt El nombre del archivo traducido es : >pruebamin.txt< El archivo indicado no existe en este directorio. Seleccione una opción: Nombrar archivo (0) Paso a minúsculas (1) Paso a mayúsculas (2) Salir (3) : 0 Por favor, escriba el nombre del archivo que desea tratar (INTRO para salir): prueba.txt El nombre del archivo seleccionado es : >prueba.txt< Seleccione una opción: Nombrar archivo (0) Paso a minúsculas (1) Paso a mayúsculas (2) Salir (3) : 1 Por favor, escriba el nombre del archivo TRADUCIDO (INTRO para salir): pruebamin.txt El nombre del archivo traducido es : >pruebamin.txt< El proceso de traducción a minúsculas en pruebamin.txt ha teminado. Seleccione una opción: Nombrar archivo (0) Paso a minúsculas (1) Paso a mayúsculas (2) Salir (3) : 2 Por favor, escriba el nombre del archivo TRADUCIDO (INTRO para salir): pruebamax.txt El nombre del archivo traducido es : >pruebamax.txt< El proceso de traducción a mayúsculas en pruebamax.txt ha teminado. Seleccione una opción: Nombrar archivo (0) Paso a minúsculas (1) Paso a mayúsculas (2) Salir (3) : 3 Saliendo... Fin del programa [maxus~:] coti% cat pruebamin.txt esto es una prueba. [maxus~:] coti% cat pruebamax.txt ESTO ES UNA PRUEBA. */
#include<stdio.h> /* Este programa muestra la estructura de bits de un valor enumerado. */ struct muchos_bits { unsigned bit1:1; unsigned bit2:1; unsigned bit3:1; unsigned bit4:1; unsigned bit5:1; unsigned bit6:1; unsigned bit7:1; unsigned bit8:1; unsigned bit9:1; unsigned bit10:1; unsigned bit11:1; unsigned bit12:1; unsigned bit13:1; unsigned bit14:1; unsigned bit15:1; unsigned bit16:1; unsigned bit17:1; unsigned bit18:1; unsigned bit19:1; unsigned bit20:1; unsigned bit21:1; unsigned bit22:1; unsigned bit23:1; unsigned bit24:1; unsigned bit25:1; unsigned bit26:1; unsigned bit27:1; unsigned bit28:1; unsigned bit29:1; unsigned bit30:1; unsigned bit31:1; unsigned bit32:1; }; enum VariosValores { Primero, Segundo = -1, Tercero, Cuarto}; union Ejemplo_union { enum VariosValores valor_enumerado; struct muchos_bits bits_union; } union_prueba; enum VariosValores valor_estudiado; void mostrar_valores(union Ejemplo_union eu); int main(int argc, char * argv[]) { printf("Programa de prueba para uniones y enumeraciones.\n\n"); printf("\nLo que sigue es la estructura de bits de los valores\ enumerados Primero, Segundo, Tercero y Cuarto:\n\n"); union_prueba.valor_enumerado = Primero; mostrar_valores(union_prueba); union_prueba.valor_enumerado = Segundo; mostrar_valores(union_prueba); union_prueba.valor_enumerado = Tercero; mostrar_valores(union_prueba); union_prueba.valor_enumerado = Cuarto; mostrar_valores(union_prueba); printf("\n\nTerminación normal del programa.\n"); } void mostrar_valores(union Ejemplo_union eu){ printf("%d",eu.bits_union.bit1); printf("%d",eu.bits_union.bit2); printf("%d",eu.bits_union.bit3); printf("%d",eu.bits_union.bit4); printf("%d",eu.bits_union.bit5); printf("%d",eu.bits_union.bit6); printf("%d",eu.bits_union.bit7); printf("%d",eu.bits_union.bit8); printf("%d",eu.bits_union.bit9); printf("%d",eu.bits_union.bit10); printf("%d",eu.bits_union.bit11); printf("%d",eu.bits_union.bit12); printf("%d",eu.bits_union.bit13); printf("%d",eu.bits_union.bit14); printf("%d",eu.bits_union.bit15); printf("%d",eu.bits_union.bit16); printf("%d",eu.bits_union.bit17); printf("%d",eu.bits_union.bit18); printf("%d",eu.bits_union.bit19); printf("%d",eu.bits_union.bit20); printf("%d",eu.bits_union.bit21); printf("%d",eu.bits_union.bit22); printf("%d",eu.bits_union.bit23); printf("%d",eu.bits_union.bit24); printf("%d",eu.bits_union.bit25); printf("%d",eu.bits_union.bit26); printf("%d",eu.bits_union.bit27); printf("%d",eu.bits_union.bit28); printf("%d",eu.bits_union.bit29); printf("%d",eu.bits_union.bit30); printf("%d",eu.bits_union.bit31); printf("%d\n",eu.bits_union.bit32); } /* Resultados de la ejecución del programa: Programa de prueba para uniones y enumeraciones. Lo que sigue es la estructura de bits de los valores enumeradosPrimero
,Segundo
,Tercero
yCuarto
: 00000000000000000000000000000000 11111111111111111111111111111111 00000000000000000000000000000000 00000000000000000000000000000001 */
Segundo
el valor -1, lo cual da lugar a la oportuna codificación como número entero; el valor siguiente es el resultado de incrementarlo en 1 unidad, y por tanto es cero. El programa supone una mejora respecto al empleado en
0203
porque plantea el uso de una función, con una notable reducción del código necesario.