informática ii - unrhola mundo diseccionado la sentencia return indica el valor que retorna la...

Post on 15-Jan-2020

1 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Informática II

Ingeniería Electrónica2011

Hola mundo diseccionado...

/*Mi primer programa en C*/

#include <stdio.h>

int main(void){

printf("Hola mundo!\n");return 0;

}

Hola mundo diseccionado...

La 1º línea entre /* y */ es un comentario y será ignorado por el compilador

La línea #include <stdio.h> le indica al preprocesador de C que incluya en el código el archivo de cabecera stdio.h, donde donde están las declaraciones de las funciones de entrada/salida estándar de C

Las líneas que comienzan por # se llaman directivas del preprocesador y no terminan en ;

Modelo de compilación en C

Hola mundo diseccionado...

La línea int main(void) define la cabecera de la función main, el punto donde comienza la ejecución de un programa en C

Puede definirse sin parámetros formales o con dos

La invocación a la función printf("Hola mundo!\n") le indica al ordenador que muestre por pantalla el mensaje que aparece entre comillas dobles

Hola mundo diseccionado

La sentencia return indica el valor que retorna la función main (por convención, 0 indica “todo OK”

C distingue mayúsculas y minúsculas, todas las palabras reservadas del lenguaje están en minúsculas

Cada sentencia termina en ;. Puedo tener múltiples sentencias en 1 sola línea o 1 única sentencia ocupar más de 1 línea

Los espacios en blancos son ignorados

Hola mundo diseccionado

Las llaves { y } indican el comienzo y final del cuerpo de la función main. En general indican bloques de sentencias que deben tratarse como una unidad. Un error común al principio!: desbalance entre el número de llaves abiertas y cerradas, ídem con los () y []

Hola mundo diseccionado...

Cuando se ejecuta aparece en pantalla:Hola mundo! El cursor se sitúa al comienzo de una nueva

línea. Esto lo produce el carácter que aparece luego de \, (carácter especial) que acción especial de impresión se realiza, en este caso un salto de línea

No va ; luego de }

Hola mundo diseccionado...

Un programa en C contiene una o más funciones una de las cuales debe ser int main(void)

Los paréntesis indican función int indica que main retorna un valor

entero cuando es invocada

#include<stdio.h>int main(){ int a, b, c = 0; printf(“Digite el primer numero: ”); scanf(“%d”,&a); printf(“Digite el segundo numero: ”); scanf(“%d”,&b); c = a + b; printf(“El resultado de la suma es: %d\n”,c); return 0; }

Librerías (uso de directivas del preprocesador)

Declaración de variables (las variables son locales en este caso).

Instrucciones (Expresiones aritméticas y lógicas, condicionales (SI), ciclos (HAGA, MIENTRAS)).

Programa principal

ANATOMIA DE UN PROGRAMA EN C

Estructura de un programa

Un programa en C consiste de: Varias funciones en uno o más archivos Una función main en uno de esos archivos Posiblemente algunos archivos de cabecera Librerías externas y sus archivos de

cabecera

Funciones y la estructura del programa

Las funciones dividen tareas grandes de computación en varias más pequeñas y, permiten la posibilidad de construir sobre lo que otros ya han hecho, en lugar de comenzar desde cero.

Las funciones apropiadas ocultan los detalles de operación de las partes del programa que no necesitan saber de ellos, aportando claridad a la totalidad y facilitando la penosa tarea de hacer cambios.

Funciones y la estructura del programa

El lenguaje C se diseñó para hacer que las funciones fueran eficientes y fáciles de usar; los programas escritos en C se componen de muchas funciones pequeñas en lugar de sólo algunas grandes.

Un programa puede residir en 1 o más archivos fuente, los cuales pueden compilarse por separado y cargarse junto con funciones de biblioteca previamente compiladas.

Conceptos básicos de funciones

En matemáticas el máximo común divisor (abreviado MCD) de 2 o más números enteros es el mayor número que los divide sin dejar resto.

Según Euclides: Al dividir a entre b (números enteros), se obtiene un cociente q y un residuo r. Es posible demostrar que el máximo común divisor de a y b es el mismo que el de b y r. También es importante tener en cuenta que el máximo común divisor de cualquier número a y 0 es precisamente a.

Euclides

Euclides

Según lo antes mencionado, para calcular el máximo común divisor de 2366 y 273 se puede proseguir de la siguiente manera:

/*Programa que calcula el MCD de 2 nros. enteros positivos*/

#include <stdio.h>

unsigned int mcd(unsigned int , unsigned int ); //prototipo de función

int main(void)

{

unsigned int a,b;

printf("Ingrese un nro. entero positivo: ");

scanf("%u",&a);

printf("Ingrese otro entero positivo: ");

scanf("%u",&b);

printf("\nEl mcd entre los 2 nros. ingresados es: %u\n",mcd(a,b));

return 0;

}

Invocación de función

unsigned int mcd (unsigned int m, unsigned int n)

{//definición de función

unsigned int r;

while((r=m%n)!=0)

{

m=n;

n=r;

}

return n;

}

Conceptos básicos de funciones

Cada definición de función tiene la siguiente forma:

tiporegresado nombrefuncion(declaraciones de argumentos){

declaraciones y proposiciones} Pueden omitirse algunas partes, una función

mínima es nada(){}, no hace ni retorna nada Si el tipo de retorno se omite, regresa un int No existe anidamiento de funciones

Conceptos básicos de funciones

Un programa es sólo un conjunto de definiciones de variables y funciones.

La comunicación entre funciones es por argumentos, valores regresados por las funciones y a través de variables externas (globales).

Las funciones pueden representarse en cualquier orden dentro del archivo fuente, y el programa puede dividirse en varios archivos fuente mientras las funciones no se dividan

Conceptos básicos de funciones

La proposición return es el mecanismo para que la función que se invoca regrese un valor al invocador.

A return puede seguirle cualquier expresión: return expresion

La expresión se convierte al tipo de retorno de la función si es necesario

Con frecuencia se usa (expresión) pero es optativo

Conceptos básicos de funciones

La función invocante tiene la libertad de ignorar el valor regresado (caso printf)

No hay necesidad de expresión después de return (caso funciones void), en ese caso no se retorna ningún valor al invocante

Puede haber varios return en una función También el control regresa al invocante, sin

valor, cuando la ejecución llega a la llave final (}) de cierre de la función (funciones void)

No pueden retornar arrays

Conceptos básicos de funciones

Si la función toma argumentos declárelos sino use void dentro de los paréntesis

Una función se invoca al definir los valores actuales para los parámetros formales de la misma.

Los parámetros siempre se pasan por valor, excepto arrays

Los procedimientos son simplemente funciones de un tipo especial (void).

Una función no void puede usarse como operando en cualquier expresión aritmética valida de C.

Conceptos básicos de funciones

C sólo permite invocar a funciones previamente definidas.

Es posible separar la declaración de una función de su definición: La definición abarca todo el código de la

función en cuestión. La declaración sólo incluye la cabecera o

prototipo de la misma.

Prototipo de una función

La declaración int power (int m, int n);

Antes de main indica que power es una función que espera 2 argumentos int y retorna un int.

Esta declaración se llama prototipo de una función, debe coincidir con la definición y uso de power. Es un error que la definición y uso que se haga de una función no corresponda con su prototipo

Prototipo de una función

Los nombres de los parámetros no necesitan coincidir, de hecho, son optativos en el prototipo:

int power (int, int); Sin embargo, unos nombres bien

seleccionados son una muy buena documentación, conviene emplearlos

La declaración de parámetros (tipo y número) y tipo de retorno en el prototipo permite el chequeo del compilador en la definición e invocación

Prototipo de funciones

Los parámetros se listan de a pares: pares: (tipo1 nombre1, tipo2 nombre2, ...)

Cada nombre debe llevar su tipo, aunque se repitan

En caso de parámetros arrays , no se especifica la dimensión:

float media (int array[], int tamano)

Prototipo de funciones

En el caso de que la matriz sea de dimensión superior a uno, deben indicarse en la definición las magnitudes de todas las dimensiones excepto la primera. Es decir: int f(float valores [][10][5])

Prototipo de una función

Esenciales cuando las aplicaciones se dividen entre múltiples archivos fuente

Ejemplo: Se tiene una aplicación dividida en 10 archivos

fuente, en cada uno de ellos se invocan 4 funciones de cada uno de los otros

Necesitaría 36 prototipos de funciones en c/u! Solución: Usar archivos de cabecera y directivas

del preprocesador. En este caso se requiere añadir 9 directivas de inclusión

Prototipos de funciones

Invocación a una función

Se puede llamar a una función especificando su nombre seguido de una lista de argumentos encerrados entre paréntesis y separados por comas.

Si la llamada a la función no requiere ningún argumento, se debe escribir a continuación del nombre de la función un par de paréntesis vacíos.

Los parámetros que se usan en la llamada normal a una función, se llaman parámetros actuales y debe haber uno por cada parámetro formal.

Invocación a una función

a=pow(2,3);//a=8 La anterior es una sentencia de

invocación a una función en sentencia de asignación para almacenar el valor retornado

El compilador puede hacer conversiones automáticas de tipos de los parámetros

Funciones y procedimientos

Variables externas y alcance

Las variables definidas dentro de main() o cualquier otra función, al igual que los argumentos de ellas, son privadas o locales a la misma.

Cada variable local de una función comienza a existir sólo cuando se llama a la función y desaparece cuando la misma termina (variables automáticas)

Variables externas y alcance

Las variables locales no retienen sus valores entre 2 llamadas sucesivas y deben inicializarse explícitamente en cada entrada, de no hacerlo contendrán “basura” (las externas se inicializan a 0 por defecto)

Como alternativas a las variables automáticas es posible definir variables que son externas (como opuesto a internas) a todas las funciones, a las que todas las funciones del archivo pueden tener acceso por su nombre

Variables externas y alcance

Pueden usarse en lugar de listas de argumentos para comunicar datos entre funciones.

Se mantienen permanentemente en existencia, a diferencia de las locales

Una variable externa debe definirse exactamente una sola vez fuera de cualquier función, esto fija un espacio de almacenamiento para ella.

Variables externas y alcance

La variable externa debe también declararse en cada función que desee tener acceso a ella, esto establece el tipo de variable. La declaración debe ser una proposición extern explícita o puede estar implícita en el contexto.

Bajo ciertas circunstancias la declaración extern puede omitirse. Si la declaración ocurre dentro del archivo fuente antes de su uso por una función en particular, no es necesario esta declaración dentro de la función

Variables externas y alcance

Cuando se trabaja con un único archivo fuente es práctica común poner las definiciones de todas las variables externas al principio del mismo y después omitir todas las declaraciones extern.

Si el programa está dividido en varios archivos fuentes y una variable se define en archivo1 y se usa en archivo2 y archivo3, se necesitan declaraciones extern en archivo2 y archivo3 para conectar las ocurrencias de las variables

Variables externas y alcance

La práctica común es reunir declaraciones extern de variables en un archivo separado llamado históricamente header (cabecera), que se incluye por #include al principio de cada archivo fuente. El sufijo .h se usa por convención para nombre de header

Variables externas y alcance

La palabra definición se refiere al lugar donde se crea la variable o se le asigna un lugar de almacenamiento

La palabra declaración se refiere al lugar donde se establece la naturaleza (en especial el tipo) de la variable pero no se le asigna espacio

Variables externas y alcance

Los tamaños de un array deben especificarse en la definición pero es optativo hacerlo en una declaración extern

La inicialización de una variable externa sólo va con su definición

Variables externas y alcance

Las variables externas existen siempre aún cuando no hacen falta. Usarlas en exceso es peligroso puesto que lleva a programas cuyas conexiones entre datos no son completamente obvias, las variables pueden cambiar de forma inesperada e inadvertida y el programa es difícil de modificar

Quedan ocultas por variables locales (o argumentos formales) con el mismo nombre

Variables externas

Variables externas

Modificadores de acceso

Además de los modificadores de tipo existen modificadores de acceso. Los modificadores de acceso limitan el uso que puede realizarse de las variables declaradas.

Los modificadores de acceso anteceden a la declaración del tipo de dato de la variable

Modificadores de acceso

register: indica al compilador que la variable en cuestión se empleará intensamente (por ejemplo en lazos de iteración) y se le solicita que se almacene en registros de la CPU en lugar de la memoria. Los compiladores tienen la libertad de ignorar esta sugerencia

Sólo puede aplicarse a variables locales (incluyendo argumentos formales)

Hoy día se usan raramente

Modificadores de acceso

volatile: modificador de acceso que permite cambiar el valor de una variable por medios no especificados explícitamente por el programa (por un proceso externo al propio programa, por ej.variable actualizada por el reloj del sistema)

Indica al compilador que no trate de optimizar dicha variable suponiéndole un valor constante, etc. Ello fuerza a que cada vez que se usa la variable, se realice una comprobación de su valor.

Resolver ejercicio

Escriba un programa que tenga una función main donde se invoque a otra función que calcule el cuadrado de un número entero positivo pasado como argumento.

La función debe calcular el cuadrado del número n pasado como argumento como la suma de los n primeros números impares

Ejemplo: 52: 1+3+5+7+9

#include <stdio.h>

unsigned int cuadrado(unsigned int);

int main(){

unsigned int nro, cuad;

printf("Ingrese 1 entero positivo para calcular cuadrado: ");

scanf("%u", &nro);

cuad=cuadrado(nro);

printf("El cuadrado del numero %u es: %u\n",nro, cuad);

return 0;

}

//Calcula el cuadrado del entero >0 n como la suma

//de los n primeros impares

unsigned int cuadrado(unsigned int n) {

unsigned int suma=0;

int i;

for(i=1;i<2*n;i+=2)//i+=2 es lo mismo que i=i+2

//para recorrer sólo los impares, ojo!!no poner i+2

suma+=i; //lo mismo que suma=suma+i;

return suma;

}

Modificadores de acceso Los modificadores const y volatile pueden

usarse de forma conjunta en ciertos casos, por lo cual no son excluyentes el uno del otro. Ello es posible si se declara una variable que actualizará el reloj del sistema, (proceso externo al programa/rutina de servicio de interrupción), y que no queremos pueda modificarse en el interior del programa. Por ello, podremos declarar:

volatile const unsigned long int hora; Una interrupción es una acción en software

requerida por el hardware

Volatile

// Esta suele ser parte de una declaración global volatile int flag = 0; // Esto es parte de un proceso ... while( !flag ) { // hacer algo mientras el flag sea falso } ...// Y esto es parte de una rutina de interrupción //y está en una función diferente del proceso. ... if( pasa_algo ) { flag = 1; } ...

Volatile

Hay que declarar flag como volatile, por que si no, el compilador puede guardar el valor de flag en un registro de la CPU para acelerar la evaluación de la condición del while, perdiendo las modificaciones introducidas por la rutina de servicio de la interrupción (ISR), si es que ocurrió una mientras estaba en el while. Poniéndola como volatile, forzás al compilador a generar código para recargar siempre de memoria el valor de la variable antes de verificar si es verdadero o falso. Algo parecido sucede para la ISR.

Variables static

La declaración static aplicada a una variable o función externa limita el alcance de ese objeto al resto del archivo fuente que se está compilando, no pueden accederse desde otros archivos fuentes

Se pueden utilizar estos nombres para definir variables en funciones de otros archivos fuentes sin ningún problema, evitando que entren en conflicto

Variables static

Variables static

La declaración static externa se usa con más frecuencia en variables, pero también se puede aplicar a funciones.

Normalmente los nombres de funciones son globales, visibles a cualquier parte del programa completo. Sin embargo, si una función se declara como static, su nombre es invisible fuera del archivo en el que está declarada.

Variables static

La declaración static también puede aplicarse a variables internas.

Las variables internas static son locales a una función particular, tal como las variables automáticas pero a diferencia de ellas, mantienen su existencia en lugar de ir y venir cada vez que se activa la función. Esto significa que las variables internas static proporcionan almacenamiento privado y permanente dentro de una función

Variables static

Variables static

La salida al ejecutar es:

Estructura de bloques

Las declaraciones de variables (incluyendo la inicialización) pueden seguir a la llave izquierda ({) que indica comienzo de bloque y no sólo después de aquélla que comienza el cuerpo de una función. Las variables declaradas de esta forma ocultan cualquier nombre idéntico de variables en bloques externos y, permanecen hasta que se encuentra la llave derecha (}) que corresponde con la inicial.

Estructura de bloques

Ejemplo:if(n>o){

int i; //declara una nueva i ... for(i=0;i<n;i++) ...}//no tiene que ver con otras i fuera de este

//bloque

Estructura de bloques

Una variable automática declarada e inicializada en un bloque se inicializa cada vez que se entra al mismo.

Una variable static se inicializa sólo la primera vez que se entra al bloque

Las variables automáticas incluyendo parámetros formales esconden a las variables y funciones externas del mismo nombre. Es mejor evitar nombres de variables que coinciden con nombres de un alcance exterior; la potencialidad de confusión y error es muy grande

Resumen de reglas de inicialización

En ausencia de una inicialización explícita se garantiza que las variables externas y static se inicializan en cero; las variables automáticas y register tienen valores iniciales indefinidos (basura)

Las variables escalares se pueden inicializar cuando se definen. Ej: int x=1;

long dia=1000L*60L*60L*24L;//mseg/día

Reglas de inicialización

Para variables externas y estáticas el inicializador debe ser una expresión constante, se realiza una única vez, conceptualmente antes que el programa comience su ejecución

Para variables automáticas o register se hace cada vez que se entra a la función o bloque. El inicializador no se limita a una constante, puede ser cualquier expresión que contenga valores previamente definidos, incluso llamado a funciones.

Reglas de inicialización

Un array puede inicializarse al seguir su declaración con una lista de inicializadores encerrados entre {} y separados por comas.

int dia[]={31,28,31,30,31,30,31,31,30,31,30,

31}; Si se omite el tamaño, el compilador calcula

la longitud contando los inicializadores

Reglas de inicialización

Si existen menos inicializadores para un arreglo que los del tamaño especificado, los otros serán 0 para variables externas o estáticas, pero basura para automáticas

En el caso de un arreglo de caracteres: char saludo[]=“Hola”;

En este caso la cadena tiene un tamaño igual a 5: 4 caracteres más el terminador ‘\0’

Recursividad

Las funciones pueden emplearse recursivamente, es decir, una función puede llamarse a sí misma

No proporciona ahorro de almacenamiento puesto que en algún lugar se debe mantener la pila de valores procesados. Ni es mucho más rápida

Pero el código es generalmente más compacto y mucho más fácil de escribir y de entender que su equivalente no recursivo

Recursividad

Ejemplo 1

El siguiente programa muestra como una función recibe un vector y la dimensión del vector en sus parámetros y retorna el promedio de sus componentes, también muestra como una función permite ingresar datos a un vector y como una función puede imprimir un vector.

Ejemplo 2

El siguiente programa muestra tres funciones, que pasan por referencia matrices. La función leematriz, permite almacenar m*n elementos en una matriz A cualquiera, la función sumaMatrices recibe dos matrices A y B y calcula en una matriz C la suma de A y B.

Archivos de cabecera

Pueden contener: Definiciones de tipos Prototipos de funciones Directivas del preprocesador

Pueden usarse para “exportar” tipos y funciones de un archivo C

Otros archivos pueden “importarlos” a dichos archivos usando las directivas de #include

El preprocesador de C

El preprocesador es un primer paso separado en la compilación

Lee y reacciona antes las directivas Comandos que comienzan con # Comentarios (los borra)

La salida del preprocesador es luego compilada

Las directivas no son realmente parte del lenguaje C pero expanden el ámbito del entorno de programación en C

El preprocesador de C

Borra comentarios Inserta los archivos de inclusión Reemplaza macros en el código fuente Realiza compilación condicional

Inclusión de archivos

Inclusión de archivos

Cualquiera de las 2 hace que el preprocesador las reemplace por el contenido del archivo fichero

Si el nombre se encierra entre “ ” la búsqueda del archivo comienza normalmente donde se encuentra el código fuente, sino se encuentra allí

O se delimita por < > sigue una ruta predefinida por la implantación (librerías)

No repetir estas directivas

Sustitución de macros

Sustitución de macros

Para definir constantes simbólicas y macros No puede haber blancos entre el nombre de

la macro y el ( cuando hay lista de parámetros

Los parámetros se ponen entre paréntesis para protegerse contra la expansión que pueda conducir a un orden de evaluación no deseado

Sustitución de macros

Macros Las macros pueden realizar cómputos simples,

mucho más rápidos que las funciones ya que no requieren paso de parámetros via la pila

Pero no definen el tipo de argumento. Sin embargo son valiosas. Muchas funciones

de librerías están definidas como macros, ej.:getchar/putchar, para evitar el exceso de tiempo de ejecución de una llamada a función por cada carácter procesado

Por convención use nombres en mayúsculas para las macros

Compilación condicional

Es posible controlar el preprocesamiento mismo con proposiciones condicionales que se evalúan durante esta etapa. Esto proporciona una forma de incluir código selectivamente, dependiendo del valor de condiciones evaluadas durante la compilación

Compilación condicional

Compilación condicional

Compilación condicional

Compilación condicional

Se hace para asegurarse de que el contenido de un archivo aux.h se incluya una sola vez, el contenido del archivo se delimita con una condicional como la del ejemplo anterior

La primera inclusión de aux.h define el nombre _AUX_H_ , las siguientes inclusiones encontrarán definido el nombre y pasarán hacia el #endif.

Un estilo semejante puede emplearse para evitar incluir archivos varias veces

top related