6 de enero de 2017

Ejercicios selectos (abstracción de datos).

  1. Compare la estructura del Ejemplo 8.1 con la estructura general de un programa en C descrita en el Ejemplo 1.1.
  2. Con base en el programa del Ejemplo 8.1 y a lo expuesto en el blog en la entrada Abstracción en acción, complete las operaciones de suma y resta para las sentencias case de las líneas 27 y 29 respectivamente. Considere el caso de la siguiente operación o una similar: 1/2 - 1/2 ¿Qué pasaría?, ¿cómo manejaría esta situación? Sugerencia: Si el resultado de alguna operación genera un numerador con cero, no presente el resultado 0/4 por ejemplo, sino únicamente 0. Utilice una sentencia if/else en la presentación de datos.
  3. Reescriba la declaración de variables r1, r2 y res de las líneas 17 - 19 del Ejemplo 8.2 en una sola línea.
  4. Escriba una función con el siguiente prototipo void imprimeRacional(RACIONAL r);, la función deberá imprimir en la salida estándar el racional proporcionado (r) con las consideraciones hechas en el ejercicio 2. Tome ahora también en consideración, que si el resultado de un expresión genera algo como 4/4, 21/21, etc, se deberá imprimir 1 en su lugar.
  5. Considere la función leeExpresion del Ejemplo 8.2. La expresión de la línea 61: r1 -> q == 0 puede reescribirse con notación de apuntadores como: (*r1).q == 0. Reescriba, en su respectiva notación de apuntador en otro programa distinto, todas las expresiones que utilizan el operador flecha en la función leeExpresion y pruebe que dicho programa funciona exactamente igual.
  6. Reescriba la función hazOperacion del Ejemplo 8.2 para que reciba sus parámetros por referencia en lugar de parámetros por valor. No olvide cambiar también el operador punto por el operador flecha.
  7. Reescriba la función hazOperacion del Ejemplo 8.2 para que utilice funciones para realizar la suma, resta, producto y división de números racionales, utilice los siguientes prototipos: 
    1. RACIONAL suma(RACIONAL r1, RACIONAL r2);
    2. RACIONAL resta(RACIONAL r1, RACIONAL r2);
    3. RACIONAL producto(RACIONAL r1, RACIONAL r2);
    4. RACIONAL division(RACIONAL r1, RACIONAL r2);
    8. Escriba una función que dado un número racional, regrese si es posible, dicho número racional simplificado e incorpórela al Ejemplo 8.2. La función deberá tener el siguiente prototipo: RACIONAL simplifica(RACIONAL r);. Sugerencia: obtenga el Máximo Común Divisor de p y q  para simplificar su expresión; para ello, puede utilizar el Algoritmo de Euclides descrito en la sección correspondiente de la entrada Pseudo código.
    9. Reescriba el Ejemplo 8.2 para que utilice un arreglo de apuntadores a funciones en lugar de una estructura switch.
    10. Sean c1 y c2 dos números complejos definidos de la siguiente manera:
                                     c1 = (a + bi)c2 = (c + di)
donde a, b, c, d son números reales. Escriba un programa que permita representar números complejos así como sus respectivas operaciones aritméticas:
  • La suma de c1 y c2 se define como: c1 + c2 = (a + bi) + (c + di)  = (a + c) + (b + d)i.
  • La resta de c1 y c2 se define como: c1 - c2 = (a + bi) - (c + di)  = (a - c) + (b - d)i.
  • La multiplicación de c1 y c2 se define como: c1 * c2 = (a + bi) * (c + di)  = (ac - bd) + (ad + bc)i.
  • La división es un poco más elaborada debido a que se racionaliza el denominador; es decir, se multiplica el numerador y el denominador por el conjugado del denominador. El conjugado de un número complejo se obtiene cambiando el signo de su componente imaginaria, es decir: si c = a + bi  es un número complejo, su conjugado está dado por  c¹ = a - bi, y entonces:
    • c1 / c2 = (a + bi) / (c + di)  = [(a + bi) * (c - di)] / [(c + di) * (c - di)] = [(ac + bd) + (bc - ad)i] / (c² + d²).
    11. Modifique el Ejemplo 8.3 para que, siguiendo la idea planteada en las funciones leeTriangulo y leeVertice, defina primero una función imprimeVertice que, como su nombre lo indica, se encargue de imprimir el vértice que reciba como argumento en la salida estándar; para que entonces la función imprimeTriangulo haga los llamados correspondientes a ésta y se pueda imprimir en la salida estándar, el triángulo que se recibe como parámetro.
    12. Extienda el Ejemplo 8.3 para que realice lo siguiente (para este ejercicio, asuma que todos los vértices serán introducidos en el sentido de las manecillas del reloj):
          12.1. Presente un menú que permita al usuario trabajar con tres tipos de figuras geométricas: triángulos, rectángulos y cuadrados. Los rectángulos y los cuadrados serán ortogonales y sus lados paralelos a los ejes x y y respectivamente. El menú deberá tener el siguiente formato:
.
          12.2. Para el caso de los triángulos, considerar:
  • Si los vértices introducidos constituyen o no un triángulo. Si los vértices no conforman un triángulo se reporta dicha situación, y se repite la lectura de los mismos hasta que constituyan un triángulo.
  • Determinar el tipo de triángulo leído: isósceles, equilátero o escaleno.
          12.3. Represente, por medio de una estructura compuesta, un cuadrado, en cuyo caso deberá:
  • Determinar si los vértices introducidos constituyen o no un cuadrado. Si los vértices no conforman un cuadrado se reporta dicha situación, y se repite la lectura de los mismos hasta que constituyan un cuadrado.
  • Dado un punto en el espacio bidimensional (vértice), determinar si dicho punto está dentro, fuera, o sobre el último cuadrado introducido.
          12.4. Represente, por medio de una estructura compuesta, un rectángulo, en cuyo caso deberá:
  • Determinar si los vértices introducidos constituyen o no un rectángulo. Si los vértices no conforman un rectángulo se reporta dicha situación, y se repite la lectura de los mismos hasta que constituyan un rectángulo.
  • Dado un punto en el espacio bidimensional (vértice), determinar si dicho punto está dentro, fuera, o sobre el último rectángulo introducido.
    13. Reescriba el Ejemplo 8.4 para que tanto la lectura de datos de la entrada estándar, como la presentación de los mismos en la salida estándar se lleve a cabo por medio de funciones; para ello utilice los siguientes prototipos de funciones, donde contactos representa el directorio de contactos y n el número de contactos a leer o presentar respectivamente. Note que las expresiones contactos[ ] y *contactos son equivalentes:
 
void llenaDirectorio(CONTACTO contactos[ ], int n);
void imprimeDirectorio(CONTACTO *contactos, int n);

    14. Escriba una función que permita ordenar, en base al nombre, el directorio de contactos del Ejemplo 8.4. Utilice el ordenamiento por burbuja y el siguiente prototipo de función:

void ordena(CONTACTO *contactos, int n);

Sugerencia: investigue lo que hace y utilice la función strcmp de la biblioteca string.h para la comparación de los nombres de los contactos.
    15. Complete la biblioteca de funciones del Ejemplo 8.5 con la función simplifica realizada en el Ejercicio 8, de tal forma que los valores almacenados en las matrices estén siempre reducidos a su expresión mínima, es decir, que estén simplificados.
    16. Escriba un programa que defina y pruebe una función con el siguiente prototipo: MATRIZ_RACIONAL resta(MATRIZ_RACIONAL a, MATRIZ_RACIONAL b, int m, int n); La función deberá calcular la resta de la matriz a menos la matriz b de manera análoga a como lo hace la función suma del Ejemplo 8.5; tome en cuenta que necesitará de una función restaRacional análoga a la función sumaRacional.
Agregue la función resta del ejercicio anterior a la biblioteca de funciones del Ejemplo 8.5.
    17. Escriba un programa que defina y pruebe una función con el siguiente prototipo: void imprimeTranspuesta(MATRIZ_RACIONAL a, int m, int n);. La función deberá imprimir en la salida estándar, la matriz transpuesta de a. La matriz transpuesta se genera convirtiendo los renglones en columnas y viceversa.
Agregue la función imprimeTranspuesta del ejercicio anterior a la biblioteca de funciones del Ejemplo 8.5.
    18. Escriba un programa que defina y pruebe una función con el siguiente prototipo: MATRIZ_RACIONAL transpuesta(MATRIZ_RACIONAL a, int m, int n);. La función deberá regresar la matriz transpuesta de a. La matriz transpuesta se genera convirtiendo los renglones en columnas y viceversa.
Agregue la función transpuesta del ejercicio anterior a la biblioteca de funciones del Ejemplo 8.5.
    19. Escriba un programa que defina y pruebe una función con el siguiente prototipo: int esSimetrica(MATRIZ_RACIONAL a, int n);. La función deberá determinar si la matriz a es o no simétrica. Una matriz simétrica es aquella que es igual con su matriz transpuesta.
Agregue la función esSimetrica del ejercicio anterior a la biblioteca de funciones del Ejemplo 8.5.
    20. Escriba un programa que defina y pruebe una función con el siguiente prototipo: MATRIZ_RACIONAL producto(MATRIZ_RACIONAL a, MATRIZ_RACIONAL b, int m, int n, int l);. La función deberá calcular el producto de las matrices a y b regresando su resultado. Investigue cómo se define y obtiene el producto de matrices antes de intentar realizar este ejercicio.
Agregue la función producto del ejercicio anterior a la biblioteca de funciones del Ejemplo 8.5.
    21. Sea A una matriz cuadrada, i.e. con el mismo número de renglones que de columnas. La matriz inversa de A, denotada por A*, se define como: A x A* = A* x A = I donde I es la matriz identidad. Escriba un programa defina y pruebe una función con el siguiente prototipo: MATRIZ_RACIONAL inversa(MATRIZ_RACIONAL a, int n);. La función deberá calcular (si existe) la matriz inversa de la matriz a, tome en cuenta que si la matriz inversa de a no existe, la función deberá regresar NULL. Investigue cómo se calcula la matriz inversa de una matriz y utilice el método que más le convenga.
Sugerencia: utilice el método de Gauss-Jordan.
Agregue la función inversa del ejercicio anterior a la biblioteca de funciones del Ejemplo 8.5.
    22. Investigue y estudie el concepto de union en C. Las uniones (union) son parecidas en su estructura y manipulación a las estructuras (struct) pero son esencialmente diferentes, debido a que en las uniones, los elementos miembro que la conforman comparten su espacio de memoria, mientras que en las estructuras, cada elemento miembro tiene su propio espacio de memoria independiente.