LENGUAJE DE PROGRAMACIÓN II SAETI T

August 28, 2017 | Author: Joseph Marquez Gutierrez | Category: Programming Language, Pointer (Computer Programming), Computer File, Computer Program, Compiler
Share Embed Donate


Short Description

Download LENGUAJE DE PROGRAMACIÓN II SAETI T...

Description

LENGUAJE DE PROGRAMACIÓN II SAETI T. VESPERTINO: CARGA DE TRABAJO. UNIDAD 1: REGISTROS: 1.1 CONCEPTOS GENERALES. LENGUAJE DE PROGRAMACIÓN: Es un conjunto de símbolos junto a un conjunto de reglas para combinar dichos símbolos que se usan para expresar programas. Constan de un léxico, una sintaxis y una semántica. ¿Qué conoces tu por léxico, sintaxis y semántica? c : Conjunto de símbolos permitidos o vocabulario  : Reglas que indican cómo realizar las construcciones del lenguaje   Reglas que permiten determinar el significado de cualquier construcción del lenguaje. Tipos de lenguajes: Atendiendo al número de instrucciones necesarias para realizar una tarea específica podemos clasificar los lenguajes informáticos en dos grandes bloques: · bajo nivel · alto nivel Lenguaje de bajo nivel Es el tipo de lenguaje que cualquier computadora es capaz de entender. Se dice que los programas escritos en forma de ceros y unos están en lenguaje de máquina, porque esa es la versión del programa que la computadora realmente lee y sigue. Lenguajes de alto nivel Son lenguajes de programación que se asemejan a las lenguas humanas usando palabras y frases fáciles de entender. · En un lenguaje de bajo nivel cada instrucción corresponde a una acción ejecutable por el ordenador, mientras que en los lenguajes de alto nivel una instrucción suele corresponder a varias acciones.

1.2 QUE ES UN CAMPO: Hay varios campos de estudio que o bien caen dentro de la teoría de lenguajes de programación, o bien tienen una profunda influencia en ella; muchos de estos se superponen considerablemente. 4

4

4 4

4

4

4

4

Teoría de los compiladores es la base formal sobre la escritura de compiladores (o más generalmente traductores); programas que traducen un programa escrito en un lenguaje a otra forma. Las acciones de un compilador se dividen tradicionalmente en análisis sintáctico (escanear y parsear), análisis semántico (determinando que es lo que debería de hacer un programa), optimización (mejorando el rendimiento indicado por cierta medida, típicamente la velocidad de ejecución) y generación de código (generando la salida de un programa equivalente en el lenguaje deseado; a menudo el set de instrucciones de una CPU). La Teoría de tipos es el estudio de sistemas de tipos, que son "métodos sintácticos tratables para proveer la ausencia de ciertos comportamientos de programa mediante la clasificación de frases según los tipos de valores que computan." (Types and Programming Languages, MIT Press, 2002). Muchos lenguajes de programación se distinguen por las características de sus sistemas de tipos. La Semántica formal es la especificación formar del comportamiento de programas de ordenador y lenguajes de programación. La Transformación de programas es el proceso de transformar un programa de una forma (lenguaje) a otra forma; el análisis de programas es problema general de examinar un programa mediante la determinación de sus características clave (como la ausencia de clases de errores de programa). istemas en tiempo de ejecución se refiere al desarrollo de entornos runtime para lenguajes de programación y sus componentes, incluyendo máquinas virtuales, recolección de basura, e interfaces para funciones externas. |          busca clasificar los lenguajes de programación en diferentes tipos basados en sus características; amplias categorías de diferentes lenguajes de programación se conocen frecuentemente como paradigmas de computación. Metaprogramación es la generación de programas de mayor orden que, cuando se ejecutan, producen programas (posiblemente en un lenguaje diferente, o en un subconjunto del lenguaje original) como resultado. Lenguajes dedicados son lenguajes construidos para resolver problemas en un dominio de problemas en particular de manera eficiente.

Además, PLT hace uso de muchas otras ramas de las matemáticas, ingeniería del software, lingüística, e incluso ciencias cognitivas

1.3 CONCEPTO DE ESTRUCTURAS: _     Una estructura es un tipo de dato definido por el usuario, al utilizar una estructura Usted tiene la habilidad para definir un nuevo tipo de dato considerablemente más complejo que los tipos que hemos utilizado hasta ahora. Una estructura es una combinación de varios tipos de datos previamente definidos, incluyendo otras estructuras que hayamos definido previamente. Una definición simple es, "una estructura es un grupo de datos relacionados en una forma conveniente al programador y/o al usuario del programa". Como es costumbre, un ejemplo nos clarifica los conceptos:

#include struct { char inicial; /* Letra inicial del apellido */ int edad; /* Edad */ int calificacion; /* Aprovechamiento */ } chico, chica; int main() { chico.inicial = 'R'; chico.edad = 15; chico.calificacion = 75; chica.edad = chico.edad - 1; /* Ella es un año menor que él */ chica.calificacion = 82; chica.inicial = 'H'; printf("%c tiene %d anos y su calificacion es de %d\n", chica.inicial, chica.edad, chica.calificacion); printf("%c tiene %d anos y su calificacion es de %d\n", chico.inicial, chico.edad, chico.calificacion); return 0; } El programa empieza definiendo una estructura utilizando la palabra clave  seguida de tres variables sencillas encerradas entre llaves, las cuales son los componentes de la estructura, despues de la llave de cierre tenemos enlistadas dos variables llamadas  y . De acuerdo a la definición de una estructura,  es una variable compuesta de tres elementos, ,  y, . Cada uno de los tres campos están asociados a  y cada uno almacena una variable de su respectivo tipo, lo mismo se puede decir para  pero sus variables son diferentes por lo tanto tenemos 6 variables agrupadas en dos, de tipo .

1.4 MANIPULACIÓN DE ESTRUCTURAS (CON EJEMPLO): El siguiente programa es básicamente el mismo que el anterior, pero esta vez definimos un array de 12 variables llamadas  , está claro que éste programa contiene 12 veces 3=36 variables sencillas cada una de las cuales puede almacenar un ítem de dato siempre y cuando sea del tipo adecuado, se define además una variable común llamada  para utilizarla en los bucles, estudie el código:

#include struct { char inicial; int edad; int calificacion; } chicos[12]; int main() { int indice; for (indice = 0; indice < 12; indice++) { chicos[indice].inicial = 'A' + indice; chicos[indice].edad = 16; chicos[indice].calificacion = 84; } chicos[3].edad = chicos[5].edad = 17; chicos[2].calificacion = chicos[6].calificacion = 92; chicos[4].calificacion = 57; /* Asignacion de estructura solo en compiladores ANSI-C */ chicos[10] = chicos[4]; for (indice = 0; indice < 12; indice++) printf("%c tiene %d anos y una calificacion de %d\n", chicos[indice].inicial, chicos[indice].edad, chicos[indice].calificacion); return 0; }

1.5 MANIPULACIÓN DE ESTRUCTURAS (CON EJEMPLO): Para asignar un valor a cada uno de los campos utilizamos un bucle , en cada ciclo del bucle se asignan todos los valores para uno de los chicos, en una situación real ésta podría no ser la mejor manera de asignar datos, pero un bucle puede leer los datos de un archivo y almacenarlos en la correcta ubicación en un programa real, considere éste ejemplo como un inicio burdo a una base da datos, pues eso es justamente nuestro ejemplo. El código resulta fácil de entender, solo haré un comentario respecto a la línea 26 en donde podemos ver una asgnación de estructura, en éste enunciado los tres campos de   son copiados en los respectivos campos de   , esto no siempre está permitido en el lenguaje C, solo en los compiladores que cumplen con la norma ANSI-C, si su compilador no es ANSI-C encierre en comentarios la línea 26. El resultado de la ejecución delprograma es el siguiente:

UNIODAD II: ARCHIVO:

2.1 CONCEPTOS GENERALES CAMPO, ESTRUCTURA, ARCHIVO: _     Para finalizar la presente lección estudiaremos el concepto de   ! , en el siguiente código podemos ver la manera de definirlo y utilizarlo, en el programa tenemos una unión de una variable sencilla de tipo  en la línea 5 y la estructura definida en las líneas 6 a la 12:

#include union { int indice; struct { unsigned int x : 1; unsigned int y : 2; unsigned int z : 2; } bits; } numero; int main() { for (numero.indice = 0; numero.indice < 20; numero.indice++) { printf("indice = %3d, bits = %3d%3d%3d\n", numero.indice, numero.bits.z, numero.bits.y, numero.bits.x); } return 0; } La estructura está compuesta de tres campos de bits llamados , ", y #. La variable llamada  es de un solo bit, la variable " es de dos bits y es adyacente a la variable , y la variable # es de dos bits y adyacente a la variable ". Como la unión causa que los bits sean almacenados en la misma ubicación en memoria que la variable  , la variable  es el bit menos significante de la variable  , " conforma los siguientes dos bits, y # es almacenado en los siguientes dos bits de  . Compile y ejecute el programa y verá que al ser incrementada la variable  en cada ciclo del bucle, verá los campos de bits incrementarse en sus respectivas ubicaciones. Una cosa debemos señalar, los campos de bits deben definirse como partes de un tipo    de lo contrario el compilador marcará error. El resultado de la ejecución del programa es:

÷ ÷      ÷   Los archivos como colección de datos sirve para la entrada y salida a la computadoray son manejados con programas. Los archivos pueden ser contrastados con Arrays y registros; Lo que resulta dinámico y por esto en un registrose deben especificar los campos, él número de elementos de un arrays (o arreglo), el número de caracteres en una cadena; por esto se denotan como " Estructuras Estáticas". En los archivos no se requiere de un tamaño predeterminado; esto significa que se pueden hacer archivos de datos más grandes o pequeños, según se necesiten. Cada archivo es referenciado por su identificador (su nombre.).    ÷     ÷  Las principales características de esta estructura son: Independencia de las informaciones respecto de los programas La información almacenada es permanente Un archivo puede ser accedido por distintos programas en distintos momentos Gran capacidad de almacenamiento.  ÷÷ ÷     ÷  Los archivos se clasifican según su uso en tres grupos: V    $  Estos contienen información que varia poco. En algunos casos es preciso actualizarlos periódicamente.

? $   Se cercan para actualizar los archivos maestros. Sus registros son de tres tipos: alta, bajas y modificaciones. ? $!%!& Tienen una vida limitada, normalmente menor que la duración de la ejecución de un programa. Su utilizan como auxiliares de los anteriores. ÷   ÷  Los elementos de un archivo pueden ser de cualquier tipo, simples o estructurados o según su función.     ÷  Se define por: &'| V    Son aquellos cuyo registros sufren pocas o ninguna variación a lo largo del tiempo, se dividen en: (  Están formados por registros que contienen campos fijos y campos de baja frecuencia de variación en el tiempo. ?  Son los que en cada momento contienen información actualizada. )  Contienen información acumulada a lo largo del tiempo de archivos que han sufridos procesos de actualización o bien acumulan datos de variación periódica en el tiempo. !&'|  $   Son aquellos que se utilizan conjuntamente con los maestros (constantes), y contienen algún campo común en sus registros con aquellos, para el procesamiento de las modificaciones experimentados por los mismos. &'| $!%  Son los archivos creados auxiliares creados durante la ejecución del programa y borrados habitualmente al terminar el mismo.         Los principales archivos de este tipo son: | *: Una colección de datos localizados en un dispositivo de entrada. | : Una colección de información visualizada por la computadora. (  : están formados por registros que contienen campos fijos y campos de baja frecuencia de variación en el tiempo. ? : son los que en cada momento contienen información actualizada. )  : Contienen información acumulada a lo largo del tiempo de archivos que han sufrido procesos de actualización, o bien acumulan datos de variación periódica en el tiempo.

|  $  %  : Son aquellos que se utilizan conjuntamente con los maestros (constantes), y contienen algún campo común en sus registros con aquellos, para el procesamiento de las modificaciones experimentados por los mismos. |  $!%  : Son los archivos auxiliares creados durante la ejecución del programa y borrados habitualmente al terminar el mismo.        Los principales archivos de este tipo son: | *, una colección de datos localizada en un dispositivo de entrada. | , una colección de información visualizada por la computadora. | V , un programa codificado en un lenguaje especifico y localizado o almacenado en un dispositivo de almacenamiento. | % , una colección de caracteres almacenados como una unidad en un dispositivo de almacenamiento.        ÷  Se refiere al métodoutilizado para acceder a los registros de un archivo prescindiendo de su organización. Existen distintas formas de acceder a los datos:    ; los registros se leen desde el principio hasta el final del archivo, de tal forma que para leer un registro se leen todos los que preceden. ? ; cada registro puede leerse / escribirse de forma directa solo con expresar su direcciónen el fichero por él numero relativo del registro o por transformaciones de la clave de registro en él numero relativo del registro a acceder. V+ ; se accede indirectamente a los registros por su clave, mediante consulta secuenciales a una tabla que contiene la clave y la dirección relativa de cada registro, y posterior acceso directo al registro. ? ,es cuando se accede a los archivos en cualquier de los modos anteriormente citados. La elección del método esta directamente relacionada con la estructura de los registros del archivo y del soporte utilizado.

2.2 ARCHIVOS DE TEXTO: INTRODUCCIÓN, DECLARACIÓN, APERTURA Y MANIPULACIÓN (CON EJEMPLO):  ÷   También conocidos como (Slream File) son utilizados para almacenar documentos que consisten en texto; En ellos, cada registro es un solo símbolo o código de control. El leer estos archivos recibimos la información en orden secuencial en el que aparece cuando lo vemos en un monitor. Los archivos de texto son una secuencia de líneas separadas por marcas de fin de línea.

m        , El usuario escribe los archivos de textos mediante un procesador de palabras que le permitirá almacenar la información pero no estrictamente en forma secuencial. El procesador también nos permite desplazarnos por todo el bloque de información y permitirnos realizar modificaciones. Mientras el usuario avance rápidamente en la lectura de registro lograra ver mas archivos. c     Crea el siguiente archivo de texto uitlizando un editor de texto cualquiera: 1.2 2512 2.4 1324 3.2 547 Escribe un programa en C que lea este archivo y calcule la suma de los productos de los números de la primera columna por los de la segunda. 1.2 * 2512 + 2.4 *1324 + 3.2 * 547 El programa debe valer para cualquier archivo con este formato y escribir el resultado en el monitor. Utiliza el depurador para comprobar el orden en que se van leyendo los datos del archivo. El orden es (elige una respuesta): 1. 2. 3. 4.

De arriba hacia abajo y de izquierda a derecha (1.2 -> 2512 -> 2.4 -> 1324 ...) De arriba hacia abajo y de derecha a izquierda (2512 -> 1.2 -> 1324 -> 2.4 ...) De abajo hacia arriba y de derecha a izquierda De abajo hacia arriba y de izquierda a derecha

A continuación puedes estudiar tres soluciones ligeramente diferentes, dependiendo de cómo se utiliza la función fscanf. Puedes comprobar que el número de formatos en el segundo argumento debe coincidir con el de variables.  #include void main () { FILE * f; int a2, a4, a6; double a1, a3, a5, suma; f = fopen ("numeros.txt", "r"); // Un formato y una variable

fscanf (f, "%lf", &a1); fscanf (f, "%d", &a2); fscanf (f, "%lf", &a3); fscanf (f, "%d", &a4); fscanf (f, "%lf", &a5); fscanf (f, "%d", &a6); fclose (f); suma = a1*a2 + a3*a4 + a5*a6; printf ("Suma = %.0lf\n", suma); }

Nombre

Descripción

ReadAllText(String)

Abre un archivo de texto, lee todas sus líneas y, a continuación, cierra el archivo.

ReadAllText(String,

Abre un archivo, lee todas sus líneas con la

Encoding)

codificación especificada y, a continuación, cierra el archivo

2.3 ARCHIVO DE ESTRUCTURAS: INTRODUCCIÓN, DECLARACIÓN, APERTURA Y MANIPULACIÓN (CON EJEMPLO): ESTRUCTURA:    !        - &*   -     "            ( &V  .        &V    m|$     ."      archivo o            /.  ! . 0&  #1        .         !& *V .       1       

.  1         .2      .1                  3.       &

* !     .       r!isro&*V .        # 2 (*m-. 1   4    r!isro .  45r!isro." 6         *-7& %!V       V     1     & *V   .                1  &*               "    .             2    V     #&(  .  1  V      /     0   #      "    & *%!V       archivosisco&c                 #      &c         V 

              !         .1 %!V 

    "       & c     %!V "V   .   1 

#   &*V   . !         !     ! #  ."       &*%!V .     !  #  variablarchivo      | /! 4. ! 40, " !      /!  0  /! 40  8 /! 40   # & | .   !   6        /! 40.   1  # .       1     /! 40& ! 4   !   /buffr0.               &  ! 4   ! 1     &  !        "lapunaorr!isro 

   / 0&  8   / ! ' !      0"!      apunaorr!isro     &

*     .  1          lcura.   1  8         scriura& c  !        9    

       "    &|   !   !    :nombrsarchivo rno:. 1    !  1  !   &

( typedef enum TTADO{OLTERO,CAADO,VIUDO}Tstado; typedef struct TCLIENTE{ int edad ; char nombre[51]; float saldo; Tstado estado; }TCliente;

Escritura: ( int escribir_bin(int fin,TCliente *clte){ FILE *archivo; int nex=0; archivo=fopen("DatosBanco.dat","wb"); if (archivo!=NULL) { nex+=fwrite(clte,sizeof(TCliente),fin+1,archivo); fclose(archivo); return nex; } return -1; }

Lectura: ( int leer_bin(int fin, TCliente *vector){ FILE *archivo; int nex=0; archivo=fopen("DatosBanco.dat","rb"); if (archivo!=NULL) { fseek(archivo,0,EEK_ET); nex+=fread(vector,sizeof(TCliente),fin+1,archivo); fclose(archivo); return nex; } else return -1; }

#include 02 //ahora debemos de incluir nuestra estructura // 03 //para este ejemplo usaremos una estructura llamada albañil 04 05 //la cual contiene los siguientes datos //nombre, folio, RFC, direccion, mail, horas trabajasdas, activida realizada y su tipo de 06 pago 07 08 struct albanil { 09 10

char nombre[50]; char folio[10];

char RFC[11]; 12 char calle[20]; 11

13 char CP[6]; 14 char colonia[20]; 15 char mail[50];

16 char horas[2]; 17 char actividad[50]; 18 char pago[4]; 19 };struct albanil albanil; 20 21 //ahora dentro de nuestro main 22 23 int main() 24 { 25

FILE *ptr; //inicializaremo una variable a archivo como apuntador char archivo[50];//y tendremos una cadena archivo para guardar el archiv con el 26 nombre que sedessee 27 28

printf("Como quieres que se llame tu archivo "); scanf("%s",&archivo);

29 30

printf("Dime tu numero de folio "); scanf("%s",albanil.folio);

31 32

printf("Dime tu nombre "); scanf("%s",albanil.nombre);

33 34

printf("Dime tu RFC "); scanf("%s",albanil.RFC);

35 36

printf("Dime tu direccion "); scanf("%s",albanil.calle);

37 38

printf("Dime tu codigo postal "); scanf("%s",albanil.CP);

39 40

printf("Dime tu colonia "); scanf("%s",albanil.colonia);

41 42

printf("Dime tu correo electronico "); scanf("%s",albanil.mail);

43 44

printf("Dime cuantas horas trabajaste "); scanf("%s",albanil.horas);

45 46

printf("Dime en que trabajaste "); scanf("%s",albanil.actividad);

47 48

printf("Dime cuanto te van a pagar "); scanf("%s",albanil.pago);

49 50

ptr=fopen(archivo,"a"); fprintf(ptr,"folio %s\n",albanil.folio);

51 52

fprintf(ptr,"nombre %s\n",albanil.nombre); fprintf(ptr,"RFC %s\n",albanil.RFC);

53 54

fprintf(ptr,"calle %s\n",albanil.calle); fprintf(ptr,"cp %s\n",albanil.CP);

55 56

fprintf(ptr,"colona %s\n",albanil.colonia); fprintf(ptr,"correo %s\n",albanil.mail);

57 58

fprintf(ptr,"horas %s\n",albanil.horas); fprintf(ptr,"actividad %s\n",albanil.actividad);

59 60

fprintf(ptr,"pago %s\n",albanil.pago); fclose(ptr);

61

return 0;

2.4 ARCHIVOS SIN TIPO: %   #    2  &         ! # &c       *; ! .  #    1       " & (1         &%!V         !1          1   & c        m  =>?

7  =>m  %   !1     ! & 7  =>m /.! .!1 . 0   ! !  1              !1   1   2   !1  59!"   &   1  2   !1 1   "  !     &

=>?

%   !    & c       . !1       #  6    ,     !1 1       

 "! & *          1         &c               6/  (" $'?-0&

*  V (, m /  .! .# -/! 0.  0, 8   C  !  =>? / .! .# -/! 0.  0, =>m /  .! .# -/! 0.  0  ,  /  0,  / 0

&

UNIDAD III: APUNTADORES: 3.1 DIRECCIONES DE MEMORIA: -!     &- J Para almacenar una referencia a un objeto en un puntero se puede aplicar al objeto el operador prefijo J, que lo que hace es devolver la dirección que en memoria ocupa el objeto sobre el que se aplica. Un ejemplo de su uso para inicializar un puntero es:

 x =10;  * px = &x; Este operador no es aplicable a expresiones constantes, pues éstas no se almacenan en ninguna dirección de memoria específica sino que se incrustan en las instrucciones. Por ello, no es válido hacer directamente:

 px = &10; // Error 10 no es una variable con dirección propia Tampoco es válido aplicar Ja campos  ", pues si estos pudiesen ser apuntados por punteros se correría el riesgo de poderlos modificar ya que a través de un puntero se accede a memoria directamente, sin tenerse en cuenta si en la posición accedida hay algún objeto, por lo que mucho menos se considerará si éste es de sólo lectura. Lo que es sí válido es almacenar en un puntero es la dirección de memoria apuntada por otro puntero. En ese caso ambos punteros apuntarían al mismo objeto y las modificaciones a éste realizadas a través de un puntero también afectarían al objeto visto por el otro, de forma similar a como ocurre con las variables normales de tipos referencia. Es más, los operadores relacionales típicos (FF,KF,B,C,BFyCF) se han redefinido para que cuando se apliquen entre dos punteros de cualesquiera dos tipos lo que se compare sean las direcciones de memoria que estos almacenan. Por ejemplo:

 x = 10;  px = &x;  px2 = px; // px y px2 apuntan al objeto almacenado en x Console.WriteLine( px == px2); // Imprime por pantalla True

En realidad las variables sobre las que se aplique J no tienen porqué estar inicializadas. Por ejemplo, es válido hacer:

  f() {  x;  

{  px = &x;} } Esto se debe a que uno de los principales usos de los punteros en C# es poderlos pasar como parámetros de funciones no gestionadas que esperen recibir punteros. Como muchas de esas funciones han sido programadas para inicializar los contenidos de los punteros que se les pasan, pasarles punteros inicializados implicaría perder tiempo innecesariamente en inicializarlos. |    &- L Un puntero no almacena directamente un objeto sino que suele almacenar la dirección de memoria de un objeto (o sea, apunta a un objeto) Para obtener a partir de un puntero el objeto al que apunta hay que aplicarle al mismo el operador prefijo L, que devuelve el objeto apuntado. Por ejemplo, el siguiente código imprime en pantalla un 10:

 x = 10;  * px= &x; Console.WriteLine(*px); Es posible en un puntero almacenar para indicar que no apunta a ninguna dirección válida. Sin embargo, si luego se intenta acceder al contenido del mismo a través del operador L se producirá generalmente una excepción de tipo Em    *  (aunque realmente esto depende de la implementación del lenguaje) Por ejemplo:

 * px = ; Console.WriteLine(*px); // Produce una NullReferenceException No tiene sentido aplicar La un puntero de tipo L ya que estos punteros no almacenan información sobre el tipo de objetos a los que apuntan y por tanto no es posible recuperarlos a través de los mismos ya que no se sabe cuanto espacio en memoria a partir de la dirección almacenada en el puntero ocupa el objeto apuntado y, por tanto, no se sabe cuanta memoria hay que leer para obtenerlo.

3.2 APUNTADORES: 1.-Un Apuntador es una variable que contiene una dirección de memoria, la cual corresponderá a un dato o a una variable que contiene el dato. Los apuntadores también deben de seguir las mismas reglas que se aplican a las demás variables, deben tener nombre únicos y deben de declararse antes de usarse. Cada variable que se utiliza en una aplicación ocupa una o varias posiciones de memoria. Estas posiciones de memoria se accesan por medio de una dirección.

3.3 APUNTADORES A ENTEROS:

int *p;

p es un apuntador a un entero

int *p[10];

p es un arreglo de 10 apuntadores a enteros

int (*p)[10];

p es un apuntador a un arreglo de 10 enteros

int *p(void);

p es una función que devuelve un apuntador a entero

int p(char *a);

p es una función que acepta un argumento que es un apuntador a carácter, devuelve un entero

int *p(char *a);

p es una función que acepta un argumento que es un apuntador a carácter, devuelve un apuntador a entero

int (*p)(char *a);

p es un apuntador a función que acepta un argumento que es un apuntador a carácter, devuelve un apuntador a entero

int (*p(char *a))[10];

p es una función que acepta un argumento que es un apuntador a carácter, devuelve un apuntador a un arreglo de 10 enteros

int p(char (*a)[]);

p es un apuntador a función que acepta un argumento que es un apuntador a un arreglo de caracteres, devuelve un apuntador a entero

int p(char *a[]);

p es un apuntador a función que acepta un argumento que es un arreglo de apuntadores a caracteres, devuelve un apuntador a entero

int *p(char a[]);

p es una función que acepta un argumento que es un arreglo de caracteres, devuelve un apuntador a entero

int *p(char (*a)[]);

p es una función que acepta un argumento que es un apuntador a un arreglo de caracteres, devuelve un apuntador a entero

int *p(char *a[]);

p es una función que acepta un argumento que es un apuntador a un arreglo de apuntadores a caracteres, devuelve un apuntador a entero

int (*p)(char (*a)[]);

p es una función que acepta un argumento que es un apuntador a un arreglo de caracteres, devuelve un apuntador a entero

int *(*p)(char (*a)[]);

p es un apuntador a una función que acepta un argumento que es un apuntador a un arreglo de apuntadores a caracteres, devuelve un apuntador a entero

int *(*p)(char

p es un apuntador a una función que acepta un argumento que es un

*a[]);

arreglo de apuntadores a caracteres, devuelve un apuntador a entero

int(*p[10])(void);

p es una arreglo de 10 apuntadores a función, cada función devuelve un entero

int (*p[10])(char * p es un arreglo de 10 apuntadores a función; cada función acepta un a); argumento que es un apuntador a carácter y devuelve un entero int *(*p[10])(char a);

p es un arreglo de 10 apuntadores a función; cada función acepta un argumento que es un carácter, y devuelve un apuntador a entero

char *(*p[10])(char p es un arreglo de 10 apuntadores a función; cada función acepta un * a); argumentoque es un carácter, y devuelve un apuntador a carácter.

A&M| | |  4

‘               

4

              

4

c               

‘ 

ï   ï   ï         †     †    ´    !" ## $ %& !"$  %#$ ± ·%!$† !$''( #·'(% 

 š !!  % $  ·%!$† !$''( ï ±· š) #· '( "($ â

4

à       *  

4

        % ''          %''%

|   ï    4

c     

4

‘ + ,          

4

à             



4

     

  #-"% ´          â 4

à +     

    . cc!

4

‘         +     

4

   *  

          

3.6 ARREGLOS A ESTRUCTURAS: V    Del mismo modo que ocurre con las funciones, las estructuras tienen una dirección, asumiendo que esta es el comienzo de su almacenamiento. Esto es especialmente cierto en C, donde las estructuras representan exclusivamente conjuntos de datos. En C++ las estructuras son cierto tipo de clases que pueden contener código (funciones), pero incluso entonces, lo que realmente se almacena en el cuerpo de la estructura son punteros (datos) a las funciones correspondientes.

O puesto que desde el punto de vista C++ las estructuras son un tipo de clases, les son aplicables los mismos principios y reglas que a aquellas. En concreto todo lo señalado respecto a punteros. Ver a este respecto "Punteros a clases" ( miembros" (

4.2.1f) y "Punteros a

4.2.1g).

Veremos que los punteros a estructuras son de uso muy frecuente para el manejo de estas; en especial cuando se pasan como argumentos a funciones, o son devueltas por estas. Por ejemplo, la sentenciaO struct punto {int x; int y;} pto = {3,4}, *ptr = &pto, arsp[10]; define un tipo de estructura denominado punto; una estructura (instancia) pto, y un puntero ptr a dicha instancia. Finalmente declara una matriz arsp de 10 estructuras tipo punto.

Ü    En general la sintaxis para declaración de punteros a estructuras sigue la sintaxis general (Declaración de punteros

4.2.1a).

†tipo_objeto> * †etiqueta_puntero> [ = †iniciador> ] En este caso, tipo_objeto es de la forma struct punto, con lo que la declaración esO struct punto * ptr; Opcionalmente puede incluirse un iniciador como en el ejemplo anteriorO struct punto * ptr = &pto; en este caso, ptr es un puntero, y su indirección *ptr, representa la estructura pto. Los miembros de la estructura pueden referenciarse mediante el operador de accesoO (*ptr).x == 3; (*ptr).y == 4; Los paréntesis son necesarios, ya que el operador de acceso (.) tiene mayor precedencia ( 4.9.0a) que el de indirección ( 4.9.11a). Por esta razón, *ptr.x es interpretada como *(ptr.x), lo que es erróneo, ya que ptr.x no es un puntero (en este caso es un entero).  Ü La expresiónO struct { int x1;

char * str; long *arr[10]; } *ptr;

Declara un puntero ptr a un tipo de estructura anónima de tres componentes

O aunque sintácticamente correcta y aceptable por el compilador, una declaración como la anterior es prácticamente inútil y muy peligrosa. Por ejemplo, la sentencia (*ptr).int = 30; puede producir una catástrofe. La razón es la misma que se apuntó en Expresiones peligrosas (

4.2.1a).

Ü Los punteros son muy importantes para el manejo de matrices y estructuras, por lo que en este caso se ha previsto una notación alternativa más corta (

4.5.4 Acceso a miembros)O

ptr->x == 3; ptr->y == 3;

Veamos las dos opciones de notación para acceso de miembros en un ejemplo con estructuras anidadasO struct punto { int x; int y; }; struct line { struct punto p1; struct punto p2; } lin, *liptr = &lin; En las sentencias anteriores hemos definido dos tipos de estructuras; una instancia y un puntero a dicha instancia. En estas condiciones, las expresiones que siguen son equivalentes (1 y 6 son preferibles por legibilidad)O lin.p1.x (lin.p1).x (*liptr).p1.x ((*liptr).p1).x liptr->p1.x (liptr->p1).x

// L1.

// L6.

Ü . ±loat pi = 3.14159; struct { int x; char * str; ±loat *arr[10]; struct punto pto; struct cuadro cuad; } str, *ptr = &str; upuestas las declaraciones anteriores, a continuación realizamos asignaciones a los miembros de str de dos formasO directamente y mediante expresiones del puntero ptr. Observe que según lo indicado al respecto del     (

4.5.1d), es perfectamente

compatible el nombre str de estructura con el de uno de sus miembros (el puntero a carácter str.str). Ü.1 Asignaciones directasO str.x = 30; str.str = "Hola mundo"; str.arr[0] = & pi; str.pto.x = 2; str.pto.y = 3; str.cuad.p1.x = 4; str.cuad.p1.y = 5; str.cuad.p2.x = 6; str.cuad.p2.y = 7; Ü.

Expresiones con punteroO

ptr->x = 30; ptr->str = "Hola mundo"; ptr->arr[0] = & pi; ptr->pto.x = 2; str.pto.y = 3; ptr->cuad.p1.x = 4; ptr->cuad.p1.y = 5; ptr->cuad.p2.x = 6; ptr->cuad.p2.y = 7;  Ü En el epígrafe relativo a la       ( señalado que los operadoresO 

Llamada de función



ubíndices



Acceso a miembro de estructura (mediante puntero)

.

Acceso a miembro de estructura

::

Acceso a miembro de clase

4.9.0a) se ha

constituyen el orden más alto en la jerarquía de precedencia, y que su asociatividad es de izquierda a derecha, por lo que hay que prestar especial atención a las expresiones en que aparecen. Para resaltar la importancia de las reglas de precedencia, en los ejemplos que siguen se exponen algunas expresiones, referidas al ejemplo (§5 significado.

), así como una explicación de su

++ Debido a la precedencia de operadores, equivale a $$(ptr->x). Así pues, incrementa el miembro x, no el valor del puntero ptr. ResultadoO str.x == 31 Ë Del mismo modo, esta indirección equivale a *(ptr->x), lo que resulta en un error, porque en el ejemplo indicado, ptr->x no es un puntero (es un ), y ya hemos visto [4.9.11] que el operando del operador de indirección debe ser un puntero. Ë

En este caso, si es correcta la aplicación del operador *; la expresión equivale a *(ptr->str), y ptr->str sí es un puntero (a carácter); concretamente señala a la primera posición de la cadena, es decirO *ptr->str == 'H' se puede evidenciar como sigueO print±("Letra \"%c\"\n",

*ptr->str);

// -> Letra "H"

++Ë e ha señalado que *ptr->str equivale a 'H'; ahora el compilador se enfrenta a la expresiónO $$'H' == 'H'$1;. El resultado depende del contexto, por ejemplo, 'H' = 'H'$1; es un error ('H' no es un Lvalue). in embargo, la sentencia que sigue se compila correctamente y produce la salida indicada. print±("Letra \"%c\"\n",

$$*ptr->str);

// -> Letra "I"

La explicación es que el compilador pasa a   el valor 'H'$1 (sin pretender ninguna otra asignación), lo que, tras una conversión de tipo, se traduce en el carácter 'I' que sigue 'H' en la lista ACII. Ë++ La expresión se traduce enO *((ptr$$)->str). i se utiliza la expresión que sigue, el resultado es el que se indica, pero cualquier posterior intento de utilizar ptr conduce a una catástrofe. print±("Letra \"%c\"\n",

*ptr$$->str);

// -> Letra "H"

La razón es que se envía a   el valor *ptr->str, que produce la salida indicada y después se produce el postincremento del puntero ptr, que queda apuntando a dios sabe donde, con lo que la utilización posterior seguramente producirá el fallo del sistema por "Error grave". O si str hubiese apuntado a una matriz de estructuras y la posición actual no fuese la última, el efecto hubiese sido simplemente dejar str apuntando a la siguiente estructura de la matriz. Ë++La expresión equivale a *($$ (ptr->str)). Nuevamente el resultado es correctoO ptr->str es un puntero  que señala al carácter 'H'; su incremento en 1 lo hace apuntar al segundo, por lo que si utilizamos la expresión que sigue se produce la salida indicadaO print±("Letra \"%c\"\n",

*$$ptr->str);

// -> Letra "o"

Ë++Esta expresión equivale a (*(ptr->str))$$. Es decir, 'H'$$; nuevamente el resultado depende del contexto. En la expresión que nos viene sirviendo para control, produce la salida señalada, porque   recibe como argumento un puntero a 'H' y el incremento se produce después. print±("Letra \"%c\"\n",

*ptr->str$$);

// -> Letra "H"

UNIDAD IV: UNIDADES. 4.1 SUBRUTINAS.

I El movimiento del programa se basa en la llamada a etiquetas y a subrutinas. Esto nos da capacidad para decidir, temporizar o retardar, operar y/o ejecutar algoritmos. Por eso debemos de tener en cuenta las técnicas más comunes en la programación de lenguaje ensamblador que nos permitirán hacer estas y muchas otras cosas. La mayoría de los microcontroladores incluyen en su repertorio de instrucciones algunas que permiten saltar a una rutina y, cuando se completa su ejecución, retornar al programa principal. El empleo de subrutinas aporta muchas ventajas entre las que se destacan las siguientes: -

Se pueden escribir como subrutinas secciones de código y ser empleadas varias veces en el mismo programa. Dan a los programas un carácter modular, es decir, se pueden codificar diferentes módulos para utilizarlos en cualquier programa. Se reduce notablemente el tiempo de programación y la detección de errores, utilizando repetidamente una subrutina. El código es más fácil de interpretar, dado que las instrucciones de las subrutinas no aparecen en el programa principal, sólo figuran las llamadas (CALL).

c   (|cc"m*% mE&!   La instrucción CALL (llamada a subrutina) consigue que la ejecución del programa continúe en la dirección donde se encuentra la subrutina a la que hace referencia. Es similar a GOTO pero coloca en la pila la dirección de la siguiente instrucción que se debe ejecutar después de terminar con la subrutina. La subrutina finaliza con la instrucción RETURN (retorno de la subrutina) que retoma la dirección guardada en la pila y la coloca en el contador del programa PC continuando el flujo de control con la instrucción que sigue a CALL. En la familia PIC de gama media la pila tiene ocho niveles de memoria del tipo LIFO (Last In, First Out) (último en entrar, primero en salir). Si se produce la llamada a una subrutina durante la ejecución de otra subrutina, la dirección de retorno de esta segunda es colocada en la cima de la pila sobre la dirección anterior. Esta segunda dirección es la primera en salir de la pila mediante la instrucción RETURN. Con la pila de ocho niveles, una subrutina puede llamar a otra y ésta, a su vez, llamar a otra hasta un máximo de ocho. Todo esto ya lo vimos anteriormente.

4.2 UNIDADES Y/O LIBRERIAS (CON EJEMPLO)

V                                                                        i i i i i i i i i

                          

!   "  #$   % i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i

m!&'(    (     (  m!&'(    (     (  m!&'(     m!&'(     m!&'(        (       (       ()  m!&'(     (   *&+  ,   m!&'(    (    -+ -    m!&'(    (   m!&'(      (  .    (    (  .     (   +    m!&'(      (   +     (    (   +     m!&'(      (  .      (  .    (    (  .   m!&'(    (  (   m!&'(       m!&'(        ( m!&'(     m!&'(          (  (     m!&'(            m!&'(   -+    (  -+ - -+   m!&'(   -+ )     (  -+ - -+   m!&'(    /m!&'(            m!&'(     ) m!&'(      m!&'(    + (     m!&'(      + (     m!&'(     m!&'(     m!&'(  

i

      (

    0 #$  % i i i i i i i i i i i

              )        1  

2 m  #$  % i i i i i i i i i i i i i i

 (     (      (      (                  (     (    -+     -+      (     -+    (    (  /  

3   m  #$  % i i i i i i i i i i i i i i i i i i i i i i

1  1 1 1  1 1 41  1   1  1 11  1  561  )1   1 1  1  1  11 11 (  1 (  1 

7  m  #$  %

i i i i i i i i i i i i i i i i i i i i i i i

    (      (      (      (  ((        (  ((            (  ((                     (  -+   -+ -   (  -+ -   (    ( -+ -     (           1      1   (        (  (    (    (      (/     (  -+  -+ -  (     (/      (        (  -+  -+ -  (    (     (         +         +       

   #$   % i

     1 

8 9  :#$  % i i

  +    +   

2 #$  % i

  (     (    

   0m  #$  % i i i i i i i i i

 /+  /   +   +  (     +  4  +  5 + /    (   (     + (   (    + (     (    + (     (      + (  -+    ( -+  1    (      ( 

4.3 ENCABEZADO (CON EJEMPLO)

‘ ‘  !"#$

  ‘                       ‘       ÷ Ô      c      ÷ à ‘            

%&' 

Ô 



% Ô 

V  ‘   V    VV  VV  VV  VV  VV  VV  VV  VV  VV  VV





















 VV    VV 

  VV   VV 

  VV 

  à                c               

à                 c               

|               c             Ê                  c            Ê                      c                    |       Ô         ‘         ÷                       

           à           ( (%) VV      

4.4 DECLARACION (CON EJEMPLO) ?     Antes de empezar a utilizar una función debemos  . La declaración de una función se conoce también como prototipo de la función. En el   de una función se tienen que especificar los parámetros de la función, así como el tipo de dato que devuelve. Los prototipos de las funciones que se utilizan en un programa se incluyen generalmente en la cabecera del programa y presentan la siguiente sintaxisO

En el prototipo de una función no se especifican las sentencias que forman parte de la misma, sino sus características. Por ejemploO

En este caso se declara la función i  que recibe como parámetro una variable de tipo entero ( ) y devuelve un valor del mismo tipo. En ningún momento estamos especificando qué se va a hacer con la variable  , sólo declaramos las características de la función i . Cabe señalar que el nombre de los parámetros es opcional y se utiliza para mejorar la comprensión del código fuente. De esta manera, el prototipo de la función cubo podría expresarse de la siguiente maneraO

Los prototipos de las funciones son utilizados por el compilador para verificar que se accede a la función de la manera adecuada con respecto al número y tipo de parámetros, y al tipo de valor de retorno de la misma. Veamos algunos ejemplos de prototipos de funcionesO

Las funciones de biblioteca se declaran en lo que se conocen como     . (del inglés ð , cabeceras). Cuando deseamos

utilizar alguna de las funciones de biblioteca, debemos especificar el fichero .h en que se encuentra declarada la función, al inicio de nuestro programa. Por ejemplo, si deseamos utilizar la función ï  en nuestro programa, debemos incluir el fichero stdio.h que contiene el prototipo de esta función. 4.5 CUERPO (CON EJEMPLO)

(    También se le llama !1   , y es junto con la cabecera, la única sección obligatoria en un programa Pascal. Debe comenzar y finalizar con las palabras reservadas!  y  respectivamente. $" 

Después de la palabra , siempre tiene que ir un  que indica el final del programa. Entre begin y end se escriben una o más sentencias, ya sean simples o compuestas. Las sentencias pueden ser varias:   ,   a procedimientos y funciones, sentencias   (sentencias if), sentencias   (sentencias for, while). Veamos un pequeño ejemplo:

&&&   i := 0; while i†10 do begin writeln('El valor de i es ',i); i := i $ 1 end

&

&&& El ejemplo es muy sencillo. Se trata de un bucle que escribe en pantalla lineas que consisten en la frase "El valor de i es" seguidas del valor que tiene en ese momento la variable i (0..9).

4.6 CREACION (CON EJEMPLO)

V      de la programaciónO

!! Nunca está terminado del todo ¡¡

Ü1   V     ð  ï      ï   ð iï  ii  ð    . Bjarne troustrupO "ProgrammingO Principles and Practice Using C++". Escribir un programa es establecer el comportamiento de una máquina mediante una serie de algoritmos que definirán su funcionamiento . En el estado actual de la ciencia, este algoritmo se plasma por escrito utilizando un lenguaje artificial comprensible por el humano-programador. Generalmente estas instrucciones, que aquí se denominan   , vienen acompañadas de algunos datos en forma de texto o imágenes, contenidas en uno o varios ficheros denominados ficheros de recursos ("resources"). in embargo, las instrucciones y recursos solo pueden ser utilizadas por la máquina después de un proceso de traducción que es realizado por la propia máquina (puede ser distinta de la que ejecuta el programa). El proceso exige que el código fuente sea transformado en una nueva secuencia de instrucciones según un nuevo sistema de codificación (el  !" ), y que los recursos adopten una disposición particular. Este conjunto de instrucciones y datos, que constituyen el denominado  , corresponden a acciones concretas y datos, que pueden ser entendidas, ejecutadas y utilizados por la máquina. En general este comportamiento pretende modelar o mimetizar el comportamiento de una entidad del mundo real, o de una abstracción que hemos imaginado; y es de tipo genérico. e pretende que la máquina se comporte como una función que acepta un conjunto de condiciones de entrada y devuelve como salida un comportamiento concreto y predecible para cada combinación de las condiciones de entrada.

Ü V  Hay bastante literatura sobre programación en general; a los académicos les gusta hablar de "Teoría de la Programación", y mucha gente se ha dedicado a especular sobre el tema. Incluso hay modas al respecto [4]. Es posible confeccionar una lista de las características que "debe" y "no debe" tener un buen programa (incluyendo la del Jefe, que solo tiene dos puntosO "Que esté para ayer; que salga barato"). El propio troustrup ( TC++PL) compara las condiciones para escribir un buen programa con las de escribir buena prosa. egún él, existen dos respuestasO "aber que se quiere decir" y "Práctica. Imitar buenos escritores". Más adelante nos recuerda que aprender a manejar bien un lenguaje puede constar tanto tiempo y esfuerzo como aprender a expresarse en un lenguaje natural o tocar un instrumento. Por supuesto sería un atrevimiento por mi parte contradecir tan docta opinión, pero puestos a filosofar me gustaría puntualizar que el verdadero problema está en el segundo punto de la segunda respuesta; la primera, aunque ciertamente importante, me parece la verdad de Perogrullo . iempre me ha parecido que programar (programar bien) tiene mucho de arte. Me parece que debe ocurrir como con la música; seguramente muchos pueden decir que debe tener una buena ejecución de violín, pero imitar a Paganini debe ser harina de otro costal. eguramente los

profesores de armonía saben que debe tener y no tener una buena sinfonía, pero otra cosa debe ser imitar a Mozart. Bajando a la tierra; tampoco se trata aquí de hacer "Paganinis de la programación C++" (ya me gustaría para mí); el mensaje que quisiera transmitir es dobleO El contenido en un viejo Refrán EspañolO "La Universidad no presta lo que la naturaleza no da". Como suena un poco duro, añadiré un consuelo para los que somos menos dotados; un proverbio que leí hace tiempo, en línea con la respuesta de troustrupO "Por el dinero del trabajo los Dioses lo venden todo". A continuación se comentan brevemente los pasos imprescindibles en la creación de un programa C++. Vaya por delante, que las anotaciones de los puntos Ü, Ü y Ü son opinión del que suscribe basados en la propia experiencia, por tanto totalmente subjetivos y opinables.

Ü#. "à ï   ð  ði    ð         ð        ïi   ð ð    ð     ð

 ð ïi     ð ð   ð  ð   ð

 ïï ïi i   ð   ðð  ði  ï ð   ð   ïð ð   i     i ð     ð          ð   i     i ði    ï  i      i i". Joel on oftware "et Your Priorities"

www.joelonsoftware.com

" i ð ïï   ðiï   ii ð  ð   i  iïï   ï   ð     ð   ð     ii    i  ðï    ð    ðï    ïï iï iïi  i      ð i   ðï  ð  ð     !ð  ï ð  

     ". Robert Bogue (Jupitermedia Corp) en "Breaking Down oftware Development Roles". " ï     ð ð ðïi  ï        ". Bjarne troustrupO "ProgrammingO Principles and Practice Using C++".

Esta es la típica obviedad que a veces se pasa por alto. Hemos dicho que escribir un programa es establecer el comportamiento de una máquina; parece lo más natural del mundo enterarse primero de cual es ese comportamiento. Tener una imagen mental lo más clara posible de las características de lo que pretendemos modelar. Esta cuestión es lo que los teóricos denominan el "espacio" del problema, "'What' domain" en la literatura inglesa. A esta fase se la suele denominar !  , y mi consejo particular es que después de una primera toma de contacto, el segundo paso sea definir de la forma más detallada posible el principio y el final del problema. Es decirO cual es la información de partida (incluyendo su formato y en que

soporte se recibe) y cual es la información final y en que soporte se proporcionará; no es lo mismo mostrar una imagen que componer una factura o disparar un proceso si un sensor analógico-digital nos suministra una determinada señal (por citar algún ejemplo). Normalmente en ambas cuestiones tiene mucho que decir el cliente [2], es lo que se llama    ; el resto (lo que hay entre los datos de entrada y la salida), debe rellenarlo el programador. Generalmente si se tienen bien definidos ambos extremos, se tiene resuelta la mitad del problema; cuando se tengan diseñados los ficheros se tendrán dos terceras partes -ver a continuación-. Este sistema tiene además la ventaja de poner inmediatamente de manifiesto las indefiniciones de partida; a veces los clientes no saben exactamente qué desean y hay que ayudarles a centrar el problema. Dentro de esta fase tiene especialísima importancia el tema de $ ; esto se refiere al orden de magnitudes que se manejarán. ¿De que rango serán las magnitudes numéricas? ¿Podrán adoptar valores negativos? ¿Hay información alfanumérica? ¿Como son de largas estas cadenas?. Especialmente si el programa implica diseño de archivos (como es casi seguro), ¿Cual podrá llegar a ser su tamaño dentro de la vida del programa?. i se manejan ficheros u objetos binarios, ¿Como son de grandes? ¿Que concepto tiene el cliente de los que sería "rápido" o "lento"? (¿milisegundos, minutos, horas?). En esta fase sea especialmente precavido y no se crea a pié juntillas todo lo que le digan (intente hacer de abogado del diablo). Como postre, diseñe las líneas maestras de una estrategia de recuperación de errores de ejecución, incluyendo que hará con los no recuperables (errores fatales). Piense por ejemplo que si algún día lo llaman para ver "que ha pasado", quizás le interese disponer de un volcado de texto ACII en el disco con una descripción del estatus del programa como parte de las funciones de salida ( 1.5). Hoy día, cuando se empieza a hablar de frigoríficos que avisarán de que faltan provisiones o de lavadoras que avisarán al técnico si se estropean, no estaría de más que sus programas estuviesen a la altura de las circunstancias.

Ü? %   i el programa debe utilizar ficheros que no vengan impuestos (ya existentes), y suponiendo que todo lo anterior esté suficientemente claro, este es el momento de hacerlo. Ponga por escrito la especificación de tales ficheros, incluyendo el nombre que dará a las variables y, en su caso, el que tendrán en el disco o almacenamiento externo. Esto puede concretarse quizás a la definición de algunas estructuras ( que se pasó por alto.

4.5). En esta fase es posible que tenga que repreguntar alguna cosa

Teniendo ya una imagen más o menos clara de lo que hará su programa, si éste es mediano o grande, es posible que todavía tenga que realizar una labor previa antes de ponerse a escribir el códigoO diseñar a grandes rasgos cuales serán los   del programa; módulos que se corresponderán aproximadamente con la distribución del código en ficheros fuente independientes. Quizás tenga que decidir también si algunas partes aparecerán como  $ [1]. Recuerde lo indicado al respecto al tratar de los ubespacios de Nombres (

4.1.11).

Esta fase es especialmente importante en el caso de programas muy grandes, cuyo desarrollo se reparte entre varios programadores que se encargan de uno o varios de estos módulos. En estos casos, el análisis, la especificación, la subdivisión en partes (con sus especificaciones particulares),

y la asignación de estas como tareas a los programadores, lo habrá realizado el jefe de programación y desarrollo.

Ü       uponiendo cumplimentados los pasos anteriores, el programador está en condiciones de construir una imagen mental clara de como será esa conexión entre la información de entrada y la salida, es lo que se denomina "espacio" de la solución ("'How' domain"); su forma concreta es justamente el   del programa que se pretende. La codificación consiste justamente trasportar a papel (en el lenguaje de programación elegido) la imagen mental de esa conexión. Para escribir el código fuente de un programa C++ solo se puede utilizar un subconjunto de 96 caracteres del juego total de caracteres U-ACII (

2.2.1a). on los siguientes [8]O

&      O abcdef ghij klmnopqrstuv wxyz ABCDEFGHIJKLMNOPQRTUVW XYZ 0123456789 _ { } [ ] # ( ) % O ; . ? * + / ^ & | ~ ! = , \ " ¶ #     denominados separadores Espacio horizontal; Tabulación horizontal (TAB); Tabulación vertical (VT); alto de forma (FF); Nueva línea (NL). O Para escribir el código solo hace falta un   de texto plano, aunque las modernas "suites" de programación incluyen editores específicos que están conectados con el depurador, el compilador el enlazador (ver más adelante) e incluso el sistema de ayudas, de forma que, por ejemplo, pueden mostrarnos automáticamente la sentencia en la que se ha producido un error de compilación, o la página correspondiente del manual si pulsamos en una palabra reservada y pedimos ayuda (F1 generalmente). También muestran en diversos colores las palabras clave, los comentarios, Etc. Los más avanzados disponen incluso de opciones que podríamos calificar de "inteligentes", en el sentido que pueden prever cual será nuestro próximo movimiento en función de la sentencia que estamos escribiendo (por ejemplo, ofrecernos una lista de las propiedades y métodos de una clase si nos estamos refiriendo a ella).

Durante la fase de escritura no desdeñe dos puntosO

4

4

Incluir la mayor cantidad de   y    posibles. Cuando se está muy "metido" en el programa todo parece evidente, pero piense que tiene que retocarlo dentro de unos años, quizás entonces le parezca "Chino" y agradecerá haber dejado la mayor cantidad de documentación y aclaraciones al respecto. Incluso si es seguro que no volverá a verlo, piense en el sufrido programador que le seguirá si tiene que habérselas con su código. En este sentido C++ no es precisamente COBOL, aunque afortunadamente permite incluir en el fuente comentarios todo lo extensos que se desee ( 3.1). No caiga tampoco en el error de pensar que esa información ya está en la documentación escrita que le han obligado a entregar junto con los fuentes; posiblemente dentro de unos años Usted mismo no encuentre esos documentos. Incluir la mayor cantidad posible de rutinas y condiciones de  . Piense que el operador es un "manazas" o que los datos pueden venir con alguna corrupción, error de transmisión, etc. Verifique constantemente que las condiciones son las esperadas (

1.4.5).

Una vez que se tiene el    (en uno o varios módulos), el proceso de traducirlo a instrucciones comprensibles por el procesador ( !" ) puede hacerse siguiendo dos modelosO los ' y los   [3]. En el caso de lenguajes compilados como C++, el fichero de texto plano (ACII 2.2.1a) que contiene el fuente del programador (con la terminación .# ó .#VV), es sometido a un proceso de varias fases que terminan en la obtención del ejecutable. De forma genérica, todo este proceso se denomina "compilación", aunque es una generalización un tanto incorrecta, ya que la compilación propiamente dicha es solo una de las etapas intermedias. ería más correcto decir "construcción" del ejecutable, aunque por la extensión y generalización de su uso seguiremos utilizando el término genérico "compilación" para referirnos a él. Los procesos de construcción del ejecutable se esquematizan en la figura que comentamos a continuaciónO

ÜV  En la primera fase de la compilación; un programa especial, denominado

(, es encargado de iniciar el proceso llamando a los diversos módulos que se encargan de la construcción del ejecutable (en 1.4.0 se amplían detalles sobre esta parte del proceso). El primero de estos módulos es el  . El preprocesador ( 1.4.1) estudia el texto buscando      ( 4.9.10), por ejemplo sentencias que pueden ser suprimidas, incluye los ficheros correspondientes a las directivas )   , sustituye los ) , elimina los comentarios y expande las macros encontradas en el fuente y en los propios ficheros incluidos. El resultado obtenido es lo que se denomina      (

1.4.2).

Ü*!   !   Puesto que el fichero fuente está escrito en un "lenguaje" (C++ en este caso) que tiene sus propias reglas de sintaxis (como los lenguajes naturales), el compilador debe comprobar que estas reglas se han respetado. Este análisis ("Parsing") es realizado por el analizador sintáctico [10]. En esta fase se realizan comprobaciones como que los paréntesis están cerrados, que no aparecen expresiones incompletas, etc. Para realizar esta labor, el "parser" debe identificar los tokens (

3.2), de forma que el fuente es tokenizado, esto es, reducido a tokens y separadores.

El fuente es escaneado, el analizador sintáctico (parser) extrae los tokens, seleccionando el que coincida con la secuencia de caracteres más larga posible dentro de la secuencia analizada [9]. Por ejemplo, la palabra clave   es reconocida como un solo token (identificador de clase de almacenamiento) en vez de seleccionar   (una palabra reservada) y  (que sería un identificador). Los  (whitespaces) es el nombre genérico dado a los espacios (32), tabulaciones verticales VT (11), horizontales TAB (9) nueva linea NL (10) y retorno de carro CR (13). Los separadores sirven para indicar donde empiezan y terminan las palabras, pero después de esto cualquier separador redundante es descartado. Por ejemplo, las dos secuenciasO int i; ±loat ±; int i; ±loat ±; son léxicamente equivalentes y el resultado del análisis son las seis palabras siguientesO int i ; ±loat ± ; El carácter ACII espacio puede formar parte de cadenas literales (alfanuméricas), en cuyo caso es protegido del proceso de análisis, permaneciendo como parte de la cadena. Por ejemploO

char name[] = "Playa Victoria"; es reducido a siete tokens, incluyendo una cadena literal "Playa Victoria" char name [ ] = "Playa Victoria" ;

Ü*!  !  En lenguajes como el   la comprobación se limita al análisis anteriormente señalado; con esto se garantiza que el fuente original es correcto (sintácticamente), es decir, es un escrito correcto desde el punto de vista del lenguaje, otra cosa es que tenga un sentido computacional correcto, o diga tonterías, incongruencias o sinsentidos [6]. Por supuesto la meta del compilador es conseguir descubrir con anticipación (al runtime) el máximo de errores posibles. En los lenguajes de alto nivel, esto se consigue con una cierta comprobación del "sentido" o "significado" del escrito, es el denominado !  !  (análisis del significado). La mejor baza de que dispone C++ para esta segunda comprobación es la comprobación estática de tipos ( 2.2). Es decir, que las variables y las operaciones entre ellas se usan correctamente; esto supone verificar que las llamadas a funciones, los valores devueltos por estas y los operandos de las expresiones corresponden con el tipo que se les supone en cada caso. Por ejemploO int x; char ±unc(); .... x = ±unc(); En este caso, la primera línea declara que la variable x es tipo  (entero); la segunda declara que la función fun devuelve un carácter ( ); si una líneas más adelante se pretende igualar la variable x con el valor devuelto por la función, el analizador semántico estaría en condiciones de asegurar que existe una incongruencia en las pretensiones del programador, generando el correspondiente mensaje de advertencia o error

.

Ü+   Todos estos tokens identificados por el analizador sintáctico, son organizados en una estructura como las hojas de un árbol. A continuación, el generador de código recorre este árbol traduciendo sus hojas directamente en código de la máquina para la que se compila [11].

i se solicita, el compilador también puede en esta fase generar un fichero en lenguaje macro ensamblador para su posible inspección por el programador (este código es también dependiente de la máquina para la que se compila y fácilmente entendible por el humano; puede contener incluso comentarios para facilitar su lectura). O Los compiladores modernos suelen incluir opciones que permiten generar código optimizado para el tipo de procesador que se utilizará. Por ejemplo, el compilador Borland C++ dispone de opciones que permiten generar código optimizado para procesadores Intel de modelos específicos ( 1.4.3a). Como cabría esperar, el compilador GNU c++ es el que ofrece más posibilidades en este sentido, que incluyen el tipo de procesador dentro de una larga lista de fabricantes, y dentro de estos diferentes modelos. En concreto, para la familias Intel i386 y x86-64, permite elegir entre 20 posibilidades diferentes!!.

A veces, después del generador de código puede ejecutarse un optimizador (peephole optmizer). Este generador de código sería propiamente el  , es decir, el encargado de traducir algo entendible por el humano en código máquina. En cualquier caso, el resultado es un fichero "objeto", generalmente con la terminación . o .. También puede ordenarse al compilador que incluya en el "objeto", determinada información adicional que será utilizada más tarde por el   , por ejemplo los números de línea de las sentencias. Cuando se hace así, se habla de una compilación "provisional" o de "depuración"; distinta de la que se realiza para la versión definitiva (de campo) del programa en la que no se incluyen este tipo de información que ya no es necesaria.

Ü10 , El último paso en construir un ejecutable es el ,. Recibe este nombre el proceso de aglutinar todos los recursos en un solo fichero ejecutable ( 1.4.4). Estos recursos son desde luego los ficheros-objeto obtenidos en la compilación de los diversos módulos (ficheros . ) que componen el programa. Además, si se han utilizado funciones o clases de librería [1] (como es casi seguro), el , ("Linker") es el programa encargado de incluir los módulos adecuados en el fichero ejecutable final. Así pues, la función primordial del enlazador es resolver todas las referencias que puedan existir en el programa, es decirO que cada invocación a un valor o a una función corresponda una dirección donde se encuentra el recurso correspondiente, y que estén todos contenidos en un solo fichero que pueda ser cargado y ejecutado por el istema Operativo. Eventualmente algunos recursos pueden estar en otros ficheros distintos del ejecutable,  $ , !  (en Windows se denominan DLLs). En cuyo caso el enlazador también incluirá las direcciones y convenciones de llamada adecuadas para que puedan ser traídos a ejecución desde el programa principal. Por último, el enlazador se encarga de insertar en el ejecutable un trozo de código especialO el    , que es el encargado de iniciar la ejecución (

1.5).

Hay que tener en cuenta que generalmente el enlazador puede producir diversos tipos de resultadosO

Ü10.1-    e trata de una versión en la que dentro del propio ejecutable, se incluye información adicional no estrictamente necesaria para la ejecución sino para la depuración (por ejemplo los números de línea del código fuente que corresponde a cada sentencia). Estos ejecutables permiten la ejecución en un modo especial, en la que por ejemplo, pueden ejecutarse las sentencias paso a paso, o que el programa se detenga al llegar a diversos puntos establecidos de antemano; ver el contenido de las variables, el estado de la pila y otros aspectos internos muy útiles cuando se intentan depurar errores de tiempo de ejecución. Esto se consigue porque el programa corre bajo control de otro programa que actúa de controlador de la ejecución, es el   ("Debugger"). O El depurador puede ser en realidad un módulo adicional al de inicio, inserto en el ejecutable, que se inicia antes que la propia función   ( 4.4.4), de forma que puede controlar la ejecución. Por esta razón entre otras, las versiones de depuración son mayores (en tamaño del fichero) que las definitivas o "de campo" [12].

Ü10. -     Es la versión definitiva que saldrá al público (se entregará al usuario). e distingue de las versiones internas en que no incluye información para depuración. Es buena práctica incluir en cada versión publicada información sobre el número de versión del programa y de compilación (esto suele venir indicado en la siguiente formaO Versión ..,, build ). Generalmente los programas sufren muchas modificaciones a lo largo de su vida (corrección de errores, perfeccionamientos, versiones para diversas plataformas, etc), y es preciso identificarlos. Es costumbre hablar de "versiones", que se identifican por grupos de números separados por puntos. Por ejemploO -  ..,,. Cada fabricante de software, grupo de trabajo o programador, utiliza una convención, estableciéndose que tipo de cambios dan lugar a diferencias de versión en el grupo de cifras ; en el  o en el ,,. Generalmente se acepta que los cambios de mayor nivel ( ) representan versiones totalmente nuevas del programa; que requieren incluso rescribir los manuales de uso. Los cambios menores corresponden a modificaciones en el grupo  (por ejemplo utilizar otras versiones de las librerías o distinto compilador); finalmente los cambios de detalle representan modificaciones en el grupo ,,. Viene a representar cambios mínimos, que no merecen una alteración del último grupo de cifras [7], pero cambios al fin y al cabo (cuando se recompila es porque algo ha cambiado, aunque sea un comentario en el fuente). Es también costumbre incluir un último identificadorO El número de compilación o construcción ("build" en la literatura inglesa); es un número progresivamente creciente para cada compilación distinta. A título de ejemplo, en la página adjunta se muestra la clasificación utilizada para las sucesiones versiones de los productos de un conocido fabricante (

Designación de versiones).

Ü10.. $ En las páginas siguientes veremos que como resultado de la "compilación", no siempre se desea conseguir un ejecutable; al menos no en el sentido tradicional del término, sino una  $ (de las que existen varios tipos), o un fichero .

En lo que respecta al lenguaje C++, existen dos tipos fundamentalesO !  y ? ! . Las primeras son colecciones de ficheros precompilados, cuyo código puede ser añadido a un ejecutable en el proceso de enlazado (los ficheros de la Librería Estándar 5 que acompañan a los compiladores C++ son de este tipo). Las segundas son auténticos ejecutables externos que son invocados desde otro ejecutable y devuelven el control a este cuando terminan su ejecución. Más detalles al respecto enO (

Ü11 

1.4.4a).

-   (rescribir el código)

La verdadera prueba de fuego del programador se presenta cuando lanza la orden de compilar y enlazar su programa. Todos los módulos involucrados en los pasos anteriores, compilador, analizador sintáctico y enlazador pueden detectar errores en nuestro código y mostrar los mensajes correspondientes.

Ü11.1/  En cuanto al momento en que se producen, son básicamente de tres tiposO 4

4

4

De     . e engloban aquí los errores detectados por preprocesador, el analizador sintáctico y el propio compilador. Los hay meramente sintácticos, por ejemplo un paréntesis no cerrado; también de tipo lógico, por ejemplo la referencia a una variable no declarada previamente, etc. etc. De  ,. on detectados por el enlazador. Por ejemplo una llamada a función cuya definición no aparece por ninguna parte (el enlazador no es capaz de encontrarla en los directorios que tiene asignados como "normales" para buscar); también la inversaO dos funciones del mismo nombre situadas en dos módulos (fuentes) distintos (la referencia aparece duplicada). De    (runtime). Existe finalmente una última clase de erroresO los que se producen cuando se ejecuta el programa; son precisamente los más difíciles de diagnosticar y verificar, sobre todo en aplicaciones grandes (los relativos a "pérdidas misteriosas" de memoria y punteros descontrolados son especialmente temibles).

Ü11. + Los errores producidos durante la compilación son de dos tipos, según su gravedadO 4 4

 ("Errors")O on errores graves, el proceso no puede continuar y es detenido después de mostrar la información pertinente. *  ("Warnings")O No son errores graves pero si circunstancias sospechosas o inusuales de las que el compilador entiende que merecen una advertencia por si es algo que se nos ha escapado inadvertidamente (por ejemploO Una variable declarada que no se utiliza para nada más). En estos casos, el proceso continua y si no hay errores graves se construye un ejecutable.

En todos los casos el aviso incluye indicación del fichero ("fuente" .C/.CPP), el número de línea, y el nombre de la función donde se produce el error, así como una explicación más o menos clara de su motivo. En principio pueden ser cuestiones banales, como haber olvidado poner un punto y

coma s al final de una sentencia (muy corriente en los que estamos acostumbrados a programar en otros lenguajes). En otros casos los mensajes son especialmente crípticos, sobre todo para el profano, pero poco a poco los entendemos mejor y podemos aprender mucho de ellos si prestamos la debida atención y entendemos su "porqué". Recordar que todos los compiladores disponen de opciones para modificar el número y tipo de los  y   ("Warnings") que aparecen. Respecto a los primeros, puede instruirse al compilador para que suspenda la actividad al aparecer el primer error, o que continúe hasta que aparezca un número determinado de ellos. Respecto a los avisos, puede ordenarse que no muestre ninguno, o que sea más o menos benevolente en determinados aspectos. Por ejemplo, puede indicarse que la comprobación siga estrictamente el estándar C++ y que avise de cualquier desviación al respecto (los compiladores suelen permitir ciertas "peculiaridades" que no son estándar). O La descripción e información acerca del error o advertencia, dependen de la plataforma, pero hemos de señalar que existen notables diferencias en cuanto al grado de desarrollo de los diversos compiladores, en especial respecto a los "Warnings". Por ejemplo, en este sentido el Compilador Borland C++ 5.5 es mucho menos riguroso que el producto homólogo de Microsoft, cuyo sistema de verificación es con mucho superior al del primero, de forma que no es infrecuente que advertencias más o menos serias e incluso algunos errores advertidos por Visual C++ 6.0 sean totalmente ignorados por Builder. A su vez los errores y advertencias señalados por el compilador GNU Cpp suelen ser más explicativos que los señalados por Borland o Visual (que en este sentido son más crípticos).

Ü11.+     Respecto a los    , es importante hacer una advertencia al neófitoO Con frecuencia el compilador nos informa de error en una línea más abajo de donde está verdaderamente. Por ejemplo, olvidar un punto y coma de final de sentencia puede dar lugar a que el compilador nos informe de un error incomprensible dos o tres línea más abajo. Cuando se realizan modificaciones en fuentes grandes y no se tiene mucha práctica, es preferible realizar cambios pequeños y compilar sistemáticamente después de cada uno. Así sabremos que el error corresponde a lo último que hemos tocado. Hay veces en que quitar una simple coma en una sentencia produce una listado de 15 o 20 errores en líneas siguientes. !úbitamente nada tiene sentido para el compilador !!. [5] En las asignaciones del tipoO Lvalue = Rvalue; en las que intentamos asignar un valor   (

2.1 que puede ser el resultado de una

expresión) a un .  ( 2.1), son muy frecuentes los errores en que el compilador produce un mensaje del siguiente aspectoO Error .... Cannot convert 'xxxxx' to 'yyyyy' in ±unction .... Lo importante a reseñar aquí, es que las expresiones xxxxx e yyyyy informan sobre el   de objeto que hay en cada lado de la expresión de asignación.

O En el capítulo dedicado a los tipos de datos ( compilador clasifica los objetos según su tipo.

2.2) se describe detalladamente como el

En las asignaciones, el Lvalue debe recibir un valor de su mismo tipo. i el tipo del Rvalue no concuerda con él, el compilador puede intentar adecuarlo, pero si esto no es posible, se produce un error como el señalado. En él se nos indica que el tipo xxxxx, que corresponde al Rvalue (el resultado de la expresión a la derecha del operador = ), no puede ser convertido al tipo yyyyy del Lvalue. Hay que advertir que las expresiones xxxxx e yyyyy están codificadas. Cada compilador utiliza un algoritmo interno para designar cada uno de los innumerables tipos que puede existir en C++. En concreto, la designación utilizada en estos mensajes es la misma que utiliza en el operador   ( 4.9.14). En situaciones difíciles, es mucha la información que puede obtenerse de estas expresiones si se observan detenidamente.

Aunque la comprobación estática de tipos, y del cumplimiento de las reglas sintácticas realizada por el compilador, resultan muy eficientes en lo que respecta a la detección de errores, en realidad, el trabajo dista de ser completo y suficiente. Existen multitud de circunstancias potencialmente erróneas que son pasadas por alto. En especial las relacionadas con pérdidas de memoria; existencia de punteros descolgados; bucles infinitos; objetos declarados pero no utilizados, y un largo etcétera. Algunos de estos errores pueden permanecer agazapados en el código y solo aparecer en circunstancias muy especiales, incluso después de que la aplicación haya sido rodada largo tiempo sin contratiempos. Muchas de estas circunstancias pueden evitarse, o al menos mitigarse, siguiendo ciertas pautas y recomendaciones "de buena práctica", muchas de las cuales están contenidas en la obra TC++PL de troustrup; la mayoría en forma de advertencias sobre cosas que "no" debe hacerse. in embargo, el problema persiste, máxime en un lenguaje como C++ plagados de peligros potenciales que acechan en el arcén, y con el que es posible "volarse la pierna completa". Para reforzar la calidad del código y prevenir errores posteriores (de run-time), se han creado multitud de herramientas. Entre las más conocidas se encuentran las siguientesO 4

. , denominadas así en atención a que tienen su origen en una utilidad de este nombre (lint) desarrollada inicialmente en el entorno Unix. Estas utilidades se ejecutan sobre el fuente sin compilar (no confundirlas con los depuradores "debugger" -de run-time-, aunque también sirven para "depurar" el código); comprueban la sintaxis y errores en los tipos de datos de forma más concienzuda y profunda que los compiladores C/C++, y avisan de gran cantidad de peligros potenciales; incorrecciones; desviaciones sobre las reglas universalmente aceptadas como de "buena práctica", etc. Actualmente han llegado a un elevado nivel de sofisticación, de forma que un buen .  puede evitarnos muchas horas de depuración. En realidad es una herramienta que no debería faltar en el taller del programador profesional.

4

. Esta utilidad, originaria del O AIX, reformatea el código fuente contenido en un fichero y lo vuelca sobre el dispositivo estándar de salida (  5.3) utilizando un formateo basado en sangrados y espaciados, que ayudan a interpretar la estructura del código.

4

0. Esta utilidad, originaria del O AIX, analiza el contenido de un fichero objeto C/C++ y proporciona en la salida estándar ( ) un gráfico de sus referencias externas.

4

. Esta utilidad, análoga a las anteriores, analiza los fuentes C/C++ y genera una tabla con todos los símbolos encontrados en cada fichero, incluyendo los nombres de los parámetros formales de las funciones (contenidos en la definición de la función). La tabla es mostrada en el dispositivo estándar de salida ( ), e incluye el sitio en que cada referencia se ha resuelto (suponiendo que la definición esté en el código analizado).

i está interesado en las características y posibilidades de estos productos, la mayoría comerciales y algunos muy costosos, aparte de la correspondiente búsqueda en Google, existe un interesante artículo de cott Meyers (uno de los "Gurus" del C++) y Martin Klaus titulado "A First Look at C++ Program Analyzers", en el que se repasan las cualidades y características de distintos paquetes, incluyendo una evaluación de su comportamiento frente a lo que el autor considera deseable. Aparecido en el número de Febrero de 1997 del Dr. Dobb's Journal, existe una versión de prepublicación accesible on-line, que es incluso más completa que el artículo publicado (probablemente debido a las exigencias de maquetación de la revista)O

www.aristeia.com.

Uno de los productos punteros y más antiguos, es el de Gimpel oftware www.gimpel.com; esta empresa dispone de dos versiones denominadas PC-Lint y FlexeLint. La primera para Windows, la segunda, más general, para cualquier entorno que soporte un compilador C, incluyendo Unix y Linux. i tiene interés en comprobar más de cerca el tipo de información que proporcionan estas utilidades, en el sitio de este fabricante existe una sección denominada Bug del mes ("Bug of the month") en la que se exponen ejemplos de código, junto con el resultado del análisis (después de pulsar un botón). Además de súmamente instructivos, los casos propuestos pueden servirle para auto-evaluar sus conocimientos de C++ al respecto. A mi entender también pueden constituir una magnífica fuente de inspiración para los enseñantes que busquen material para ejemplo o evaluación (sed piadosos en los exámenes porque algunos son realmente para niveles avanzados. No se puede pretender que después de un semestre de estudio, el alumno esté en condiciones de adivinar correctamente el "bug C/C++ del mes" O-)

Ü11.   Para los    se requieren estrategias especiales. En principio, durante la fase de comprobación inicial, se tienen las ofrecidas por el   . Prácticamente todos los entornos de desarrollo disponen de un depurador más o menos potente y sofisticado. Puede afirmarse que el depurador es otra herramienta que no debe faltar en el arsenal de cualquier programador profesional, en especial porque hay errores que son prácticamente imposibles de diagnosticar y corregir sin su ayuda. Como se ha indicado, el depurador incluye en el ejecutable un código especial que realiza las funciones de depuración deseadas, pero aparte de los que podríamos denominar estándar (cuyos módulos son incluidos en durante la fase de enlazado del ejecutable), existen herramientas específicas que analizan el ejecutable y son capaces de detectar determinados errores e inconsistencias. Estas herramientas realizan su trabajo durante la ejecución, para lo que modifican

el código a analizar incluyendo determinados módulos que les permiten controlar el desarrollo de la ejecución (se dice que "instrumentan" el código). La forma de realizar esta "instrumentación" depende de la herramientaO puede realizarse durante la compilación ("compile-time"), añadiendo código que no aparece en el fuente; durante el enlazado ("link-time"); durante la carga ("loadtime"), cuando el ejecutable es acomodado en memoria, o antes de la carga, sobre cualquier ejecutable listo para ser usado. Generalmente estas herramientas controlan la ejecución, toman nota de las incidencias, y finalmente proporcionan un informe de las mismas cuando la ejecución finaliza. O no existe una denominación unificada para este tipo de productos. Quizás el más conocido es es BoundsChecker, de Numega www.numega.com (actualmente aparece como Compuware). También puede intentar una búsqueda en Google bajo el epígrafe "Memory debugger".

Después de todas las medidas preventivas ya reseñadas, cuando finalmente, después de las pruebas de "laboratorio" damos por bueno el programa, este queda merced a si mismo; a la calidad de su propio mecanismo de defensa. Como errar es humano, los diseñadores del C++ pensaron que a pesar de la programación más cuidadosa, siempre pueden presentarse circunstancias excepcionales o imprevistas. Para poder hacerles frente, dotaron al lenguaje de opciones especiales con las que tratar este tipo de situaciones, de forma que pudiese seguir todo bajo control; estos recursos específicos se exponen con detalle en el capítulo dedicado al Tratamiento de Excepciones (

1.6).

Ü1    Ya hemos señalado que para construir un programa C++ basta un editor de texto plano y un compilador C++ para la máquina y istema en que deba ejecutarse, y que en el término "Compilador" incluimos todas las herramientas auxiliares, enlazador, librerías, etc. Por supuesto que en este sentido, las plataformas comerciales, en especial las versiones denominadas "Enterprise", ofrecen unas prestaciones inigualables, incluyendo potentes depuradores, diseño gráfico de elementos con capacidad de arrastrar y soltar ("dragg and drop") elementos, y conjuntos preconstruidos de clases que simplifican extraordinariamente la construcción de determinados aspectos de las aplicaciones. Por ejemplo, el manejo de bases de datos o comunicaciones. En esta categoría podemos incluir productos como C++Builder de Borland o Visual C++ de Microsoft para el entorno Windows. En la página dedicada a los Compiladores encontrará algunas referencias (

Compiladores).

i desea saber más sobre aspectos relacionados con la compilación, preproceso, análisis sintáctico y semántico, traducción del código, etc, mi consejo es que consulte "Compiladores y Procesadores de Lenguajes" [Jiménez-04] Inicio.

[1] En el argot de programación, "función de librería" se refiere a un recurso prefabricado; trozos de código, generalmente en forma de funciones o clases que otros han escrito, que incluimos en nuestro programa. La confección de programas se parece a la construcción de un edificio en el

que cada vez más se utilizan elementos preconstruidos (algunas veces normalizados), que facilitan y aceleran la construcción. uelen ser de dos clasesO      (lenguaje utilizado), que en caso del C++ están incluidas en la denominada . $ ! ( 5), y de  ; librerías especializadas en cuestiones muy concretas que pueden adquirirse para no tener que escribir por nosotros mismos rutinas que otros (que además saben mucho sobre el tema), se han encargado de escribir y comprobar. Por ejemploO librerías gráficas, de comunicaciones, estadísticas, para escribir códigos de barras en una impresora, Etc. Las modernas "suites" de programación C++ incluyen completísimas librerías en las que están resueltas la mayoría de las situaciones que habitualmente se suelen presentar en la programación normal. Precisamente el entorno C++Builder de Borland-Imprise es un claro ejemplo. El paquete estándar comprende un entorno gráfico de programación (1? ) para Windows, que incluye un potente conjunto de librerías en forma de "herramientas". Es un producto comercial con un precio determinado. En cambio, el compilador, el depurador y la Librería Estándar se suministran gratis. Es decir, se asume que el valor comercial está en el entorno gráfico integrado y en las librerías adicionales. [2] eguramente se me ocurre lo de "cliente" por deformación profesional; por supuesto el cliente podemos ser nosotros mismos, el jefe, el profesor de la asignatura, Etc. [3] Con objeto de mejorar la velocidad de ejecución (tradicionalmente lenta), algunos intérpretes, utilizan en realidad un modelo híbrido. Obtienen un seudo-ejecutable intermedio, mediante un preprocesado seguido de un "parsing", con lo que se obtiene un código "tokenizado" que es el que se entrega realmente al intérprete. [4] A la hora de redactar estas líneas parece estar muy de moda una técnica denominada Programación Extrema (eXtreme programming), cuya filosofía se basa en 12 principios o mandamientos, alguno tan pintoresco como el de las "40 horas semanales", según el cuál la mejor manera de aumentar el rendimiento es que los programadores "solo" trabajen 40 horas a la semana, pues está científicamente demostrado que un trabajador fresco produce código de mejor calidad que uno cansado. A mí particularmente, este tipo de consejos me recuerdan el de los libros de instrucciones americanos para el microondasO "No se aconseja utilizarlo para secar a su mascota" O-)) [5] Como consecuencia, después de algunos años de oficio, los programadores suelen (solemos) ser gente un poco "tocada de la azotea". No cabe duda que pasar años viviendo en un mundo donde no da igual un punto que una coma en un millón de líneas de código termina imprimiendo carácter. El resultado es que el resto de la gente "normal" no entiende muy bien porqué somos tan maniáticos y puntillosos en algunos asuntos, ya que afortunadamente (¿?), el mundo real suele ser de lógica más "borrosa" (a veces, tan borrosa que apenas se ve nada...). NotaO Esto de la lógica "Borrosa" viene a cuento y recuerdo de un amigo. Una persona de un gran talento natural que no ha tenido ocasión de recibir formación académica (es mecánico y apenas ha ido a la escuela). En cierta ocasión delante de unas cervezas intenté explicarle las diferencias entre la lógica binaria y la difusa ("Fuzzy logic"). Días después conversaba él con otras personas y me sorprendió como introducía el concepto de la lógica difusa con total oportunidad y como si fuese una cosa sabida de toda la vida. olo había cambiado una palabra; "borrosa" en lugar de difusa.

[6] Las circunstancias son exactamente idénticas a las que se presentan en los lenguajes naturales. También en estos es posible construir frases sintácticamente correctas pero carentes de sentido (los políticos saben mucho de esto). [7] En esta nomenclatura, una versión 2.4.10 es anterior a la 2.13.0, que a su vez es anterior a la 12.3. [8] Para resolver el problema de que algunos de estos símbolos no aparecen en los teclados de determinados idiomas (por ejemplo, la tilde ~ en los teclados españoles) se recurrió a representarlos mediante ternas de otros caracteres, los denominados trigrafos (

3.2.3e).

[9] Esta regla de análisis es conocida como de Max Munch; en realidad no es ningún personaje real, sino un convenio adoptado por los integrantes del primer Comité de Estandarización del lenguaje. [10] En general, un "parser" es un programa diseñado para analizar un documento. [11] " ið  i   ï             ið    i  iï    i ï     "      

ð à      ïï#   ð  ð    $  %   i  ï &        àï '    ð          (  $ )      i   ï       *V  i  ð ð      iï         ï      ïï i     ið( i ð   ". John K. Ousterhout. "criptingO Higher Level Programming for the 21st Century"

www.tcl.tk

[12] Como botón de muestra, señalar que en una aplicación C++ típica Windows, cuyo ejecutable resultaba de 631 KBytes en su versión "de campo", la inclusión de la información necesaria para depuración hizo aumentar su tamaño hasta 3.257 KBytes (Compilador GNU gcc-g++ 3.4.2 para Windows -incluido en Dev-C++ -)

&N? "     /  0 ] Las funciones son un conjunto de instrucciones que realizan una tarea específica. En general toman ciertos valores de entrada, llamados parámetros y proporcionan un valor de salida o valor de retorno; aunque en C++, tanto unos como el otro son opcionales, y pueden no existir. Tal vez parezca un poco precipitado introducir este concepto tan pronto en el curso. Sin embargo, las funciones son una herramienta muy valiosa, y como se usan en todos los

programas C++, creo que debemos tener, al menos, una primera noción de su uso. A fin de cuentas, todos los programas C++ contienen, como mínimo, una función.

V    ] En C++ es obligatorio usar prototipos. Un prototipo es una declaración de una función. Consiste en una presentación de la función, exactamente con la misma estructura que la definición, pero sin cuerpo y terminada con un ";". La estructura de un prototipo es: [j j|] †tipo_valor_retorno> [†modi±icadores>] †identi±icador>(†lista_parámetros>);

En general, el prototipo de una función se compone de las siguientes secciones: 4

4

4 4

4

Opcionalmente, una palabra que especifique el tipo de almacenamiento, puede ser

  o . Si no se especifica ninguna, por defecto será  . No te preocupes de esto todavía, de momento sólo usaremos funciones externas, lo menciono porque es parte de la declaración. El tipo del valor de retorno, que puede ser , si no necesitamos valor de retorno. En C, si no se establece, será  por defecto, aunque en general se considera una mala técnica de programación omitir el tipo de valor de retorno de una función. En C++ es obligatorio indicar el tipo del valor de retorno. Modificadores opcionales. Tienen un uso muy específico, de momento no entraremos en este particular, lo veremos en capítulos posteriores. El identificador de la función. Es costumbre, muy útil y muy recomendable, poner nombres que indiquen, lo más claramente posible, qué es lo que hace la función, y que permitan interpretar qué hace el programa con sólo leerlos. Cuando se precisen varias palabras para conseguir este efecto se puede usar alguna de las reglas más usuales. Una consiste en separar cada palabra con un "_". Otra, que yo prefiero, consiste en escribir la primera letra de cada palabra en mayúscula y el resto en minúsculas. Por ejemplo, si hacemos una función que busque el número de teléfono de una persona en una base de datos, podríamos llamarla "busca_telefono" o "BuscaTelefono". Una lista de declaraciones de parámetros entre paréntesis. Los parámetros de una función son los valores de entrada (y en ocasiones también de salida). Para la función se comportan exactamente igual que variables, y de hecho cada parámetro se declara igual que una variable. Una lista de parámetros es un conjunto de declaraciones de parámetros separados con comas. Puede tratarse de una lista vacía. En C es preferible usar la forma "func(void)" para listas de parámetros vacías. En C++ este procedimiento se considera obsoleto, se usa simplemente "func()".

Por ejemplo: int Mayor(int a, int b);

Un prototipo sirve para indicar al compilador los tipos de retorno y los de los parámetros de una función, de modo que compruebe si son del tipo correcto cada vez que se use esta función dentro del programa, o para hacer las conversiones de tipo cuando sea necesario.

En el prototipo, los nombres de los parámetros son opcionales, y si se incluyen suele ser como documentación y ayuda en la interpretación y comprensión del programa. El ejemplo de prototipo anterior sería igualmente válido si se escribiera como: int Mayor(int, int);

Esto sólo indica que en algún lugar del programa se definirá una función "Mayor" que admite dos parámetros de tipo  y que devolverá un valor de tipo . No es necesario escribir nombres para los parámetros, ya que el prototipo no los usa. En otro lugar del programa habrá una definición completa de la función. Normalmente, los prototipos de las funciones se declaran dentro del fichero del programa, o bien se incluyen desde un fichero externo, llamado fichero de cabecera, (para esto se usa la directiva O , que veremos en el siguiente capítulo). Ya lo hemos dicho más arriba, pero las funciones son   por defecto. Esto quiere decir que son accesibles desde cualquier punto del programa, aunque se encuentren en otros ficheros fuente del mismo programa. En contraposición las funciones declaradas  sólo son accesibles dentro del fichero fuente donde se definen.

?    ] Al igual que hemos visto con las variables, las funciones deben declararse, para lo que usaremos los prototipos, pero también deben definirse. Una definición contiene además las instrucciones con las que la función realizará su trabajo, es decir, su código. La sintaxis de una definición de función es: [j j|] †tipo_valor_retorno> [modi±icadores] †identi±icador>(†lista_parámetros>) { [sentencias] }

Como vemos, la sintaxis es idéntica a la del prototipo, salvo que se elimina el punto y coma final, y se añade el cuerpo de función que representa el código que será ejecutado cuando se llame a la función. El cuerpo de la función se encierra entre llaves "{}". La definición de la función se hace más adelante o más abajo, según se mire, es decir, se hace después que el prototipo. Lo habitual es hacerlo después de la función main. Una función muy especial es la función main, de la que ya hablamos en el capítulo primero. Se trata de la función de entrada, y debe existir siempre, ya será la que tome el control cuando se ejecute el programa. Los programas Windows usan la función WinMain como

función de entrada, aunque en realidad esta función contiene en su interior la definición de una función main, pero todo esto se explica en otro lugar. Existen reglas para el uso de los valores de retorno y de los parámetros de la función main, pero de momento la usaremos como int ë () o int ë (void), con un entero como valor de retorno y sin parámetros de entrada. El valor de retorno indicará si el programa ha terminado sin novedad ni errores retornando cero, cualquier otro valor de retorno indicará un código de error.

*   (GG ] La estructura de un programa en C o C++ quedaría así: [directivas del pre-procesador: includes y de±ines] [declaración de variables globales] [prototipos de ±unciones] [declaraciones de clases] ±unción main [de±iniciones de ±unciones] [de±iniciones de clases]

También se puede omitir el prototipo si se hace la definición antes de cualquier llamada a la función, es decir, en la zona de declaración de prototipos. Esto se puede hacer siempre, sin embargo no es muy recomendable como veremos a lo largo del curso. Para no dejar las cosas "a medias", podemos ver una posible definición de la función "Mayor", que podría ser la siguiente: int Mayor(int a, int b) { i±(a > b) return a; else return b; }

*       Los programas complejos se escriben normalmente usando varios ficheros fuente. Estos ficheros se compilan separadamente y se enlazan todos juntos. Esto es una gran ventaja durante el desarrollo y depuración de grandes programas, ya que las modificaciones en un fichero fuente sólo nos obligarán a compilar ese fichero fuente, y no el resto, con el consiguiente ahorro de tiempo. La definición de las funciones y clases puede hacerse dentro de los ficheros fuente o también pueden enlazarse desde bibliotecas compiladas previamente. En C++ es obligatorio el uso funciones prototipo, y aunque en C no lo es, resulta altamente recomendable.

4.8 USO Y MANTENIMIENTO (CON EJEMPLO). El mantenimiento también es más difícil y costoso que con lenguajes de más alto nivel. El código en C se presta a sentencias cortas y enrevesadas de difícil interpretación. Aunque el lenguaje admite código escrito de forma fácilmente legible, si no se siguen normas en el equipo de programación algunos programadores pueden acabar escribiendo código difícil de leer. Esto complica la revisión y el mantenimiento. C no dispone de sistemas de control automáticos y la seguridad depende casi exclusivamente de la experiencia del programador. La mayor parte de los problemas de seguridad en los sistemas informáticos actuales deriva de haber sido realizados en C. El fallo de seguridad clásico consiste en que algunas entradas de información al programa no se comprueban en longitud. Si un atacante introduce datos lo bastante grandes puede provocar la sobreescritura de código en la pila del programa e incluso llegar a forzar la ejecución de código pernicioso. Los lenguajes de tipo dinámico cuentan con controles de gestión de memoria y de entrada de datos automáticos. Por estas razones, los directores de desarrollo han de sopesar la ventaja en eficiencia de un buen programa en C frente a la mayor duración del trabajo y los riesgos de seguridad y estabilidad. Han de tener en cuenta además, que los equipos bajan de precio con el tiempo mientras que el coste de los programadores aumenta. En equipos de trabajo con poca experiencia en C, se desaconseja su uso porque el tipo de problemas y errores al que el programador se enfrenta hace más difícil aprender C sobre la marcha que en otros lenguajes.

 , que son las ecuaciones constitutivas que caracterizan el comportamiento de un sólido elástico lineal. Estas ecuaciones tienen la forma general:

Gran parte de las estructuras de ingeniería son diseñadas para sufrir deformaciones pequeñas,se involucran sólo en la recta del diagrama de esfuerzo y deformación. De tal forma que la deformación ȯ es una cantidad adimencional,el modulo E se expresa en las mismas unidades que el esfuerzo ı (unidades pa, psi y ksi).El máximo valor del esfuerzo para el que puede emplearse la ley de Hooke en un material es conocido como límite de proporcionalidad de un material .En este caso, los materiales dúctiles que poseen un punto de cedencia definido;en ciertos materiales no puede definirse la proporcionalidad de cedencia fácilmente, ya que es difícil determinar con precisión el valor del esfuerzo ı para el que la similitud entre ı y ȯ deje de ser lineal. Al utilizar la ley de Hooke en valores mayores que el límite de proporcionalidad no conducirá a ningún error significativo. En resistencia de materiales se involucra en las propiedades físicas de materiales,como resistencia ,ductibilidad y resistencia de corrosión;que pueden afectarse debido a la aleación ,el tratamiento térmico y el proceso de manofactura.

(    En el caso de un problema unidimensional donde las deformaciones o tensiones en direcciones perpendiculares a una dirección dada son irrelevantes o se pueden ignorar ı = ı11,  = 11, C11 = E y la ecuación anterior se reduce a:

donde E es el módulo de Young.

(     Para caracterizar el comportamiento de un sólido elástico lineal e isótropo se requieren además del módulo de Young otra constante elástica, llamada coeficiente de Poisson («). Por otro lado, las ecuaciones de Lamé-Hooke para un sólido elástico lineal e isótropo pueden ser deducidas del teorema de Rivlin-Ericksen, que pueden escribirse en la forma:

En forma matricial, en términos del módulo de Young y el coeficiente de Poisson como:

Las relaciones inversas vienen dadas por:

HIDROSTÁTICA. 2.4 PROPIEDADES DE LOS FLUIDOS: V 2V1 ?*? ? .2 3.41?2

Puesto que el estudio de 1a mecánica de fluidos trata típicamente con un fluido en flujo continuo o con una pequeña cantidad de fluido en reposo, es más conveniente relacionar la masa y el peso del fluido con un volumen dado del fluido. Así pues, las propiedades de densidad y de peso específico se definen de la manera siguienteO ?  1?*? La densidad es la cantidad de masa por unidad de volumen de una sustancia

Por consiguiente, utilizando la letra griega p para la densida

En donde V es el volumen de la sustancia cuya masa es m. Las unidades de densidad son kilogramos por metro cúbico en el istema Internacional (I) y slugs por pie cúbico en el istema Británico de Unidades. La ociedad Norteamericana para Pruebas y Materiales (ATM [American ocietv for Testing and Materials]) ha publicado varios métodos estándar de prueba para medir densidad, que describen recipientes cuya capacidad se conoce exactamente, llamados picnómetros. En estas normas se determina la forma apropiada de llenar, manejar, controlar la temperatura y hacer lecturas en estos dispositivos. Dos de ellos son el picnómetro de Bingham y el picnómetro bícapilar de Lipkin.

Las normas también exigen la determinación precisa dc la masa de los fluidos que se encuentran en los picnómetros al 0.1 Mg. más cercano, utilizando una balanza analítica. V 2 V #531#2 El peso específico es la cantidad de peso por unidad de volumen de una sustancia. Utilizando la letra griega

(gamma) para denotar el peso específico,

En donde V es el volumen de una sustancia que tiene el peso W. Las unidades del peso especifico, son los newtons por metro cúbico (N/m3) en el I y libras por pie cúbico (lb/pie3) en el istema Británico de Unidades. + *- ?*? V #131#* La gravedad especifica es el cociente de la densidad de una sustancia entre la densidad del agua a 4 °C, o, es el cociente del peso especifico de una sustancia entre el peso especifico del agua a 4 °C. Estas definiciones de la gravedad especifica se pueden expresar de manera matemática comoO

En donde el subíndice s se refiere a la sustancia cuya gravedad especifica se esta determinando y el subíndice w se refiere al agua. La definición matemática de gravedad especifica se puede escribir comoO

Esta definición es valida, independientemente de la temperatura a la que se determina la gravedad especifica. in embargo, las propiedades de los fluidos varían con la temperatura. En general cuando la densidad diminuye, aumenta la temperatura.

.*#12 / ?  1?*?6V 2 V #131#2

e encuentra muy a menudo que el peso especifico de una sustancia cuando se conoce su densidad y viceversa. La conversión de uno a otra se puede efectuar mediante la siguiente ecuación En la que g es la aceleración debida a la gravedad. La definición de peso especifico esO

Al multiplicar por g tanto el numerador como el denominador de esta ecuación obtenemosO

pero m = w / g por consiguiente tenemosO

puesto que p = m / v, obtenemosO

27& /1-2

4

Determinar las propiedades físicas, Densidad, Peso especifico y gravedad especifica a un liquido utilizando diferentes métodos.

4

Comprobar que la densidad de un fluido está relacionada directamente con su masa

4

Comprobar que el peso especifico de un fluido esta relacionado directamente con la densidad.

4

Adquirir destreza en el uso de los instrumentos y equipos de laboratorio.

4

Aprender que con métodos sencillos de laboratorio podemos averiguar propiedades de los fluidos 1/ 2?4##12

La realización del laboratorio es la parte del curso de Mecánica de fluidos, que sirve para confirmar los conceptos teóricos desarrollados en clase, con el comportamiento real de los fenómenos físicos; para luego

aplicar con confianza los conceptos teóricos en el estudio de manejo de fluidos en diferentes campos de la Ingeniería.

. 8 /2 4/1.19*?2

4

Calibrador

4

Picnómetro

4

Dos tipos de fluidos

4

Pipeta

4

Beaker

4

Densímetro o hidrómetro

4

Balanza

4

Termómetro

4

Recipiente Eureka Can

4

ólidos en hierro .*72 */2 12? 8 #*1#*? 3.41?2

V 2V1 ?*? ? .2 3.41?2  V

/*?2V2 41- 1?*?? .* *.. 3*#4./*?? 1+ 1 1*#1-1.

*/*3 ? 72+2/*:

V/1 87 ? . 000 #2#.4 12

4

Teniendo en cuenta que la forma como tomamos talvez no sea perfecta por lo tanto las medidas no fueron exactas, que factores como la temperatura, humedad del lugar donde se hicieron las pruebas tienen que ver con los resultados dados podemos decir que el factor de error es mínimo puesto que los valores obtenidos se parecen o se aproximan mucho a los valores que nos dan los textos.

   8 /2?2?  4 ;*#*

31+4 *

-2.#8; QF

98100 0,981

0,987

750

9,87

7500

10-4

0,968×10-4 0,0736

0,0981

10000

1

0,968

736

 /NM %0F 101325 1,01325

0,1013

10330

1,033

1

760

%/ )0F 133

1,33×10-4 13,6

0,00136

0,00132

1

0,00133

Las obsoletas unidades manométricas de presión, como los milímetros de mercurio, están basadas en la presión ejercida por el peso de algún tipo estándar de fluido bajo cierta gravedad estándar. Las unidades de presión manométricas no deben ser utilizadas para propósitos científicos o técnicos, debido a la falta de repetibilidad inherente a sus definiciones. También se utilizan los milímetros de columna de agua (mm c.d.a.)

V     

Manómetro. 1. La fuerza asociada a la presión en un fluido ordinario en reposo se dirige siempre hacia el exterior del fluido, por lo que debido al principio de acción reacción, resulta en una compresión para el fluido, jamás una tracción. 2. La superficie libre de un líquido en reposo (y situado en un campo gravitatorio constante) es siempre horizontal. Eso es cierto sólo en la superficie de la Tierra y a simple vista, debido a la acción de la gravedad no es constante. Si no hay acciones gravitatorias, la superficie de un fluido es esférica y, por tanto, no horizontal. 3. En los fluidos en reposo, un punto cualquiera de una masa líquida está sometida a una presión que es función únicamente de la profundidad a la que se encuentra el punto. Otro punto a la misma profundidad, tendrá la misma presión. A la superficie imaginaria que pasa por ambos puntos se llama superficie equipotencial de presión o superficie isobárica.

*   m      Los frenos hidráulicos de los automóviles son una aplicación importante del principio de Pascal. La presión que se ejerce sobre el pedal del freno se transmite a través de todo el líquido a los pistones los cuales actúan sobre los discos de frenado en cada rueda multiplicando la fuerza que ejercemos con los pies.    La refrigeración se basa en la aplicación alternativa de presión elevada y baja, haciendo circular un fluido en los momentos de presión por una tubería. Cuando el fluido pasa de presión elevada a baja en el evaporador, el fluido se enfría y retira el calor de dentro del refrigerador. Como el fluido se encuentra en un ciclo cerrado, al ser comprimido por un compresor para elevar su temperatura en el condensador, que también cambia de estado a líquido a alta presión, nuevamente esta listo para volverse a expandir y a retirar calor (recordemos que el frío no existe es solo una ausencia de calor).

c      Se inflan a una presión de 310.263,75 Pa, lo que equivale a 30 psi (utilizando el psi como unidad de presión relativa a la presión atmosférica). Esto se hace para que las llantas tengan elasticidad ante fuertes golpes (muy frecuentes al ir en el automóvil).

V  $"  La presión que se origina en la superficie libre de los líquidos contenidos en tubos capilares, o en gotas líquidas se denomina presión capilar. Se produce debido a la tensión superficial. En una gota es inversamente proporcional a su radio, llegando a alcanzar valores considerables. Por ejemplo, en una gota de mercurio de una diezmilésima de milímetro de diámetro hay una presión capilar de 100 atmósferas. La presión hidrostática corresponde al cociente entre la fuerza normal F que actúa, en el seno de un fluido, sobre una cara de un cuerpo y que es independiente de la orientación de ésta. Depende únicamente de la profundidad a la que se encuentra situado el elemento considerado. La de un vapor, que se encuentra en equilibrio dinámico con un sólido o líquido a una temperatura cualquiera y que depende únicamente de dicha temperatura y no del volumen, se designa con el nombre de presión de vapor o saturación.

2.6 PRINCIPIO DE ARQUIMEDES:

Ejemplo del Principio de Arquímedes

El  |16  es un principio físico que afirma que un cuerpo total o parcialmente sumergido en un fluido en reposo, será empujado con una fuerza vertical ascendente igual al peso del fluido desplazado por dicho cuerpo. Esta fuerza recibe el nombre de     o de Arquímedes, y se mide en newtons (en el SI). El principio de Arquímedes se formula así:

Donde  es el empuje , "f es la densidad del fluido, el volumen del cuerpo sumergido, ! la aceleración de la gravedad y m la masa, de este modo, el empuje depende de la densidad del fluido, del volumen del cuerpo y de la gravedad existente en ese lugar. El empuje (en condiciones normales1y descrito de modo simplificado2 ) actúa verticalmente hacia arriba y está aplicado en el centro de gravedad del fluido desalojado por el cuerpo; este punto recibe el nombre de centro de carena.

]   La anécdota más conocida sobre Arquímedes, matemático griego, cuenta cómo inventó un método para determinar el volumen de un objeto con una forma irregular. De acuerdo a Vitruvio, arquitecto de la antigua Roma, una nueva corona con forma de corona triunfal había sido fabricada para Hierón II, tirano gobernador de Siracusa, el cual le pidió a Arquímedes determinar si la corona estaba hecha de oro sólido o si un orfebre deshonesto le había agregado plata.3 Arquímedes tenía que resolver el problema sin dañar la corona, así que no podía fundirla y convertirla en un cuerpo regular para calcular su densidad. Mientras tomaba un baño, notó que el nivel de agua subía en la tina cuando entraba, y así se dio cuenta de que ese efecto podría usarse para determinar el volumen de la corona. Debido a que la compresión del agua sería despreciable,4 la corona, al ser sumergida, desplazaría una cantidad de agua igual a su propio volumen. Al dividir la masa de la corona por el volumen de agua desplazada, se podría obtener la densidad de la corona. La densidad de la corona sería menor si otros metales más baratos y menos densos le hubieran sido añadidos. Entonces, Arquímedes salió corriendo desnudo por las calles, tan emocionado estaba por su descubrimiento para recordar vestirse, gritando "¡Eureka!" (en griego antiguo: "Å" que significa "¡Lo he encontrado!)"5 La historia de la corona dorada no aparece en los trabajos conocidos de Arquímedes, pero en su tratado obre los cuerpos flotantes él da el principio de hidrostática conocido como el principio de Arquímedes. Este plantea que todo cuerpo sumergido en un fluido experimenta un empuje vertical y hacia arriba igual al peso del volumen de fluido desalojado es decir dos cuerpos que se sumergen en una superficie (ej:agua), y el más denso o el que tenga compuestos más pesados se sumerge más rápido, es decir, tarda menos tiempo, aunque es igual la distancia por la cantidad de volumen que tenga cada cuerpo sumergido.6

?  Aunque el principio de Arquímedes fue introducido como principio, de hecho puede considerarse un teorema demostrable a partir de las ecuaciones de Navier-Stokes para un fluido en reposo, mediante el teorema de Stokes (igualmente el principio de Arquímedes puede deducirse matemáticamente de las ecuaciones de Euler para un fluido en reposo que

a su vez pueden deducirse generalizando las leyes de Newton a un medio continuo). Partiendo de las ecuaciones de Navier-Stokes para un fluido:

(1) La condición de que el fluido incompresible que esté en reposo implica tomar en la ecuación anterior , lo que permite llegar a la relación fundamental entre presión del fluido, densidad del fluido y aceleración de la gravedad: (2) A partir de esa relación podemos reescribir fácilmente las fuerzas sobre un cuerpo sumergido en términos del peso del fluido desalojado por el cuerpo. Cuando se sumerge un sólido K en un fluido, en cada punto de su superficie aparece una fuerza por unidad de superfice perpendicular a la superficie en ese punto y proporcional a la presión del fluido p en ese punto. Si llamamos al vector normal a la superficie del cuerpo sencillamente mediante el teorema de podemos escribir la resultante de las fuerzas Stokes de la divergencia:

(3)

Donde la última igualdad se da sólo si el fluido es incompresible. V    Para un prisma recto de base Ab y altura H, sumergido en posición totalmente vertical, la demostración anterior es realmente elemental. Por la configuración del prisma dentro del fluido las presiones sobre el área lateral sólo producen empujes horizontales que además se anulan entre sí y no contribuyen a sustentarlo. Para las caras superior e inferior, puesto que todos sus puntos están sumergidos a la misma profundidad, la presión es constante y podemos usar la relación Fuerza = presión x Área y teniendo en cuenta la resultante sobre la cara superior e inferior, tenemos: (4) Donde pinf es la presión aplicada sobre la cara inferior del cuerpo, psup es la presión aplicada sobre la cara superior y A es el area proyectada del cuerpo. Teniendo en cuenta la ecuación

general de la hidrostática, que establece que la presión en un fluido en reposo aumenta proporcionalmente con la profundidad: (5) Introduciendo en el último término el volumen del cuerpo y multiplicando por la densidad del fluido f vemos que la fuerza vertical ascendente FV es precisamente el peso del fluido desalojado. (6) El empuje o fuerza que ejerce el líquido sobre un cuerpo, en forma vertical y ascendente, cuando éste se halla sumergido, resulta ser también la diferencia entre el peso que tiene el cuerpo suspendido en el aire y el "peso" que tiene el mismo cuando se lo introduce en un líquido. A éste último se lo conoce como peso "aparente" del cuerpo, pues su peso en el líquido disminuye "aparentemente"; la fuerza que ejerce la Tierra sobre el cuerpo permanece constante, pero el cuerpo, a su vez, recibe una fuerza hacia arriba que disminuye la resultante vertical.

2.7 PRINCIPIO DE PASCAL: En física, el  V  o  " V , es una ley enunciada por el físico y matemático francés Blaise Pascal (1623-1662) que se resume en la frase: la presión ejercida en cualquier parte de un fluido incompresible y en equilibrio dentro en un recipiente de paredes indeformables, se transmite con igual intensidad en todas las direcciones y en todos los puntos del fluido.1 El principio de Pascal puede comprobarse utilizando una esfera hueca, perforada en diferentes lugares y provista de un émbolo. Al llenar la esfera con agua y ejercer presión sobre ella mediante el émbolo, se observa que el agua sale por todos los agujeros con la misma velocidad y por lo tanto con la misma presión. También podemos ver aplicaciones del principio de Pascal en las prensas hidráulicas, en los elevadores hidráulicos y en los frenos hidráulicos. == Aplicaciones del principio ==la mayoria de personas le ponnen su nombre como es el principio de PASCAL El principio de Pascal puede ser interpretado como una consecuencia de la ecuación fundamental de la hidrostática y del carácter altamente incompresible de los líquidos. En esta clase de fluidos la densidad es prácticamente constante, de modo que de acuerdo con la ecuación:

Donde: , presión total a la profundidad , medida en Metros.

, presión sobre la superficie libre del fluido. , densidad del fluido. , aceleración de la gravedad. La presión se define como la fuerza ejercida sobre unidad de área p = F/A. De este modo obtenemos la ecuación: F1/A1 = F2/A2, entendiéndose a F1 como la fuerza en el primer pistón y A1 como el área de este último. Realizando despejes sobre este ecuación básica podemos obtener los resultados deseados en la resolución de un problema de física de este orden. Si se aumenta la presión sobre la superficie libre, por ejemplo, la presión total en el fondo ha de aumentar en la misma medida, ya que el término gh no varía al no hacerlo la presión total. Si el fluido no fuera incompresible, su densidad respondería a los cambios de presión y el principio de Pascal no podría cumplirse. Por otra parte, si las paredes del recipiente no fuesen indeformables, las variaciones en la presión en el seno del líquido no podrían transmitirse siguiendo este principio.

V    Artículo principal:Prensa hidráulica

La prensa hidráulica es una máquina compleja que permite amplificar la intensidad de las fuerzas y constituye el fundamento de elevadores, prensas, frenos y muchos otros dispositivos hidráulicos de maquinaria industrial. La prensa hidráulica constituye la aplicación fundamental del principio de Pascal y también un dispositivo que permite entender mejor su significado. Consiste, en esencia, en dos cilindros de diferente sección comunicados entre sí, y cuyo interior está completamente lleno de un líquido que puede ser agua o aceite. Dos émbolos de secciones diferentes se ajustan, respectivamente, en cada uno de los dos cilindros, de modo que estén en contacto con el líquido. Cuando sobre el émbolo de menor sección 1 se ejerce una fuerza F1 la presión p1 que se origina en el líquido en contacto con él se transmite íntegramente y de forma casi instantánea a todo el resto del líquido. Por el principio de Pascal esta presión será igual a la presión p2 que ejerce el fluido en la sección 2, es decir:

con lo que las fuerzas serán, siendo, 1; QF

98100 0,981

 /NM %0F 101325 1,01325

>; Q

0,987

750

9,87

7500

10-4

0,968×10-4 0,0736

0,0981

10000

1

0,968

736

0,1013

10330

1,033

1

760

%/ )0F 133

0,00133

1,33×10-4 13,6

0,00136

0,00132

1

Las obsoletas unidades manométricas de presión, como los milímetros de mercurio, están basadas en la presión ejercida por el peso de algún tipo estándar de fluido bajo cierta gravedad estándar. Las unidades de presión manométricas no deben ser utilizadas para propósitos científicos o técnicos, debido a la falta de repetibilidad inherente a sus definiciones. También se utilizan los milímetros de columna de agua (mm c.d.a.)

V      

Manómetro. 1. La fuerza asociada a la presión en un fluido ordinario en reposo se dirige siempre hacia el exterior del fluido, por lo que debido al principio de acción reacción, resulta en una compresión para el fluido, jamás una tracción. 2. La superficie libre de un líquido en reposo (y situado en un campo gravitatorio constante) es siempre horizontal. Eso es cierto sólo en la superficie de la Tierra y a simple vista, debido a la acción de la gravedad no es constante. Si no hay acciones gravitatorias, la superficie de un fluido es esférica y, por tanto, no horizontal. 3. En los fluidos en reposo, un punto cualquiera de una masa líquida está sometida a una presión que es función únicamente de la profundidad a la que se encuentra el punto. Otro punto a la misma profundidad, tendrá la misma presión. A la superficie imaginaria que pasa por ambos puntos se llama superficie equipotencial de presión o superficie isobárica.

  |  7     Los frenos hidráulicos de los automóviles son una aplicación importante del principio de Pascal. La presión que se ejerce sobre el pedal del freno se transmite a través de todo el líquido a los pistones los cuales actúan sobre los discos de frenado en cada rueda multiplicando la fuerza que ejercemos con los pies.

m   La refrigeración se basa en la aplicación alternativa de presión elevada y baja, haciendo circular un fluido en los momentos de presión por una tubería. Cuando el fluido pasa de presión elevada a baja en el evaporador, el fluido se enfría y retira el calor de dentro del refrigerador. Como el fluido se encuentra en un ciclo cerrado, al ser comprimido por un compresor para elevar su temperatura en el condensador, que también cambia de estado a líquido a alta presión, nuevamente esta listo para volverse a expandir y a retirar calor (recordemos que el frío no existe es solo una ausencia de calor).

c      Se inflan a una presión de 310.263,75 Pa, lo que equivale a 30 psi (utilizando el psi como unidad de presión relativa a la presión atmosférica). Esto se hace para que las llantas tengan elasticidad ante fuertes golpes (muy frecuentes al ir en el automóvil).

V    61  La presión que se origina en la superficie libre de los líquidos contenidos en tubos capilares, o en gotas líquidas se denomina presión capilar. Se produce debido a la tensión superficial. En una gota es inversamente proporcional a su radio, llegando a alcanzar valores considerables. Por ejemplo, en una gota de mercurio de una diezmilésima de milímetro de diámetro hay una presión capilar de 100 atmósferas. La presión hidrostática corresponde al cociente entre la fuerza normal F que actúa, en el seno de un fluido, sobre una cara de un cuerpo y que es independiente de la orientación de ésta. Depende únicamente de la profundidad a la que se encuentra situado el elemento considerado. La de un vapor, que se encuentra en equilibrio dinámico con un sólido o líquido a una temperatura cualquiera y que depende únicamente de dicha temperatura y no del volumen, se designa con el nombre de presión de vapor o saturación.

3.7 LEYES DE BOYLE, CHARLES Y GAY LUSSAC: La c " =" '$ (o c " =" ), formulada por Robert Boyle y Edme Mariotte, es una de las leyes de los gases ideales que relaciona el volumen y la presión de una cierta cantidad de gas mantenida a temperatura constante. La ley dice que el volumen es inversamente proporcional a la presión:

donde es constante si la temperatura y la masa del gas permanecen constantes. Cuando aumenta la presión, el volumen disminuye, mientras que si la presión disminuye el volumen aumenta. No es necesario conocer el valor exacto de la constante k para poder hacer uso de la ley: si consideramos las dos situaciones de la figura, manteniendo constante la cantidad de gas y la temperatura, deberá cumplirse la relación:

donde: = Presión inicial = Presión final = Volumen inicial = Volumen final Además si despejamos cualquier incógnita se obtiene lo siguiente :

Esta ley es una simplificación de la ley de los gases ideales o perfectos particularizada para procesos isotermos de una cierta masa de gas constante.

Junto con la ley de Charles, la ley de Gay-Lussac, la ley de Avogadro y la ley de Graham, la ley de Boyle forma las leyes de los gases, que describen la conducta de un gas ideal. Las tres primeras leyes pueden ser generalizadas en la ecuación universal de los gases.

*   ="  Para poder comprobar su teoría, Boyle hizo el siguiente experimento: Introdujo un gas en un cilindro con un émbolo y comprobó las distintas presiones al bajar el émbolo. A continuación hay una tabla que muestra algunos de los resultados que obtuvo: Experimento de Boyle S V/ 0 >-p," p:pp p  p  p>>p ( pL   pp p, p pp p p p p  p*pp("  p%   p p p p pp    p "  p(p  p  p" p p p p p , p p p p  p p  p p   p  p p p !Ep p  p p     p p p $ p p p p! p@ p p  p  pK p  pp $ p p p    p   p p :*  ),  68K0*                                    ‘                                    &           ‘                       &                                          '     )          *    )           L          * ‘                             + - *    1                                       4       ›%      21 "'"AP )68I2* %   )1  (  *    ‘ +              & 5  +           I                 $  >7777  2>777 )    

            *I77777    K777 +   Z          4     ›    &    =  /.  )›&=/.*                1   -‘    ‘  ;     1  ›   )›          1    * 1#  ›              $ M   M           (  ›    '    )›';* &        /   + 68@7 68K7                                         1    +      ›&=/. ////////////////

 + *  9$ ( ‘ 68@I  (   =           (=. )(   =  . *1  +                         )‘     68@@* 4   < %   @8 5    5         & % /(     27II7@   % 8J?    )(           * 1     1  (   60K70    1  =  G   1  (        ‘ ‘      + T   5         1       (  ‘          P › M )1  (  *

  68J0               ‘ 1               %           ›&=/.‘      +  ‘ 3'  )     3  *                           4  27777          ‘ ‘    66             68J2 ‘ +      -›           

   %     %  07 1  (   6J     8        K               %   #    &            ‘  68J2M                         .                 (    M                 (  ‘ 0>         &   >  +         &(=.                           (=.   ‘   0J  68J2                 ‘  1         M !   1  (   M                       ‘  1  =      / ‘     $     ›  1  1  ›    ;    &           ‘ 5                         #      ‘ 68J@        ‘     + M         (  =     0>  06

          › )›  %  1# *      + ‘ 0K   +       ‘            ‘  E   ‘              4›        P (   77       ›   &    ›   +      C        5        ca Raza Cósmica                    

                            + -                                                Z                     ‘    raza cósmica                                     ›ovimiento Vostmista,        ;# !                            6827"                                                   #                   +  ›   ‘    6806      1  N  ,  

                     +           7` &                                                           

 M           &                                         -P › P 1  !%  M P % ›      +        ‘    F"'''                               % M  ‘  ! P 3         

  &   O                  !         ;   na fi osofía de o atinoamericano 3I&                      

               
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF