19 de junio de 2017

Pseudo código.

   El pseudo código es un tipo de notación algorítmica en el que se utiliza texto. Es un lenguaje artificial de especificación de algoritmos, caracterizado por:
  1. Mantener una sangría conveniente para la fácil identificación de los elementos que lo componen.
  2. Permitir la declaración de los datos (constantes y/o variables) manipulados por el algoritmo.
  3. Disponer de un conjunto pequeño y completo de palabras reservadas. Las palabras reservadas son propias del lenguaje artificial y no pueden ser utilizadas como identificadores de variables o módulos. Las palabras reservadas se muestran en negritas en la descripción de las estructuras de control correspondientes.
   El pseudo código se concibió para superar las dos principales desventajas del diagrama de flujo:
  1. Lento de crear.
  2. Difícil de modificar.
   A pesar de esto, los diagramas de flujo son una excelente herramienta para el seguimiento del flujo de un algoritmo, así como para transformar con relativa facilidad dichos algoritmos en programas.

Estructuras de control.
   Esta sección describe brevemente en su representación en pseudo código las estructuras de control. Todas las estructuras de control enunciadas siguen las mismas características descritas con anterioridad en las entradas correspondientes de Algoritmos (panorama general) y Algoritmos (definición y conceptos), por lo que se recomienda su revisión.

   Estructura secuencial.
   La siguiente lista de sentencias ilustra la representación en pseudo código de la estructura de control secuencial:

                                                       <Sentencia 1>
                                                       <Sentencia 2>
                                                                  .
                                                                  .
                                                                  .
                                                       <Sentencia n>
Estructura secuencial en pseudo código.

    Es claro que el orden en que se ejecutan o procesan las sentencias es el orden natural en el que aparecen: de izquierda a derecha y de arriba hacia abajo, exactamente de la misma forma en la que leemos un texto.
 
   Estructuras de selección.
   Las estructuras de selección simple, doble y múltiple se muestran a continuación. La condición debe tener una naturaleza de carácter booleano, es decir, que la condición pueda ser evaluada sin ambigüedad como verdadera o falsa:

                                                  if (condición)
                                                         <Sentencia(s)>

Estructura de selección simple (if) en pseudo código.

    Si condición es verdadera, se procesan el grupo de Sentencias (puede ser una o varias) correspondiente, si es falsa, se ignora.
 
                                                  if (condición)
                                                         <Sentencia(s) 1>
                                                  else
                                                         <Sentencia(s) 2>
Estructura de selección doble (if-else) en pseudo código.
 
    Para la estructura de control if-else, si condición es verdadera, se procesan el grupo de Sentencias 1 (puede ser una o varias) correspondiente, si es falsa, se procesan el grupo de Sentencias 2. 

                                                  if (condición 1)
                                                         <Sentencia(s) 1>
                                                  else if (condición 2)
                                                         <Sentencia(s) 2>
                                                  else if (condición 3)
                                                         <Sentencia(s) 3>
                                                                      .
                                                                      .
                                                                      .
                                                  else
                                                         <Sentencia(s) n + 1>

Estructura de selección múltiple anidada (if-else) en pseudo código.

    La estructura de control if-else se puede anidar, permitiendo con ello una mayor versatilidad, así por ejemplo, si condición 1 es verdadera, se procesan el grupo de Sentencias 1 (puede ser una o varias) y se ignoran todas las demás; si es falsa se evalúa la condición 2 y, si es verdadera, se procesan el grupo de Sentencias 2 y se ignoran todas las restantes y así sucesivamente con todas las condiciones y sentencias que existan.
    El último else es opcional. Si existe y ninguna de las condiciones anteriores fue verdadera, entonces se procesa el grupo de Sentencias n + 1.

                                                switch (indicador)
                                                        case <valor 1>:
                                                                <Sentencia(s) 1>
                                                        case <valor 2>:
                                                                <Sentencia(s) 2>
                                                                      .
                                                                      .
                                                                      .
                                                        case <valor n>:
                                                                <Sentencia(s) n>
                                                        default:
                                                                <Sentencia(s) n + 1>

Estructura de selección múltiple (switch-case) en pseudo código.

    La estructura de selección múltiple switch-case es un caso particular de selección múltiple anidada if-else. En ella, el indicador se evalúa y se compara con alguno de los valores (valor 1, valor 2, ..., valor n) para que, se coincide con alguno de ellos, se procese el grupo de Sentencias correspondiente.
    El default y su grupo de sentencias asociado es opcional. Si existe, y el indicador no coincidió con ninguno de los valores propuestos por los case, entonces se procesa el grupo de Sentencias n + 1.
 
    Estructuras de repetición.
   Finalmente, las estructuras de repetición “mientras” (while) y “hacer mientras” (do-while), son presentadas a continuación:


                                                   while (condición)
                                                         <Sentencia(s)>
                                                   end while

Estructura de repetición mientras (while) en pseudo código.
 
    En la estructura de repetición while, mientras la condición sea verdadera se procesará el grupo de Sentencias correspondiente. Una vez que la condición sea falsa, se ejecutará la primera sentencia que aparezca después del end while continuando el flujo de control secuencial a partir de ahí.

                                                   do
                                                         <Sentencia(s)>
                                                   while (condición)

Estructura de repetición hacer-mientras (do-while) en pseudo código.

       En la estructura de repetición do-while, mientras la condición sea verdadera se procesará el grupo de Sentencias correspondiente. Una vez que la condición sea falsa, se ejecutará la primera sentencia que aparezca después del while continuando el flujo de control secuencial a partir de ahí.
   
    Observe que la descripción y el funcionamiento de la estructura do-while es similar al de la estructura while, con la diferencia de que la expresión en el ciclo while es evaluada al principio, mientras que en el ciclo do-while es evaluada al final. Con base en lo anterior se tiene que:
  • Las sentencias de la estructura de repetición while se repiten de 0 a n-veces.
  • Las sentencias de la estructura de repetición do-while se repiten de 1 a n-veces.
   En esencia, esta es la única diferencia que existe entre las estructuras de repetición while y do-while. No pierda de vista esta simple pero fundamental diferencia.

   Pseudocódigo del algoritmo de Euclides.
   Esta sección muestra el pseudocódigo para el problema propuesto en la sección Algoritmo de Euclides: definición del problema de la entrada Algoritmos (definición y conceptos), por lo que convendría revisarla para tener una mejor comprensión del algoritmo.

   Se deja como ejercicio al lector el comparar el siguiente algoritmo en pseudo código con el de la sección Diagrama de flujo del algoritmo de Euclides de la entrada Diagramas de flujo.

                Algoritmo MCD
                    Inicio
                               Variables
                                          m, n, r de tipo entero

                               obtener (m, n)

                               r = m mod n

                               while (r != 0)
                                          m = n
                                          n = r
                                          r = m mod n
                               end while

                               imprimir (n)
                    Fin
Algoritmo de Euclides en pseudo código.


18 de mayo de 2017

Diagramas de flujo.

   Un diagrama de flujo es una notación algorítmica de tipo gráfica.

   Un diagrama de flujo es una herramienta gráfica de descripción de algoritmos, que se caracteriza por utilizar un conjunto de símbolos gráficos para expresar simbólicamente los flujos de control o el orden lógico en el que se realizan las acciones de un algoritmo.

   Aunque existe en la literatura una amplia variedad de representaciones para los símbolos utilizados en los diagramas de flujo, en este blog se adoptarán sólo cinco, mismos que se presentan a continuación:

Elementos gráficos de los diagramas de flujo y su significado.

Estructuras de control.
   Esta sección muestra los diagramas de flujo de las estructuras de control, para más detalles respecto a las estructuras de control, refiérase por favor a la entrada Algoritmos (panorama general).

   Estructura secuencial.
   La siguiente figura muestra el diagrama de flujo que representa a la estructura de control secuencial. La estructura y su funcionamiento se explican por sí mismas:
Estructura secuencial en diagrama de flujo.

   Estructuras de selección.
   Las siguientes figuras muestran los diagramas de flujo de las estructuras de selección:

(a) Estructura de selección simple (if) en diagrama de flujo.
(b) Estructura de selección doble (if-else) en diagrama de flujo.
   
(c) Estructura de selección múltiple (switch-case) en diagrama de flujo.

   Puede observarse en la figura (a), que en la estructura de selección simple se evalúa la condición, y si ésta es verdadera, se ejecuta un determinado grupo de sentencias; en caso contrario, las sentencias son ignoradas.

   Por otro lado, en la estructura de selección doble (b), cuando la condición es verdadera se ejecutará un determinado grupo de sentencia(s) 1, y si es falsa se procesará otro grupo diferente de sentencia(s) 2.

   Por último, en la estructura de selección múltiple se ejecutarán unas sentencias u otras según sea el valor que se obtenga al evaluar una expresión representada por el indicador. Se considera que dicho resultado debe ser de tipo ordinal, es decir, de un tipo de datos en el que cada uno de los elementos que constituyen el tipo, excepto el primero y el último, tiene un único predecesor y un único sucesor.

   Estructuras de repetición.
Las siguientes figuras muestran las estructuras de repetición básicas.

(a) Estructura de repetición while en diagrama de flujo.
(b) Estructura de repetición do-while en diagrama de flujo.
 
    Lo que caracteriza a la estructura de repetición “mientras” (while) como puede apreciarse en la figura (a), es que las sentencias del cuerpo del ciclo se procesan cuando la condición es verdadera, además de que la condición es verificada al principio, de donde se deduce que las sentencias se podrán ejecutar de 0 a n veces.

   Por otro lado, en la estructura de repetición “hacer mientras” (do-while), las sentencias del cuerpo del ciclo se ejecutan al menos una vez, y continúan repitiéndose hasta que la condición sea falsa. La verificación de la condición se realiza al final del ciclo (figura (b)), por lo que se deduce que las sentencias se ejecutarán de 1n veces; i.e., al menos una vez.

Diagrama de flujo del algoritmo de Euclides
   La siguiente figura  muestra el diagrama de flujo para el problema propuesto en la sección Algoritmo de Euclides: definición del problema de la entrada Algoritmos (definición y conceptos). La solución a dicho problema está determinada por el algoritmo de Euclides, mismo que se presenta a continuación en su versión de diagrama de flujo:

Diagrama de flujo para el algoritmo de Euclides.
 
   Para ser congruentes con la propuesta de solución realizada en la sección Estructura de un algoritmo de la entrada Algoritmos (definición y conceptos), además del algoritmo, se ha indicado en recuadros de menor intensidad, las especificaciones del proceso de entrada, del proceso de salida, y del proceso general de solución.

17 de mayo de 2017

Ejercicios selectos (bienvenido).

  1. Investigue qué secuencias de escape existen y para qué sirven. Escriba un programa que las incluya, y pruebe cada una de ellas.
  2. Escriba un programa en C que imprima su nombre completo en la pantalla en una sola línea.
  3. Escriba un programa en C que imprima su nombre completo en la pantalla pero dividido en tres líneas:
    1. En la primera línea su(s) nombre(s).
    2. En la segunda línea su primer apellido.
    3. En la tercera línea su segundo apellido.
  4. Diferentes culturas y pueblos tienen distintos tipos de leyendas y la disciplina de la computación no escapa a ellas. Se dice que todo aquel que se inicie en las maravillosas artes de la programación estructurada usando al lenguaje de programación C debe, si no quiere recibir la maldición de ser un mal programador toda su vida, escribir un programa que imprima, en la salida estándar el mensaje: Hola Mundo! Independientemente de sus creencias, evite el riesgo de la maldición y colabore con la perpetuidad de esta tradicional leyenda realizando este simple pero gratificante ejercicio de tal manera que, si el augurio se cumple, se dé por descartada al menos, la maldición...
  5. Investigue qué otros tipos de datos existen en C, qué representación tienen, cuál es el rango de números que pueden almacenar, y cuál es el especificador de formato que utilizan para las funciones printf y scanf respectivamente. Nota: no siempre es el mismo.
  6. Extienda el Ejemplo 2.5 para que considere todos los tipos de datos en C que investigó en el ejercicio anterior.  El Ejemplo 2.5 muestra el uso del operador unario (un operador unario se refiere a que el operador sólo necesita un operando para realizar su función; el operador + por ejemplo es un operador binario porque necesita dos operandos para realizar su función) sizeof para determinar el tamaño en bytes que ocupa el operando asociado. Observe también que el operador sizeof trabaja no sólo sobre tipos de datos (líneas 12 y 14), sino también sobre variables (líneas 11 y  13). El rango de los números representados por un tipo de dato depende del tamaño en bits del tipo de dato; para determinar el tamaño en bits multiplique el tamaño en bytes del tipo de dato y multiplíquelo por ocho.
  7. Experimente omitiendo intencionalmente el uso del operador “&” (ampersand) en la lectura de una variable como la que se hace en el Ejemplo 2.3. ¿Qué sucede cuando compila? ¿Qué pasa cuando se ejecuta?,  si el programa es ejecutado, ¿qué valor se guarda en la variable?
  8. Escriba una programa que basándose en el Ejemplo 2.3, realice la resta de dos números enteros decimales.
  9. Escriba una programa que basándose en el Ejemplo 2.3, realice la multiplicación de dos números enteros decimales.
  10. Escriba una programa que basándose en el Ejemplo 2.3, realice el módulo de dos números enteros decimales. ¿Qué podría pasar en este caso?
  11. Escriba una programa que basándose en el Ejemplo 2.3, realice la división de dos números enteros decimales ¿Qué podría pasar en este caso?
  12. Repita los ejercicios 8-11 con las consideraciones implementadas en el Ejemplo 2.4.
  13. Basándose en el Ejemplo 2.4, modifíquelo para que ahora trabaje con números con punto decimal (float). Haga lo propio para los ejercicios 8, 9 y 11; tome en cuenta que el especificador de formato a utilizar es ahora "%f".
  14. Dependiendo del IDE que esté utilizando, investigue y documéntese acerca de la depuración de programas. Si está compilando en línea, busque un tutorial del programa gdb; en cualquier caso, debe saber que la depuración no sólo le será de suma utilidad, sino que es una tarea fundamental de la programación.