introduccion2
Diferencias
Muestra las diferencias entre dos versiones de la página.
Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
introduccion2 [2020/03/09 02:38] – [Ejemplo con varias funciones: quicksort] lmateu | introduccion2 [2020/03/09 23:44] (actual) – lmateu | ||
---|---|---|---|
Línea 1: | Línea 1: | ||
===== Introducción ===== | ===== Introducción ===== | ||
- | ¿Qué es la programación de //software de sistemas//? (fuente: [[http:// | + | ¿Qué es la //programación de software de sistemas//? (fuente: [[http:// |
- | La alternativa es el //software de aplicaciones// | + | La alternativa es la //programación de software de aplicaciones// |
- | * Proveen servicios a otro software: un motor para juegos de video, un administrador de bases de datos, | + | * Proveen servicios a otro software: un motor para juegos de video, un administrador de bases de datos, |
* Poseen requisitos especiales en cuanto a desempeño: el sistema operativo, resolución numérica de ecuaciones diferenciales, | * Poseen requisitos especiales en cuanto a desempeño: el sistema operativo, resolución numérica de ecuaciones diferenciales, | ||
* Usualmente ambas. | * Usualmente ambas. | ||
- | |||
- | |||
Programa de curso: | Programa de curso: | ||
Línea 16: | Línea 14: | ||
¿Por qué estudiar el lenguaje C? | ¿Por qué estudiar el lenguaje C? | ||
- | Cuando se requiere alto desempeño el mejor lenguaje es C o su sucesor C++. Por eso hay una enorme cantidad de software escrito en C y es probable que Ud. tenga que hacer mejoras a programa | + | Cuando se requiere alto desempeño el mejor lenguaje es C o su sucesor C++. Por eso hay una enorme cantidad de software escrito en C y es probable que Ud. tenga que hacer mejoras a programas |
+ | |||
+ | Por esta razón el sitio // | ||
¿Cual es la principal desventaja de C? | ¿Cual es la principal desventaja de C? | ||
- | Al contrario de Python y Java, C no es robusto. | + | Ud. ya sabe programar en Python y aprenderá el lenguaje |
+ | |||
+ | ¿Por qué estudiar los threads? | ||
+ | |||
+ | Hasta ahora Ud. solo a escrito programas secuenciales: | ||
¿Por qué estudiar Unix y/o Linux? | ¿Por qué estudiar Unix y/o Linux? | ||
- | La mayoría de los servidores que entregan las páginas de la web corren Linux, una variante de Unix. Se necesitan expertos que trabajen en Linux para programar el software que hay detrás de esos servidores. | + | La mayoría de los servidores que entregan las páginas de la web corren Linux, una variante de Unix. Se necesitan expertos que trabajen en Linux para programar el software que hay detrás de esos servidores. |
+ | |||
+ | ¿Por qué estudiar los sockets? | ||
+ | |||
+ | Muchos sistemas son del tipo cliente/ | ||
+ | |||
+ | También usaremos los sockets como herramienta de paralelización: | ||
¿Por qué no se enseña C++? | ¿Por qué no se enseña C++? | ||
Línea 30: | Línea 40: | ||
Por restricciones de tiempo. | Por restricciones de tiempo. | ||
- | ===== Historia de los lenguajes de programación más usados | + | ===== Historia de los lenguajes de programación más influyentes |
* En los 50's nace Fortran, el primer lenguaje de programación "de alto nivel" | * En los 50's nace Fortran, el primer lenguaje de programación "de alto nivel" | ||
Línea 41: | Línea 51: | ||
* En los 90's James Gosling concibe Java como una forma de darle robustez a C++. Es menos complejo que C++. | * En los 90's James Gosling concibe Java como una forma de darle robustez a C++. Es menos complejo que C++. | ||
- | ===== Ejemplo de programa en C ===== | ||
- | |||
- | El programa de más abajo muestra los primeros //n// números de la serie de Fibonacci. | ||
- | |||
- | < | ||
- | $ gcc --std=c99 fib.c -o fib | ||
- | $ | ||
- | </ | ||
- | |||
- | Que no aparezca ningún mensaje de diagnóstico significa que el programa está bien escrito. | ||
- | |||
- | El programa se ejecuta por ejemplo en el shell de comandos con: | ||
- | |||
- | < | ||
- | $ ./fib 8 | ||
- | f0= 0 | ||
- | f1= 1 | ||
- | f2= 1 | ||
- | f3= 2 | ||
- | f4= 3 | ||
- | f5= 5 | ||
- | f6= 8 | ||
- | f7= 13 | ||
- | $ | ||
- | </ | ||
- | |||
- | Este es el archivo //fib.c//: | ||
- | |||
- | <code C> | ||
- | // Calcula los primeros n numeros de fibonacci | ||
- | |||
- | #include < | ||
- | #include < | ||
- | |||
- | int main(int argc, char **argv) { | ||
- | int n= atoi(argv[1]); | ||
- | int prev= 0; | ||
- | printf(" | ||
- | int curr= 1; | ||
- | int next; | ||
- | printf(" | ||
- | for (int i= 2; i<n; i++) { | ||
- | next= prev+curr; | ||
- | printf(" | ||
- | prev= curr; | ||
- | curr= next; | ||
- | } | ||
- | return 0; | ||
- | } | ||
- | </ | ||
- | |||
- | Ejercicio: copie este mismo programa en un archivo //fib.c// en algún computador con Linux. | ||
- | |||
- | ===== Formato de un programa en C ===== | ||
- | |||
- | * Un archivo fuente escrito en el lenguaje C debe llevar la extensión ' | ||
- | * A partir de C99 un comentario se inicia con %%'//' | ||
- | * El estilo antiguo de los comentarios (antes de C99) sigue siendo válido y se inician con /* y terminan con */. Pueden extenderse por varias líneas. | ||
- | * Las líneas con //# | ||
- | * En el archivo se define la función //main//, pero se pueden definir múltiples funciones, una a continuación de la otra. | ||
- | * Al ejecutar un programa la primera función que se ejecuta es siempre la función //main//. | ||
- | * El compilador ignora los espacios en blanco, tabs y cambios de línea. | ||
- | |||
- | ===== El sistema de tipos de C ===== | ||
- | |||
- | El lenguaje C posee tipos estáticos. | ||
- | |||
- | * //int// para los números enteros | ||
- | * //char// para enteros pequeños que usualmente corresponden a la codificación en ascii de un caracter | ||
- | * //double// para números reales | ||
- | * //void// se usa para indicar que una función no entrega ningún valor | ||
- | |||
- | Los tipos dinámicos de Python le otorgan flexibilidad y comodidad. | ||
- | |||
- | ===== Formato de una función en C ===== | ||
- | |||
- | Su formato es: //tipo// //nombre// ( // | ||
- | |||
- | * //tipo// es el tipo de los valores que retorna la función. | ||
- | * // | ||
- | * // | ||
- | |||
- | Por ejemplo el formato para //main//, exceptuando las instrucciones, | ||
- | |||
- | <code C> | ||
- | int main(int argc, char **argv) { | ||
- | ... etc. ... | ||
- | } | ||
- | </ | ||
- | |||
- | |||
- | La función //main// recibe los parámetros //argc// y // | ||
- | |||
- | C posee instrucciones simples como la asignación e instrucciones compuestas como los ciclos, los if/ | ||
- | |||
- | ===== Instrucciones simples ===== | ||
- | |||
- | Las instrucciones simples siempre terminan con un punto y coma. Una instrucción puede abarcar varias líneas | ||
- | |||
- | En el programa de ejemplo observamos 4 categorías de instrucciones simples: declaración de variables, asignación, | ||
- | |||
- | ==== Declaración de variables ==== | ||
- | |||
- | Su sintaxis es: //tipo// //nombre// = // | ||
- | |||
- | //Tipo// especifica el tipo de los valores que almacena la variable. | ||
- | |||
- | En el ejemplo se declara la variable //prev// de tipo //int// con valor inicial 0: | ||
- | |||
- | <code C> | ||
- | int prev = 0; | ||
- | </ | ||
- | |||
- | Se observa que para la variable //next// no se indica un valor inicial: | ||
- | |||
- | <code C> | ||
- | int next; | ||
- | </ | ||
- | |||
- | En tal caso hay un valor inicial desconocido. | ||
- | |||
- | Es posible declarar varias variables en una misma instrucción separando las variables con una coma. Por ejemplo se pudo declarar //prev//, //curr// y //next// en una sola instrucción: | ||
- | |||
- | <code C> | ||
- | int prev = 0, curr= 1, next; | ||
- | </ | ||
- | |||
- | Yo suelo declarar varias variables en una sola instrucción, | ||
- | |||
- | Otro ejemplo de declaración es la de la variable //n// de tipo //int//: | ||
- | |||
- | <code C> | ||
- | int n= atoi(argv[1]); | ||
- | </ | ||
- | |||
- | El valor inicial es la expresión // | ||
- | |||
- | Ejercicio: ¿Como declararía una variable que almacena el número PI? | ||
- | ==== Asignación ==== | ||
- | |||
- | Sintaxis: // | ||
- | |||
- | Sirve para cambiar el valor de una variable. | ||
- | |||
- | <code C> | ||
- | next= prev+curr; | ||
- | </ | ||
- | |||
- | El lado derecho del igual puede ser una expresión complicada con múltiples operadores e invocaciones de otras funciones. | ||
- | Recuerde que las instrucciones simples siempre terminan con un ;. El cambio de línea no le dice nada al compilador. | ||
- | |||
- | ==== Invocación de una función ==== | ||
- | |||
- | Algunas funciones son de tipo void, es decir no retornan ningún valor y por lo tanto no tiene sentido invocarlas como parte de una asignación. | ||
- | |||
- | //nombre// ( // | ||
- | |||
- | En donde // | ||
- | |||
- | <code C> | ||
- | printf(" | ||
- | printf(" | ||
- | </ | ||
- | |||
- | Acá la función se llama //printf// (print formatted) y cumple el mismo propósito que //print// en // | ||
- | |||
- | El primer parámetro de //printf// es siempre el formato. | ||
- | |||
- | En realidad en C la invocación de función es válida porque es válida cualquier instrucción con la sintaxis: // | ||
- | |||
- | De hecho la asignación también es un caso particular de esa sintaxis por = se considera un operador como + y *. | ||
- | |||
- | ==== Retorno de función ==== | ||
- | |||
- | Para terminar la ejecución de una función se usa la instrucción return, que usa la siguiente sintaxis: | ||
- | |||
- | **return** // | ||
- | |||
- | El valor retornado es el resultado de evaluar la expresión. | ||
- | |||
- | ===== Instrucciones compuestas ===== | ||
- | |||
- | Se forman a partir de una o más instrucciones (simples o compuestas). | ||
- | |||
- | ==== Ciclo while ==== | ||
- | |||
- | La sintaxis es: **while** (// | ||
- | |||
- | Es como el while de Python: se evalúa la condición, si es verdadera se ejecuta la instrucción. | ||
- | |||
- | <code C> | ||
- | int a= 1; | ||
- | while ( a < 100 ) | ||
- | a = a * 2; | ||
- | </ | ||
- | |||
- | El último valor que tomará a es 128 porque cuando a sea mayor o igual que 100, ya no se ejecutará la instrucción a=a*2; | ||
- | |||
- | Observe que la indentación no indica cuantas instrucciones están dentro del while. | ||
- | |||
- | <code C> | ||
- | int a= 1; | ||
- | while ( a < 100 ) | ||
- | a = a * 2; | ||
- | a = a + 1; // ¡No haga esto por favor! | ||
- | </ | ||
- | |||
- | El valor final de //a// será 129. La asignación a=a+1 se ejecuta una sola vez después de que a sea 128. Este código está mal escrito porque está mal indentado. | ||
- | |||
- | <code C> | ||
- | int a= 1; | ||
- | while ( a < 100 ) | ||
- | a = a * 2; | ||
- | a = a + 1; // ¡Bien! | ||
- | </ | ||
- | |||
- | Esta es una ventaja de Python. | ||
- | |||
- | ==== Agrupación de instrucciones ==== | ||
- | |||
- | Sintaxis: { // | ||
- | |||
- | Se usa para colocar varias instrucciones en instrucciones compuestas que aceptan solo una instrucción. | ||
- | |||
- | <code C> | ||
- | int a= 1; | ||
- | while ( a < 100 ) { | ||
- | a = a * 2; | ||
- | a = a + 1; // ¡Bien! | ||
- | } | ||
- | </ | ||
- | |||
- | Ejercicio: indique en donde se usa agrupación de instrucciones en el programa para fibonacci. | ||
- | |||
- | La indentación usada es importante, aunque al compilador le de lo mismo. | ||
- | |||
- | <code C> | ||
- | // ¡No use estos estilos de indentación! | ||
- | while ( a < 100 ) while ( a < 100 ) while ( a < 100 ) { | ||
- | { { a = a * 2; | ||
- | a = a * 2; a = a * 2; a = a + 1; } | ||
- | a = a + 1; a = a + 1; | ||
- | } } | ||
- | </ | ||
- | |||
- | El estilo de la izquierda sí se usa ampliamente y es legible. | ||
- | |||
- | ==== El ciclo for ==== | ||
- | |||
- | Sintaxis: for ( inicio; condición ; expresión ) instrucción | ||
- | |||
- | Se usa mucho para hacer ciclos. | ||
- | |||
- | <code C> | ||
- | { | ||
- | inicio; | ||
- | while ( condición ) { | ||
- | instrucción | ||
- | expresión; | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | Ejemplo: | ||
- | |||
- | <code C> | ||
- | for (int i= 2; i<n; i++) | ||
- | next= prev+curr; | ||
- | </ | ||
- | |||
- | Ejercicio: reescriba la instrucción equivalente usando while. | ||
- | |||
- | ==== Ejecución condicional ==== | ||
- | |||
- | Sintaxis 1: **if** ( // | ||
- | |||
- | Significado: | ||
- | |||
- | Sintaxis 2: **if** ( // | ||
- | |||
- | Significado: | ||
- | |||
- | Ejemplo: | ||
- | |||
- | <code C> | ||
- | int a= 15, b= 35; | ||
- | if (a<b) | ||
- | b = b-a; | ||
- | else | ||
- | a = a-b; | ||
- | </ | ||
- | | ||
- | |||
- | Ejercicio: ¿Qué debe hacer cuando debe ejecutar varias instrucciones cuando la condición es verdadera? | ||
- | |||
- | ===== Trabajo personal ===== | ||
- | |||
- | Debe realizar el siguiente trabajo personal antes de la segunda clase de este curso (clase del jueves): | ||
- | estudie y complete los ejercicios de la parte //Learn the Basics// de este [[https:// | ||
- | |||
- | ===== Ejemplo con varias funciones: quicksort ===== | ||
- | |||
- | Cree el archivo qsort.c con el siguiente contenido: | ||
- | |||
- | <code C> | ||
- | #include < | ||
- | #include < | ||
- | |||
- | void swap(double v[], int i, int j); // nota 1: encabezado de funcion | ||
- | |||
- | void quicksort(double a[], int left, int right) { | ||
- | if (left> | ||
- | return; | ||
- | |||
- | swap(a, left, (left+right)/ | ||
- | int last= left; | ||
- | |||
- | // +--+-----------+--------+--------------+ | ||
- | // | |/////////// | ||
- | // +--+-----------+--------+--------------+ | ||
- | // left last | ||
- | |||
- | for (int i= left+1; i< | ||
- | if (a[i]< | ||
- | swap(a, ++last, i); | ||
- | } | ||
- | swap(a, left, last); | ||
- | |||
- | quicksort(a, | ||
- | quicksort(a, | ||
- | } | ||
- | |||
- | void swap(double v[], int i, int j) { // nota 6: definicion posterior | ||
- | double tmp= v[i]; | ||
- | v[i]= v[j]; | ||
- | v[j]= tmp; | ||
- | } | ||
- | |||
- | int main(int argc, char *argv[]) { | ||
- | int n= argc-1; | ||
- | double a[n]; // nota 7: declaracion de arreglo | ||
- | |||
- | for (int i= 0; i<n; i++) | ||
- | a[i]= atof(argv[i+1]); | ||
- | |||
- | quicksort(a, | ||
- | |||
- | for (int i= 0; i<n; i++) | ||
- | printf(" | ||
- | printf(" | ||
- | |||
- | return 0; // nota 9: retorno de función no //void// | ||
- | } | ||
- | </ | ||
- | |||
- | Notas: | ||
- | - Esto se denomina declaración de encabezado de función. | ||
- | - Se usa la instrucción //return// para anticipar el retorno de una función. | ||
- | - Acá es donde se usa la función // | ||
- | - Observe que las llaves no son necesarias acá. Pero su uso le entrega legibilidad al programa. | ||
- | - C es recursivo. | ||
- | - Esta es la definición de //swap//, que fue usada antes en la nota 3, por lo que se necesitó la declaración de su encabezado en la nota 1. | ||
- | - Esa es la sintaxis para declarar un arreglo de //n// elementos de tipo // | ||
- | - Use el formato %g para desplegar reales con //printf//. | ||
- | - La función //main// debe retornar obligatoriamente un entero. Este se llama el código de retorno del programa y se puede mostrar en el shell echo el comando echo %%$? | ||
- | |||
- | He aquí cómo compilar y un ejemplo de ejecución con el resultado del programa: | ||
- | |||
- | < | ||
- | $ gcc -std=c99 qsort.c -o qsort | ||
- | $ ./qsort 3 1 5 7 4 | ||
- | 1 3 4 5 7 | ||
- | $ echo $? | ||
- | 0 | ||
- | $ | ||
- | </ | ||
- | |||
- | Ejercicios: | ||
- | * Modifique el programa de modo que muestre los números descendentemente (ahora son mostrados ascendentemente). | ||
- | * Modifique el programa de modo que cada número se muestre en una línea independiente. | ||
- | * Modifique el programa de modo que el código de retorno sea 1 cuando el usuario olvidó especificar los elementos a ordenar (es decir cuando n=0). | ||
- | |||
- | ===== Opcional ===== | ||
- | |||
- | En el curso Metodologías de Diseño y Programación deberá estudiar el lenguaje Java. Se puede considerar Java como un sucesor de C y por lo tanto gran parte de lo que estudie en este curso le servirá también para aprender Java. Los tipos y la sintaxis son parecidos. | ||
introduccion2.1583721516.txt.gz · Última modificación: 2020/03/09 02:38 por lmateu