30 de mayo de 2016

Estructuras de control.

El lenguaje de programación C incorpora tres estructuras de control:
  1. Estructura de control secuencial.
  2. Estructuras de control para la selección de sentencias.
  3. Estructuras de control para la repetición de sentencias.
   La estructura de control secuencial se encarga de que se ejecuten en orden y en secuencia (de ahí su nombre), las sentencias, operaciones y expresiones escritas en la gramática del lenguaje C, esto es, de izquierda a derecha y de arriba hacia abajo.

   ¿Qué pasa cuando en un programa tenemos que hacer una división por ejemplo? Para el caso de la división (módulo) puede presentarse un problema debido a la indeterminación latente en la división. El resultado de la división se indetermina  si el denominador es cero, entonces, ¿qué hacer en estos casos? Para prevenir este tipo de situaciones se necesita de una estructura de control que permita procesar o no un grupo de sentencias, en función de alguna determinada condición. A éste tipo de estructuras de control se les conoce como estructuras de control para la selección de sentencias.

   Las estructuras de selección y de repetición de sentencias se describen en otras entradas en las que se muestra el funcionamiento y uso de dichas estructuras de control.
while vs do-while.


28 de mayo de 2016

Consideraciones respecto a la E/S de procesos.

   Cuando un proceso se ejecuta, tiene asociados tres flujos (streams) de manera automática sin que se haga nada especial para su creación:
  1. Entrada estándar (stdin): asociado al teclado, pero puede ser redireccionado.
  2. Salida estándar (stdout): asociado a la pantalla, pero puede ser redireccionado.
  3. Error estándar (stderr): asociado a la pantalla y no puede ser redireccionado.

   El redireccionamiento se refiere a la capacidad de un proceso de tomar o enviar datos de, o hacia un archivo. Ésto quiere decir, que un programa no siempre lee sus datos desde el teclado, o que no siempre envía sus datos a la pantalla, sino que los datos pueden ser leídos de, o enviados a archivos, sin incluir explícitamente sentencias o funciones para la gestión de dichos archivos.

   Usando redireccionamiento, el proceso no se “enteraría” de que los datos que lee o escribe, no están siendo obtenidos desde el teclado o presentados en la pantalla respectivamente, ya que el mecanismo de redireccionamiento es transparente para los procesos, favoreciendo con ello su versatilidad.

   Por último, es importante mencionar que los flujos están estrechamente relacionados con los archivos, mismos que se trataran de manera más detallada en otra entrada.


 

14 de mayo de 2016

Un primer programa en C.

Bienvenido a C.

   Con base en la estructura general de un programa en C, este Primer Ejemplo  muestra ya algunos de esos elementos.

   La estructura de control principal que gobierna al paradigma de la programación estructurada y al lenguaje de programación C, es la estructura de control secuencial. La estructura de control secuencial, ejecuta o procesa las sentencias, instrucciones, expresiones, funciones, etc., en orden consecutivo, esto es, en la misma forma en que la mayoría de los habitantes de América Latina leemos: de izquierda a derecha y de arriba hacia abajo, por lo que el procesamiento de las líneas de los códigos de los ejemplos seguirán dicha regla.

   Las líneas 1-3 del ejemplo muestran el uso de comentarios. Los comentarios en C se inician con una diagonal seguida inmediatamente de un símbolo de asterisco (“/*”), y terminan con los mismos símbolos pero colocados en orden inverso, es decir:  “*/”.

   El uso de comentarios dentro de un programa permite esclarecer algunos de los aspectos poco claros, o no tan evidentes de nuestro código o algoritmo. Los comentarios ayudan también a especificar cierta fórmula,  una determinada expresión, o algún aspecto considerado durante la elaboración del algoritmo.

   Los comentarios deberían ayudar a hacer más claro y comprensible un programa. Un código bien escrito debe ser auto documentado, esto es, que el uso apropiado de identificadores, la claridad de expresiones, y el espaciado deberían ser suficientes para hacer clara y comprensible la intención del código, pero cuando valga la pena hacer alguna aclaración por las razones anteriormente expuestas o alguna otra que se me haya escapado, los comentarios serán una herramienta muy útil.

   Ahora bien, aunque no es una regla del lenguaje, sí constituye una buena práctica de programación el iniciar los programas con un comentario que describa tanto la funcionalidad del programa, como algunas otras características que se consideren relevantes para su comprensión. En el ejemplo citado se muestra, además de lo anterior, el nombre del autor del código (línea 2). Se recomienda ampliamente seguir esta práctica.

   La línea 4 es una directiva de inclusión. Le indica al compilador que incluya la biblioteca de entrada y salida estándar (stdio.h) misma que contiene, entre otras cosas, a la función printf que se utilizará en la línea 7. La biblioteca de entrada y salida estándar se incluye en la mayoría de los programas en C.

   La línea 6 define la función principal main( ). El punto de entrada de todo programa en C es main, si esta función no existe, no es posible generar un programa ejecutable. La línea 6 indica también que main regresará un valor entero, mismo que está estrechamente relacionado con la línea 9. Todas las funciones en C deben especificar el tipo de dato de retorno; el tipo de dato por omisión es int (entero).

   Por otro lado, la línea 7 muestra el uso más simple quizá de la función printf. La función printf, toma el argumento entre comillas (“ ”), y lo envía a la salida estándar, la cual está normalmente asociada con la pantalla. Observe el símbolo “\n”, a éste tipo de símbolos se les denomina secuencias de escape, y aunque es un símbolo compuesto por dos caracteres: “\” y “n”, se hace referencia a él como uno solo.

   Técnicamente hablando, el símbolo “\n” representa un avance de línea y un retorno de carro, en analogía al mecanismo que utilizaban las máquinas de escribir mecánicas.  El avance de línea y retorno de carro (\n) le indican al cursor que avance al siguiente renglón y se ponga al principio del mismo después de haber escrito: “Bienvenido a C!”. Las sentencias en C terminan con “;”.

   La penúltima línea del ejemplo (línea 9), regresa el valor cero (0) al invocador. Vale la pena aquí hacer una mención comúnmente pasada por alto: como se mencionó en la descripción de las etapas del proceso de programación, es común utilizar un IDE para la elaboración de programas en C, lo cual no debe llevar al lector a pensar que éste sea el proceso final, sino que es preciso saber que es sólo una fase de diseño y producción. Una vez que un programa ha sido probado, depurado, corregido y mejorado, se espera que trabaje como una aplicación más, independiente del entorno en el que se desarrolló. Ahora bien, no debe perderse de vista que las aplicaciones son ejecutadas por el Sistema Operativo (SO), cualquiera que éste sea, por lo que el valor de retorno se regresa al invocador de la función main, es decir, al SO y de ahí su importancia.

   Si el SO recibe como valor de retorno de la aplicación el valor cero, se entiende que la aplicación terminó normalmente y sin problemas; en otro caso, podría haber ocurrido algún tipo de error o situación anormal durante la ejecución de la aplicación. Supongamos que durante la ejecución de un programa, éste solicita memoria al SO y por alguna razón no se le concede; en este caso, dicho programa no podría continuar su ejecución y tendría que terminar de manera anormal, regresando un valor distinto de cero, pues bien, éste valor es precisamente el que le serviría al SO para saber que hubo un problema, identificar de qué tipo (en base al valor recibido), e iniciar un mecanismo de recolección de basura o de compactación de memoria entre otras muchas posibilidades, todo en función del valor de retorno procesado.

   Finalmente, si se observan las líneas 6 y 10, dichas líneas contienen, respectivamente, los símbolos “{” y “}”, los cuales se denominan delimitadores de bloque, y su función es la de agrupar declaraciones y sentencias dentro de una sentencia compuesta, o bloque (cuerpo) de la función. Los delimitadores de bloque también agrupan declaraciones y sentencias de estructuras de control y se mostrará en ejemplos posteriores.

   Los delimitadores de bloque pueden ser visualizados como el inicio (begin) y el fin (end) utilizado en la definición de algoritmos pero en realidad son más que eso, ya que definen un bloque de construcción y en su momento se hará hincapié en ello, por ahora, resultará de utilidad que se visualicen de esta manera.

   Una vez que se ha comprendido el código del ejemplo el paso siguiente sería compilarlo. El proceso de compilación y ejecución es muy dependiente de la forma de trabajo: utilizando un IDE o una compilación en línea.

   La salida de nuestro ejemplo muestra en la pantalla el mensaje: Bienvenido a C!, tal como se presenta en la siguiente figura.

Salida del ejemplo del primer programa en C.
 
    Considere ahora esta versión alternativa del Primer Ejemplo, el cual muestra los siguientes aspectos respecto del ejemplo anterior:
  1. Pueden utilizarse varias funciones printf para imprimir un mismo mensaje en la pantalla, si ésto tiene o no sentido, es otra cosa.
  2. Pueden ir más de una sentencia por renglón: observe que hay varios printf por línea, y el “;” separa y delimita las sentencias. Lo anterior obedece a estilo de programación y conveniencia, lo que no debe olvidar es que, aunque para la computadora sería lo mismo procesar todo el programa en una sola línea, para los humanos no lo es, ya que repercute en la legibilidad y por consiguiente, en la comprensión del programa. No olvide que se requieren programas que sean fáciles de entender no sólo para quien lo escribió, sino para cualquiera que conozca la sintaxis del lenguaje.
  3. El número de sentencias o funciones printf por línea es independiente de la lógica del programa.
  4. Si no se le indica explícitamente a la función printf que avance de línea y regrese el cursor al inicio, el cursor se queda en la posición siguiente respecto al último símbolo puesto en pantalla.
   Compare los dos programas de ejemplo. No olvide que dichos programas son lógicamente equivalentes pero diferentes, ya que su código es distinto. Compruebe y corrobore que ambos programas producen exactamente la misma salida.