alexis lopez
 
  Home
  B.D
  B.D II
  => Tareas
  => Logica computacional
  => Manual de C
  => codigo ascii
  => avance proyecto
  => Metodo de ordenamiento
  java
Manual de C

1. Compilación de un programa en C/C++

n esta capítulo se dan las procesos básicos que se requieren para compilar un programa de C. Se describe también el modelo de compilación de C y también como C soporta bibliotecas adicionales.

 

1.1 Creación, compilación y ejecución de un programa

 

1.1.1 Creación del programa

e puede crear un archivo que contenga el programa completo, como en los ejemplos que se tienen más adelante. Se puede usar cualquier editor de textos ordinario con el que se este familiarizado. Un editor disponible en la mayoría de los sistemas UNIX es vi, y en Linux se puede usar pico.

or convención el nombre del archivo debe terminar con ``.c'' por ejemplo: miprograma.c progprueba.c. El contenido del archivo deberá obedecer la sintaxis de C.

 

1.1.2 Compilación

xisten muchos compiladores de C. El cc es el compilador estándar de Sun. El compilador GNU de C es gcc, el cual es bastante popular y esta disponible en varias plataformas.

xisten también compiladores equivalentes de C++ los cuales usualmente son nombrados como CC. Por ejemplo, Sun provee CC y GNU GCC. El compilador de GNU es también denotado como g++.

xisten otros compiladores menos comunes de C y C++. En general todos los compiladores mencionados operan esencialmente de la misma forma y comparten muchas opciones comunes en la línea de opciones. Más adelante se listan y se dan ejemplos de opciones comunes de los compiladores. Sin embargo, la mejor referencia de cada compilador es a través de las páginas en línea, del manual del sistema. Por ejemplo: man gcc.

ara compilar el programa usaremos el comando gcc. El comando deberá ser seguido por el nombre del programa en C que se quiere compilar. Un determinado número de opciones del compilador pueden ser indicadas también. Por el momento no haremos uso de estas opciones todavía, se irán comentando algunas más esenciales.

or lo tanto, el comando básico de compilación es:

gcc programa.c

donde programa.c es el nombre del archivo.

i hay errores obvios en el programa (tales como palabras mal escritas, caracteres no tecleados u omisiones de punto y coma), el compilador se detendrá y los reportará.

odría haber desde luego errores lógicos que el compilador no podrá detectar. En el caso que esta fuera la situación se le estará indicando a la computadora que haga las operaciones incorrectas.

uando el compilador ha terminado con éxito, la versión compilada, o el ejecutable, es dejado en un archivo llamado a.out, o si la opción -o es usada con el compilador, el nombre después de -o es el nombre del programa compilado.

e recomienda y es más conveniente usar la opción -o con el nombre del archivo ejecutable como se muestra a continuación:

gcc -o programa programa.c

el cual pone el programa compilado en el archivo del programa señalado, en éste caso en programa, en vez del archivo a.out.

 

1.1.3 Ejecución del programa

l siguiente estado es correr el programa ejecutable. Para correr un ejecutable en UNIX, simplemente se escribe el nombre del archivo que lo contiene, en este casoprograma (o a.out).

on lo anterior, se ejecuta el programa, mostrando algún resultado en la pantalla. En éste estado, podría haber errores en tiempo de ejecución (run-time errors), tales como división por cero, o bien, podrían hacerse evidentes al ver que el programa no produce la salida correcta.

i lo anterior sucede, entonces se debe regresar a editar el archivo del programa, recompilarlo, y ejecutarlo nuevamente.

 

1.2 El modelo de compilación de C

n la figura 1.1 se muestran las distintas étapas que cubre el compilador para obtener el código ejecutable.

 

Figura 1.1: Modelo de compilación de C.
includegraphics[width=2in, clip]{figuras/modelo_C.eps}

 

1.3 El preprocesador

sta parte del proceso de compilación será cubierta con más detalle en el capítulo 12 referente al preprocesador. Sin embargo, se da alguna información básica para algunos programas de C.

l preprocesador acepta el código fuente como entrada y es responsable de:

  • quitar los comentarios
  • interpretar las directivas del preprocesador las cuales inician con #.

or ejemplo:

  • #include -- incluye el contenido del archivo nombrado. Estos son usualmente llamados archivos de cabecera (header). Por ejemplo:
    • #include <math.h> -- Archivo de la biblioteca estándar de matemáticas.
    • #include <stdio.h> -- Archivo de la biblioteca estándar de Entrada/Salida.
  • #define -- define un nombre simbólico o constante. Sustitución de macros.
    • #define TAM_MAX_ARREGLO 100

 

1.4 Compilador de C

l compilador de C traduce el código fuente en código de ensamblador. El código fuente es recibido del preprocesador.

 

1.5 Ensamblador

l ensamblador crea el código fuentei o los archivos objeto. En los sistemas con UNIX se podrán ver los archivos con el sufijo .o.

 

1.6 Ligador

i algún archivo fuente hace referencia a funciones de una biblioteca o de funciones que están definidas en otros archivos fuentes, el ligador combina estas funciones (con main()) para crear un archivo ejecutable. Las referencias a variables externas en esta étapa son resueltas.

 

1.7 Algunas opciones útiles del compilador

escrito el modelo básico de compilación, se darán algunas opciones útiles y algunas veces esenciales. De nueva cuenta, se recomienda revisar las páginas de manpara mayor información y opciones adicionales.

 

Se compilador se detiene en la étapa de preprocesamiento y el resultado se muestra en la salida estándar.
gcc -E arch1.c

 

Suprime el proceso de ligado y produce un archivo .o para cada archivo fuente listado. Después los archivos objeto pueden ser ligados por el comando gcc, por ejemplo:
gcc arch1.o arch2.o ... -o ejecutable

biblioteca

Liga con las bibliotecas objeto. Esta opción deberá seguir los argumentos de los archivos fuente. Las bibliotecas objeto son guardadas y pueden estar estandarizadas, un tercero o usuario las crea. Probablemente la biblioteca más comúnmente usada es la biblioteca matemática (math.h). Esta biblioteca deberá ligarse explícitamente si se desea usar las funciones matemáticas (y por supuesto no olvidar el archivo cabecera #include <math.h>, en el programa que llama a las funciones), por ejemplo:
gcc calc.c -o calc -lm
Muchas otras bibliotecas son ligadas de esta forma.

directorio

Agrega directorios a la lista de directorios que contienen las rutinas de la biblioteca de objetos. El ligador siempre busca las bibliotecas estándares y del sistema en/lib y /usr/lib. Si se quieren ligar bibliotecas personales o instaladas por usted, se tendrá que especificar donde estan guardados los archivos, por ejemplo:
gcc prog.c -L/home/minombr/mislibs milib.a

trayectoria

Agrega una trayectoria o ruta a la lista de directorios en los cuales se buscarán los archivos cabecera #include con nombres relativos (es decir, los que no empiezan con diagonal /).

 

El procesador por default, primero busca los archivos #include en el directorio que contiene el archivo fuente, y después en los directorios nombrados con la opción -I si hubiera, y finalmente, en /usr/include. Por lo tanto, si se quiere incluir archivos de cabecera guardados en /home/minombr/miscabeceras se tendrá que hacer:
gcc prog.c -I/home/minombr/miscabeceras
Nota: Las cabeceras de las bibliotecas del sistema son guardados en un lugar especial (/usr/include) y no son afectadas por la opción -I. Los archivos cabecera del sistema y del usuario son incluídos en una manera un poco diferente.

 

Opción para llamar las opciones de depuración (debug). Instruye al compilador para producir información adicional en la tabla de símbolos que es usado por una variedad de utilerías de depuración. Por ejemplo, si se emplea el depurador de GNU, el programa deberá compilarse de la siguiente forma para generar extensiones de GDB:
gcc -ggdb -o prog prog.c

 

Define símbolos como identificadores (-Didentificador) o como valores (-Dsímbolo=valor) en una forma similar a la directiva del preprocesador #define).

 

Muestra en la salida estandar de errores los comandos ejecutados en las étapas de compilación.

 

1.8 Uso de las bibliotecas

 es un lenguaje extremadamente pequeño. Muchas de las funciones que tienen otros lenguajes no están en C, por ejemplo, no hay funciones para E/S, manejo de cadenas o funciones matemáticas.

a funcionalidad de C se obtiene a través de un rico conjunto de bibliotecas de funciones.

omo resultado, muchas implementaciones de C incluyen bibliotecas estándar de funciones para varias finalidades. Para muchos propósitos básicos estas podrían ser consideradas como parte de C. Pero pueden variar de máquina a máquina.

n programador puede también desarrollar sus propias funciones de biblioteca e incluso bibliotecas especiales de terceros, por ejemplo, NAG o PHIGS.

odas las bibliotecas (excepto E/S estándar) requieren ser explícitamente ligadas con la opción -l y, posiblemente con L, como se señalo previamente.

 

1.9 Ejemplos

 

1.9.1 Creación de una biblioteca estática

i se tiene un conjunto de rutinas que se usen en forma frecuente, se podría desear agruparlas en un conjunto de archivos fuente, compilar cada archivo fuente en un archivo objeto, y entonces crear una biblioteca con los archivos objeto. Con lo anterior se puede ahorrar tiempo al compilar en aquellos programas donde sean usadas.

upongamos que se tiene un conjunto de archivos que contengan rutinas que son usadas frecuentemente, por ejemplo un archivo cubo.c:

 

float cubo(float x)
{
	return (x*x*x);
}

 otro archivo factorial.c

 

int factorial(int n)
{
	int i, res=1;
	for(i=1; i<=n; i++)
		res*=i;
	return (res);
}

ara los archivos de nuestras funciones también se debe tener un archivo de cabezera, para que puedan ser usadas, suponiendo que se tiene el siguiente archivolibmm.h con el siguiente contenido:

 

extern float cubo(float);
extern int factorial(int);

l código que use la biblioteca que se esta creando podría ser:

 

/* Programa prueba.c */
#include "libmm.h"
#define VALOR 4

main()
{
	printf("El cubo de %d es %fn",VALOR, cubo(VALOR) );
	printf("t y su factorial es %dn",factorial(VALOR) );
}

ara crear la biblioteca se deben compilar los archivos fuente, que lo podemos hacer de la siguiente forma:

 

$ gcc -c cubo.c factorial.c

o cual nos dejará los archivos cubo.o y factorial.o. Después se debe crear la biblioteca con los archivos fuentes, suponiendo que nuestra biblioteca se llame libmm.a, tendrás que hacerlo con el comando ar así:

 

$ ar r libmm.a cubo.o factorial.o

uando se actualiza una biblioteca, se necesita borrar el archivo anterior (libmm.a). El último paso es crear un índice para la biblioteca, lo que permite que el ligador pueda encontrar las rutinas. Lo anterior, lo hacemos con el comando ranlib, por lo que teclearemos ahora:

 

$ ranlib libmm.a

os últimos dos pasos pudieron ser combinados en uno sólo, entonces hubieramos podido teclear:

 

$ar rs libmm.a cubo.o factorial.o

hora que ya tenemos la biblioteca, es conveniente que coloquemos nuestra biblioteca y el archivo cabezera en algún lugar apropiado. Supongamos que dejamos la biblioteca en ~/lib y el fichero cabezera en ~/include, debemos hacer lo siguiente:

 

$ mkdir ../include
$ mkdir ../lib
$ mv libmm.h ../include
$ mv libmm.a ../lib

i llegarás a modificar la biblioteca, tendrías que repetir la última instrucción.

e debe ahora compilar el archivo con la biblioteca, de la siguiente forma:

 

gcc -I../include -L../lib -o prueba prueba.c -lmm

 

1.9.2 Creación de una biblioteca compartida

as ventajas que presentan las bibliotecas compartidas, es la reducción en el consumo de memoria, si son usadas por más de un proceso, además de la reducción del tamaño del código ejecutable. También se hace el desarrollo más fácil, ya que cuando se hace algún cambio en la biblioteca, no se necesita recompilar y reenlazar la aplicación cada vez. Se requiere lo anterior sólo si se modifico el número de argumentos con los que se llama una función o se cambio el tamaño de alguna estructura.

l código de la biblioteca compartida necesita ser independiente de la posición, para hacer posible que sea usado el código por varios programas. Para crear la biblioteca hacerlo de la siguiente forma:

 

$ gcc -c -fPIC cubo.c factorial.c

ara generar la biblioteca dinámica hacer lo siguiente:

 

$ gcc -shared -o libmm.so cubo.o factorial.o

o existe un paso para la indexación como ocurre en las bibliotecas estáticas.

espués habrá que mover la biblioteca dinámica a su directorio correspondiente (../lib) y proceder a compilar para que nuestro código use la biblioteca.

 

$ gcc -I../include -L../lib -o prueba prueba.c -lmm

os preguntamos que sucede si hay una biblioteca compartida (libmm.so) y una estática (libmm.a) disponibles. En este caso, el ligador siempre toma la compartida. Si se desea hacer uso de la estática, se tendrá que nombrar explícitamente en la línea de comandos:

 

$ gcc -I../include -L../lib -o prueba prueba.c libmm.a

uando se usan bibliotecas compartidas un comando útil es ldd, el cual nos informa que bibliotecas compartidas un programa ejecutable usa, a continuación un ejemplo:

 

$ ldd prueba
	libstuff.so => libstuff.so (0x40018000)
	libc.so.6 => /lib/i686/libc.so.6 (0x4002f000)
	/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

omo se ve en cada línea aparece el nombre de la biblioteca, el camino completo a la biblioteca que es usada, y donde en el espacio de direcciones virtuales la biblioteca esta mapeada.

i ldd muestra como salida not found para alguna biblioteca, se van a tener problemas y el programa no podra ser ejecutado. Una forma de arreglarlo es buscar la biblioteca y colocarla en el lugar correcto para que el programa loader la encuentre, que siempre busca por default en lib y /usr/lib. Si se tienen bibliotecas en otro directorio, crear una variable de ambiente LD_LIBRARY_PATH y poner los directorios separados por ;.

 

1.10 Funciones de la biblioteca de UNIX

l sistema UNIX da un gran número de funciones de C. Algunas implementan operaciones de uso frecuente, mientras otras están muy especializadas en relación a su aplicación.

o reinvente la rueda. Se recomienda revisar si una función en alguna biblioteca existe, en vez de hacer la tarea de escribir su propia versión. Con lo anterior se reduce el tiempo de desarrollo de un programa. Ya que las funciones de la biblioteca han sido probadas, por lo que estarán corregidas, a diferencia de cualquiera que un programador pueda escribir. Lo anterior reducirá el tiempo de depuración del programa.

 

1.10.1 Encontrando información acerca de las bibliotecas.

l manual de UNIX tiene una entrada para todas las funciones disponibles. La documentación de funciones esta guardada en la sección 3 del manual, y hay muchas otras útiles que hacen llamadas al sistema en la sección 2. Si ya sabe el nombre de la función que se quiere revisar, puede leer la página tecleando:

man 3 sqrt

i no sabe el nombre de la función, una lista completa esta incluida en la página introductoria de la sección 3 del manual. Para leerlo, teclee:

man 3 intro

ay aproximadamente 700 funciones. El número tiende a incrementarse con cada actualización al sistema.

n cualquier página del manual, la sección de SYNOPSIS incluye información del uso de la función. Por ejemplo:

 

#include <time.h>
char *ctime(const time_t *timep);

o que significa que se debe tener

 

#include <time.h>

n el archivo del programa que hace el llamado a ctime. Y que la función ctime toma un apuntador del tipo time_t como un argumento, y regresa una cadena char *.

n la sección DESCRIPTION se da una pequeña descripción de lo que hace la función.

2.3 Estructura de un programa en C

n programa de C tiene básicamente la siguiente forma:

  • Comandos del preprocesador.
  • Definiciones de tipos.
  • Prototipos de funciones - declara el tipo de función y las variables pasadas a la misma.
  • Variables
  • Funciones

ara un programa se debe tener una función main().

na función tiene la forma:

 

tipo nombre_de_la_funcion (parámetros)
{

      variables locales
              
      sentencias de C
              
}

i la definición del tipo es omitida, C asume que la función regresa un tipo entero. Nota: Lo anterior puede ser una fuente de problemas en un programa.

 continuación se muestra un primer programa:

 

/* Programa ejemplo */ 
              
main()
{
              
   printf( "Me gusta Cn" );
   exit (0);
              
}

OTAS:

  • C requiere un punto y coma al final de cada sentencia.
  • printf es una función estándar de C, la cual es llamada en la función main().
  • n significa salto de línea. Salida formateada.
  • exit() es también una función estándar que hace que el programa termine. En el sentido estricto no es necesario ya que es la última línea de main() y de cualquier forma terminará el programa.

n caso de que se hubiera llamado a la función printf de la siguiente forma: 

 

printf(".n.1n..2n...3n");

a salida tendría la siguiente forma:

 

.1
..2
...3

 

2.4 Variables

 tiene los siguientes tipos de datos simples: 

 

Tabla 2.1: Tipos de C
Tipo Tamaño (bytes) Límite inferior Límite superior
char 1 -- --
unsigned char 1 $0$ $255$
short int 2 $-32768$ $+32767$
unsigned short int 2 $0$ $65536$
(long) int 4 $-2^{31}$ $+2^{31}-1$
float 4 $-3.2 times 10^{pm38} $ $+3.2 times 10^{pm38} $
double 8 $-1.7 times 10^{pm308} $ $+1.7 times 10^{pm308} $

 

 

os tipos de datos básicos tiene varios modificadores que les preceden. Se usa un modificador para alterar el significado de un tipo base para que encaje con las diversas necesidades o situaciones. Los modificadores son: signed, unsigned, long y short.

n los sistemas UNIX todos los tipos int son long int, a menos que se especifique explícitamente short int.

ota: no hay un tipo booleano en C -- se deberá usar char, int o aún mejor unsigned char.

igned, unsigned, long y short pueden ser usados con los tipos char e int. Aunque es permitido el uso de signed en enteros, es redundante porque la declaración de entero por defecto asume un número con signo.

ara declarar una variable en C, se debe seguir el siguiente formato:

 

tipo lista_variables;

ipo es un tipo válido de C y lista_variables puede consistir en uno o más indentificadores separados por una coma. Un identificador debe comenzar con una letra o un guión bajo.

jemplo:

int i, j, k;
float x,y,z;
char ch;

 

2.4.1 Definición de variables globales

na varible global se declara fuera de todas las funciones, incluyendo a la función main(). Una variable global puede ser utilizada en cualquier parte del programa.

or ejemplo:

short numero, suma;
int numerogr, sumagr;
char letra;

main()
{
...
}

s también posible preinicializar variables globales usando el operador de asignación =, por ejemplo:

 

float suma= 0.0;
int sumagr= 0;
char letra= 'A';

main()
{
...
}

ue es lo mismo que:

 

float suma;
int sumagr;
char letra;

main()
{
    suma  = 0.0;
    sumagr= 0;
    letra = 'A';

...
}

entro de C también se permite la asignación múltiple usando el operador =, por ejemplo: 

a = b = c = d = 3;

ue es lo mismo, pero más eficiente que:

a = 3;
b = 3;
c = 3;
d = 3;

a asignación múltiple se puede llevar a cabo, si todos los tipos de las variables son iguales.

Se pueden redefinir los tipos de C usando typedef. Como un ejemplo de un simple uso se considera como se crean dos nuevos tipos real y letra. Estos nuevos tipos pueden ser usados de igual forma como los tipos predefinidos de C.

 

typedef float real;
typedef char letra;

/* Declaracion de variables usando el nuevo tipo */
real suma=0.0;
letra sig_letra;

 

2.4.2 Lectura y escritura de variables

l lenguaje C usa salida formateada. La función printf tiene un caracter especial para formatear (%) -- un caracter enseguida define un cierto tipo de formato para una variable.

%c caracteres 
%s cadena de aracteres 
%d enteros 
%f flotantes 

or ejemplo: 

printf("%c %d %f",ch,i,x);

a sentencia de formato se encierra entre " ", y enseguida las variables. Asegurarse que el orden de formateo y los tipos de datos de las variables coincidan.

canf() es la función para entrar valores a variables. Su formato es similar a printf. Por ejemplo: 

 

scanf("%c %d %f %s",&ch, &i, &x, cad);

bservar que se antepone & a los nombres de las varibles, excepto a la cadena de caracteres. En el capítulo 8 que trata sobre apuntadores se revisará más a fondo el uso de este operador.

 

2.5 Constantes

NSI C permite declarar constantes. Cuando se declara una constante es un poco parecido a declarar una variable, excepto que el valor no puede ser cambiado.

a palabra clave const se usa para declarar una constante, como se muestra a continuación:

const a = 1;
int a = 2;

otas:

  • Se puede usar const antes o después del tipo.
  • Es usual inicializar una constante con un valor, ya que no puede ser cambiada de alguna otra forma.

a directiva del preprocesador #define es un método más flexible para definir constantes en un programa.

recuentemente se ve la declaración const en los parámetros de la función. Lo anterior simplemente indica que la función no cambiara el valor del parámetro. Por ejemplo, la siguiente función usa este concepto:

 

char *strcpy(char *dest, const char *orig);

l segundo argumento orig es una cadena de C que no será alterada, cuando se use la función de la biblioteca para copiar cadenas.

 

2.6 Operadores Aritméticos

o mismo que en otros lenguajes de programación, en C se tienen los operadores aritméticos más usuales (+ suma, - resta, * multiplicación, / división y % módulo).

l operador de asignación es =, por ejemplo: i=4; ch='y';

ncremento ++ y decremento -- unario. Los cuales son más eficientes que las respectivas asignaciones. Por ejemplo: x++ es más rápido que x=x+1.

os operadores ++ y -- pueden ser prefijos o postfijos. Cuando son prefijos, el valor es calculado antes de que la expresión sea evaluada, y cuando es postfijo el valor es calculado después que la expresión es evaluada.

n el siguiente ejemplo, ++z es prefijo y -- es postfijo:

int x,y,z;

main()
{
    x=( ( ++z ) - ( y-- ) ) % 100;
}

ue es equivalente a:

int x,y,z;

main()
{
    z++;
    x = ( z-y ) % 100;
    y--;
}

l operador % (módulo o residuo) solamente trabaja con enteros, aunque existe una función para flotantes (15.1 fmod() ) de la biblioteca matemática.

l operador división / es para división entera y flotantes. Por lo tanto hay que tener cuidado. El resultado de x = 3 / 2; es uno, aún si x es declarado como float. La regla es: si ambos argumentos en una división son enteros, entoces el resultado es entero. Si se desea obtener la división con la fracción, entonces escribirlo como: x = 3.0 / 2; o x = 3 / 2.0 y aún mejor x = 3.0 / 2.0.

or otra parte, existe una forma más corta para expresar cálculos en C. Por ejemplo, si se tienen expresiones como: i = i + 3; o x = x * (y + 2); , pueden ser reescritas como:

$expr_1 mbox{ oper } = expr_2$

o cual es equivalente, pero menos eficiente que:

 

$expr_1 = expr_1 mbox{ oper } expr_2$

or lo que podemos reescribir las expresiones anteriores como: i += 3; y x *= y + 2; respectivamente.

 

2.7 Operadores de Comparación

l operador para probar la igualdad es ==, por lo que se deberá tener cuidado de no escribir accidentalmente sólo =, ya que:

 

if ( i = j ) ...

s una sentencia legal de C (sintácticamente hablando aunque el compilador avisa cuando se emplea), la cual copia el valor de ``j'' en ``i'', lo cual será interpretado como VERDADERO, si j es diferente de cero.

iferente es !=, otros operadores son: < menor que, > mayor que, <= menor que o igual a y >= (mayor que o igual a).

 

2.8 Operadores lógicos

os operadores lógicos son usualmente usados con sentencias condicionales o relacionales, los operadores báscios lógicos son:

 Y lógico, || O lógico y ! negación.

 

2.9 Orden de precedencia

s necesario ser cuidadosos con el significado de expresiones tales como a + b * c, dependiendo de lo que se desee hacer

(a + b) * c

o

a + (b * c)

odos los operadores tienen una prioridad, los operadores de mayor prioridad son evaluados antes que los que tienen menor prioridad. Los operadores que tienen la misma prioridad son evaluados de izquierda a derecha, por lo que:

a - b - c

es evaluado como

(a - b) - c

 

Prioridad Operador(es)
Más alta ( ) [ ] ->
  ! ~ ++ -- - (tipo) * & sizeof
  * / %
  + -
  << >>
  < <= > >=
  == !=
  &
  ^
  |
  &&
  ||
  ?
  = += -= *= /=
Más baja ,

e acuerdo a lo anterior, la siguiente expresión:

 

a < 10 && 2 * b < c

s interpretada como:

 

(a < 10) && ( (2 * b) < c )

 

a =
     b =
            10 / 5
                    + 2;

omo

a =
     ( b =
            ( 10 / 5 )
                        + 2 );

3. Estructuras Condicionales

n este capítulo se revisan los distintos métodos con los que C controla el flujo lógico de un programa.

omo se revisó en el capítulo anterior, los operadores relaciones binarios que se usan son:

 

==, !=, <, <=, > y >=

demás los operadores lógicos binarios:

 

||, &&

 el operador lógico unario de negación !, que sólo toma un argumento.

os operadores anterior son usados con las siguientes estructuras que se muestran.

 

3.1 La sentencia if

as tres formas como se puede emplear la sentencia if son: 

if (condicion)
sentencia;

 

if (condicion)
sentencia1;
else
sentencia2;

 

if (condicion1)
sentencia1;
else if (condicion2)
sentencia2;
... 
else
sentencian;

l flujo lógico de esta estructura es de arriba hacia abajo. La primera sentencia se ejecutará y se saldrá de la estructura if si la primera condición es verdadera. Si la primera condición fue falsa, y existe otra condición, se evalúa, y si la condición es verdadera, entonces se ejecuta la sentencia asociada. Si existen más condiciones dentro de la estructura if, se van evaluando éstas, siempre y cuando las condiciones que le precedan sean falsas.

a sentencia que esta asociada a la palabra reservada else, se ejecuta si todas las condiciones de la estructura if fueron falsas.

or ejemplo:

 

main()
{
   int x, y, w;

	........

   if (x>0)
   {
      z=w;
      .......
   }
   else
   {
      z=y;
      .......
   }
}

 

3.2 El operador ?

l operador ternario condicional ? es más eficiente que la sentencia if. El operador ? tiene el siguiente formato:

 

expresion1 ? expresion 2 : expresion3;

ue es equivalente a la siguiente expresión:

 

if (expresion1) then expresion2 else expresion3;

or ejemplo, para asignar el máximo de a y b a la variable z, usando ?, tendríamos:

 

z = (a>b) ? a : b;

ue es lo mismo que:

 

if (a > b)
        z = a;
    else
        z = b;

l uso del operador ? para reemplazar las sentencias if ... else no se restringe sólo a asignaciones, como en el ejemplo anterior. Se pueden ejecutar una o más llamadas de función usando el operador ? poniéndolas en las expresiones que forman los operandos, como en el ejemplo siguiente:

f1(int n)
{
    printf("%d ",n);
}

f2()
{
    printf("introducidon");
}

main()
{
    int t;

    printf(": ");
    scanf("%d",&t);

    /* imprime mensaje apropiado */
    t ? f1(t) + f2() : printf("Se dió un ceron");

}

 

3.3 La sentencia switch

unque con la estructura if ... else if se pueden realizar comprobaciones múltiples, en ocasiones no es muy elegante, ya que el código puede ser difícil de seguir y puede confundir incluso al autor transcurrido un tiempo. Por lo anterior, C tiene incorporada una sentencia de bifurcación múltiple llamada switch. Con esta sentencia, la computadora comprueba una variable sucesivamente frente a una lista de constantes enteras o de caracter. Después de encontrar una coincidencia, la computadora ejecuta la sentencia o bloque de sentencias que se asocian con la constante. La forma general de la sentencia switch es: 

switch (variable) {
case constante1:
secuencia de sentencias 
break;
case constante2:
secuencia de sentencias 
break;
case constante3:
secuencia de sentencias 
break;
... 
default:
secuencia de sentencias
}

onde la computadora ejecuta la sentencia default si no coincide ninguna constante con la variable, esta última es opcional. Cuando se encuentra una coincidencia, la computadora ejecuta las sentencias asociadas con el case hasta encontrar la sentencia break con lo que sale de la estructura switch.

as limitaciones que tiene la sentencia switch ... case respecto a la estructura if son:

 

  • Sólo se tiene posibilidad de revisar una sola variable.
  • Con switch sólo se puede comprobar por igualdad, mientras que con if puede ser con cualquier operador relacional.
  • No se puede probar más de una constante por case.

a forma como se puede simular el último punto, es no teniendo sentencias asociados a un case, es decir, teniendo una sentencia nula donde sólo se pone el caso, con lo que se permite que el flujo del programa caiga al omitir las sentencias, como se muestra a continuación:

 

switch (letra)
{
   case 'a':
   case 'e':
   case 'i':
   case 'o':
   case 'u':
      numvocales++;
      break;

   case ' ':
      numesp++;
      break;

   default:
      numotras++;
      break;
}

4. Iteración

n este capítulo se revisan los mecanismos de C para repetir un cojunto de instrucciones hasta que se cumple cierta condición.

 

4.1 La sentencia for

a sentencia for tiene el siguiente formato: 

for ( expresion1; expresion2; expresion3)
sentencia; 
o { bloque de sentencias }

n donde expresion1 se usa para realizar la inicialización de variables, usando una o varias sentencias, si se usan varias sentencias deberá usarse el operador , para separarlas. Por lo general, establece el valor de la variable de control del ciclo. expresion2 se usa para la condición de terminación del ciclo y expresion3 es el modificador a la variable de control del ciclo cada vez que la computadora lo repite, pero también puede ser más que un incremento.

or ejemplo:

int X;

main()
{
    for( X=3; X>0; X--)
    {
        printf("X=%dn",X);
    }
}

enera la siguiente salida a pantalla ...

 

X=3
X=2
X=1

odos las siguientes sentencias for son válidas en C. Las aplicaciones prácticas de tales sentencias no son importantes aquí, ya que tan sólo se intenta ilustrar alguanas características que pueden ser de utilidad:

 

for ( x=0; ( (x>3) && (x<9) ); x++ )

for ( x=0, y=4; ( (x>3) && (x<9) ); x++, y+=2)

for ( x=0, y=4, z=4000; z; z/=10)

n el segundo ejemplo se muestra la forma como múltiples expresiones pueden aparecer, siempre y cuando estén separadas por una coma ,

n el tercer ejemplo, el ciclo continuará iterando hasta que z se convierta en $0$.

 

4.2 La sentencia while

a sentencia while es otro ciclo o bucle disponible en C. Su formato es: 

while ( expresion) sentencia; 

onde sentencia puede ser una sentencia vacía, una sentencia única o un bloque de sentencias que se repetirán. Cuando el flujo del programa llega a esta instrucción, primero se revisa si la condición es verdad para ejecutar la(s) sentencia(s), y después el ciclo while se repetirá mientras la condición sea verdadera. Cuando llega a ser falsa, el control del programa pasa a la línea que sigue al ciclo.

n el siguiente ejemplo se muetra una rutina de entrada desde el teclado, la cual se cicla mientras no se pulse A:

 

main()
{
    char carac;

    carac = '
 
   
Hoy habia 19 visitantes (25 clics a subpáginas) ¡Aqui en esta página!
Este sitio web fue creado de forma gratuita con PaginaWebGratis.es. ¿Quieres también tu sitio web propio?
Registrarse gratis