3.13. Ejercicios

Las soluciones a los ejercicios se pueden encontrar en el documento electrónico titulado «The Thinking in C++ Annotated Solution Guide», disponible por poco dinero en www.BruceEckel.com.

  1. Cree un fichero de cabecera (con extensión «.h»). En este fichero, declare un grupo de funciones variando las listas de argumentos y valores de retorno de entre los siguientes: void, char, int y float. Ahora cree un fichero .cpp que incluya su fichero de cabecera y haga definiciones para todas esas funciones. Cada definición simplemente debe imprimir en nombre de la función, la lista de argumentos y el tipo de retorno para que se sepa que ha sido llamada. Cree un segundo fichero .cpp que incluya el fichero de cabecera y defina una int main(), que contenga llamadas a todas sus funciones. Compile y ejecute su programa.

  2. Escriba un programa que use dos bucles for anidados y el operador módulo (%) para detectar e imprimir números enteros (números enteros sólo divisibles entre si mismos y entre 1).

  3. Escriba un programa que utilice un bucle while para leer palabras de la entrada estándar (cin) y las guarde en un string. Este es un bucle while «infinito», que debe romper (y salir del programa) usando la sentencia break. Por cada palabra que lea, evalúela primero usando una secuencia de sentencias if para «mapear» un valor entero de la palabra, y después use una sentencia switch que utilice ese valor entero como selector (esta secuencia de eventos no es un buen estilo de programación; solamente es un supuesto para que practique con el control de flujo). Dentro de cada case, imprima algo con sentido. Debe decidir cuales son las palabras interesantes y qué significan. También debe decidir qué palabra significa el fin del programa. Pruebe el programa redireccionando un fichero como entrada (si quiere ahorrarse tener que escribir, ese fichero puede ser el propio código fuente del programa).

  4. Modifique Menu.cpp para usar sentencias switch en lugar de if.

  5. Escriba un programa que evalúe las dos expresiones de la sección llamada «precedencia».

  6. Modifique YourPets2.cpp para que use varios tipos de datos distintos (char, int, float, double, y sus variantes). Ejecute el programa y cree un mapa del esquema de memoria resultante. Si tiene acceso a más de un tipo de máquina, sistema operativo, o compilador, intente este experimento con tantas variaciones como pueda manejar.

  7. Cree dos funciones, una que tome un string* y una que tome un string&. Cada una de estas funciones debería modificar el objeto externo a su manera. En main(), cree e inicialice un objeto string, imprímalo, después páselo a cada una de las dos funciones, imprimiendo los resultados.

  8. Escriba un programa que use todos los trígrafos para ver si su compilador los soporta.

  9. Compile y ejecute Static.cpp. Elimine la palabra reservada static del código, compile y ejecútelo de nuevo, y explique lo que ocurre.

  10. Intente compilar y enlazar FileStatic.cpp con FileStatic2.cpp. ¿Qué significan los mensajes de error que aparecen?

  11. Modifique Boolean.cpp para que funcione con valores double en lugar de int.

  12. Modifique Boolean.cpp y Bitwise.cpp de modo que usen los operadores explícitos (si su compilador es conforme al Estándar C++ los soportará).

  13. Modifique Bitwise.cpp para usar las funciones de Rotation.cpp. Asegúrese de que muestra los resultados que deje claro qué ocurre durante las rotaciones.

  14. Modifique Ifthen.cpp para usar el operador if-else ternario(?:).

  15. Cree una struct que contenga dos objetos string y uno int. Use un typedef para el nombre de la struct. Cree una instancia de la struct, inicialice los tres valores de la instancia, y muestrelos en pantalla. Tome la dirección de su instancia y asígnela a un puntero a tipo de la struct. Usando el puntero, Cambie los tres valores de la instancia y muestrelos.

  16. Cree un programa que use un enumerado de colores. Cree una variable de este tipo enum y, utilizando un bucle, muestre todos los números que corresponden a los nombres de los colores.

  17. Experimente con Union.cpp eliminando varios elementos de la union para ver el efecto que causa en el tamaño de la union resultante. Intente asignar un elemento (por tanto un tipo) de la union y muéstrelo por medio de un elemento diferente (por tanto, un tipo diferente) para ver que ocurre.

  18. Cree un programa que defina dos arrays de int, uno a continuación del otro. Indexe el primer array más allá de su tamaño para caer sobre el segundo, haga una asignación. Muestre el segundo array para ver los cambios que eso ha causado. Ahora intente definir una variable char entre las definiciones de los arrays, y repita el experimento. Quizá quiera crear una función para imprimir arrays y así simplificar el código.

  19. Modifique ArrayAddresses.cpp para que funcione con los tipos de datos char, long int, float y double.

  20. Aplique la técnica de ArrayAddresses.cpp para mostrar el tamaño de la struct y las direcciones de los elementos del array de StructArray.cpp.

  21. Cree un array de objetos string y asigne una cadena a cada elemento. Muestre el array usando un bucle for.

  22. Cree dos nuevos programas a partir de ArgsToInts.cpp que usen atol() y atof() respectivamente.

  23. Modifique PointerIncrement2.cpp de modo que use una union en lugar de una struct.

  24. Modifique PointerArithmetic.cpp para que funcione con long y long double.

  25. Defina una variable float. Tome su dirección, moldee esa dirección a un unsigned char, y asígnela a un puntero unsigned char. Usando este puntero y [], indexe la variable float y use la función printBinary() definida en este capítulo para mostrar un mapa de cada float (vaya desde 0 hasta sizeof(float)). Cambie el valor del float y compruebe si puede averiguar que hay en el float (el float contiene datos codificados).

  26. Defina un array de int. Tome la dirección de comienzo de ese array y utilice static_cast para convertirlo a un void*. Escriba una función que tome un void*, un número (que indica el número de bytes), y un valor (indicando el valor que debería ser asignado a cada byte) como argumentos. La función debería asignar a cada byte en el rango especificado el valor dado como argumento. Pruebe la función con su array de int.

  27. Cree un array const de double y un array volatile de double. Indexe cada array y utilice const_cast para moldear cada elemento de no-const y no-volatile, respectivamente, y asigne un valor a cada elemento.

  28. Cree una función que tome un puntero a un array de double y un valor indicando el tamaño de ese array. La función debería mostrar cada valor del array. Ahora cree un array de double y inicialice cada elemento a cero, después utilice su función para mostrar el array. Después use reinterpret_cast para moldear la dirección de comienzo de su array a un unsigned char*, y ponga a 1 cada byte del array (aviso: necesitará usar sizeof para calcular el número de bytes que tiene un double). Ahora use su función de impresión de arrays para mostrar los resultados. ¿Por qué cree los elementos no tienen el valor 1.0?

  29. (Reto) Modifique FloatingAsBinary.cpp para que muestra cada parte del double como un grupo separado de bits. Tendrá que reemplazar las llamadas a printBinary() con su propio código específico (que puede derivar de printBinary()) para hacerlo, y también tendrá que buscar y comprender el formato de punto flotante incluyendo el ordenamiento de bytes para su compilador (esta parte es el reto).

  30. Cree un makefile que no sólo compile YourPets1.cpp y YourPets2.cpp (para cada compilador particular) sino que también ejecute ambos programas como parte del comportamiento del objetivo predeterminado. Asegúrese de usar las reglas de sufijo.

  31. Modifique StringizingExpressions.cpp para que P(A) sea condicionalmente definida con #ifdef para permitir que el código de depuración sea eliminado automáticamente por medio de una bandera en línea de comandos. Necesitará consultar la documentación de su compilador para ver cómo definir y eliminar valores del preprocesador en el compilador de línea de comandos.

  32. Defina una función que tome un argumento double y retorne un int. Cree e inicialice un puntero a esta función, e invoque la función por medio del puntero.

  33. Declare un puntero a un función que toma un argumento int y retorna un puntero a una función que toma un argumento char y retorna un float.

  34. Modifique FunctionTable.cpp para que cada función retorne un string (en lugar de mostrar un mensaje) de modo que este valor se imprima en main().

  35. Cree un makefile para uno de los ejercicios previos (a su elección) que le permita escribir make para construir una versión en producción del programa y make debug para construir una versión del programa que incluye información de depuración.