introducción a la programación en c

83
Asignatura de Sistemas Operativos INTRODUCCIÓN A LA PROGRAMACIÓN EN LENGUAJE C GUÍA BÁSICA PARA PRINCIPIANTES V. 1.0 Universidad de Valladolid Segundo de Ingeniería Técnica Informática de Sistemas 1 de noviembre de 2010

Upload: cristian-tg

Post on 26-Jun-2015

109 views

Category:

Documents


0 download

DESCRIPTION

Aquí os dejo un pequeño tutorial para que parendais lo básico de Programación en C.Pero recordad, para aprender a programar lo más importante es programar por tu cuenta!!

TRANSCRIPT

Page 1: Introducción a la programación en C

Asignatura de

Sistemas Operativos

INTRODUCCIÓN A LA

PROGRAMACIÓN EN

LENGUAJE C GUÍA BÁSICA PARA PRINCIPIANTES V. 1.0

Universidad de Valladolid

Segundo de Ingeniería Técnica Informática de Sistemas

1 de noviembre de 2010

Page 2: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 1

Page 3: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 2

ÍNDICE DE CONTENIDOS

0. NOTA DEL AUTOR ................................................ 4

1. INTRODUCCIÓN .................................................... 6

2. VARIABLES .......................................................... 8

3. OPERADORES ..................................................... 12

4. OPERACIONES E/S.............................................. 18

5. CONTROL DE FLUJO ........................................... 22

6. FUNCIONES ........................................................ 28

7. VECTORES ......................................................... 34

8. PUNTEROS .......................................................... 42

9. ESTRUCTURA DE DATOS .................................... 46

10. PREPROCESADOR ................................................ 52

11. FICHEROS ........................................................... 54

12. HERRAMIENTAS ................................................. 58

APÉNDICE A ............................................................. 60

APÉNDICE B .............................................................. 62

APÉNDICE C ............................................................. 64

APÉNDICE D ............................................................. 66

APÉNDICE E .............................................................. 68

APÉNDICE F .............................................................. 70

APÉNDICE G ............................................................. 72

APÉNDICE H ............................................................. 76

BIBLIOGRAFÍA .......................................................... 82

Page 4: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 3

Page 5: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 4

Capítulo 0 – Nota Del Autor

En algunos casos el código que se muestra como ejemplo no es directamente

codificable y ejecutable.

Por razones de ahorro de espacio y legibilidad se han eliminado ciertas porciones de

código.

En caso de dudas sobre las estructuras y funciones que aquí se referencian, consulte la

bibliografía o el manual en línea, por ejemplo:

# man fprintf

Cada apartado de este curso está dividido en dos zonas:

Apuntes de teoría con ejemplos y cuestiones teóricas.

Ejercicios propuestos. Aquí hay dos tipos de enlaces:

Ficheros descargables, con código para compilar y observar su

funcionamiento.

Guiones de laboratorio aparecidos en cursos anteriores, en los que se

ponen en práctica los conceptos desarrollados en el apartado teórico.

En cada ejercicio propuesto se indica su grado de dificultad

(* = fácil, ** = media, *** = difícil).

Realice los guiones propuestos, y no pase al siguiente apartado sin haber respondido

las preguntas y realizado los ejercicios.

Page 6: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 5

Page 7: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 6

Capítulo 1 – Introducción

Historia

1967, BCPL (Basic Combined Programming Lenguage)- Martin Richards busca un

lenguaje para el diseño de Sistemas Operativos.

1970, Ken Thompson – primera versión de UNIX. Usa lenguaje B.

1972, Denis Ritchie – Lenguaje C.

o Lenguaje de alto nivel – independiente de máquina.

o Con instrucciones sencillas, próximas al código máquina.

Con la popularidad de las microcomputadoras muchas compañías comenzaron a

implementar su propio C por lo cual surgieron discrepancias entre sí.

1983, ANSI (American National Standars Institute) estableció un comité para crear

una definición no ambigua del lenguaje C e independiente de la máquina que pudiera

utilizarse en todos los tipos de C.

El primer programa

Un programa siempre ha de estar documentado. Use /* Comentarios */

Cada sentencia termina en ;

En lenguaje C un programa es una serie de llamadas a funciones (devuelve un nuevo dato).

Todo programa C debe contener la función especial int main(). Ésta es la función

principal del programa, o lo que es lo mismo, la función por la que empezará a

ejecutarse el programa.

A la hora de identificar variables y funciones es importante tener en cuenta que el

lenguaje C distingue Mayúsculas y minúsculas

Los ficheros de cabecera (ficheros acabados en .h y que se incluyen en un programa C

mediante la palabra #include), contienen, como se verá más adelante, prototipos, es

decir, declaraciones y/o definiciones de variables, constantes, funciones, etc.

El cuerpo de una función va entre llaves {}.

La palabra clave return marca el final de una función. Cuando se ejecuta esta

sentencia, el control pasa a la función que llamó a la que ahora finaliza. Si se trata de

la función principal (función main), el control pasa al intérprete de comandos del

Sistema Operativo.

Page 8: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 7

Compilación

El lenguaje C habitualmente es compilado, con lo que el código fuente se debe traducir a

código máquina a través del compilador. Dependiendo del Sistema Operativo y la plataforma

de desarrollo, se tendrán distintos compiladores. En máquinas tipo UNIX / LINUX los

compiladores más habitualmente usados son el cc o el gcc. La sintaxis de estos compiladores

es la siguiente:

cc nombre_fuente.c –o nombre_ejecutable (-Wall indica si hay algún warning)

Opciones: -ansi, -l ... (ver man cc ó man gcc).

Una opción de uso frecuente es la –l que seguida por una letra indica al compilador aquellas

bibliotecas de funciones que deben ser incluidas, cuando estás no son la estándar. Es habitual

usar en programas funciones matemáticas como seno, coseno, potencias, etc. Estas funciones

están definidas en la biblioteca matemática, que para que sea incluida en la compilación debe

añadirse a la línea de compilación la opción –lm.

Ejercicio/Ejemplo. Mi primer programa C. Mediante un editor escribe el siguiente código,

compílalo y ejecútalo.

Responde a las siguientes preguntas:

1. ¿Qué hace la función printf?. Cambia el valor del argumento a esa función (valor

dentro del paréntesis) y examina qué efectos tiene al compilar y volver a ejecutar el

programa.

2. Cambia el valor del argumento del comando return por otro entero. Vuelve a

compilar el programa y ejecutarlo. Tras esto, Y SIN EJECUTAR NINGÚN OTRO

COMANDO ENTRE MEDIAS, ejecuta el siguiente comando UNIX: “echo $?”.

¿Cuál es el significado del argumento de la función return.

3. Cambia el nombre a la función main e intenta compilar el programa. ¿Por qué da

error?

Ejercicio/Ejemplo. Al compilar el siguiente programa verás que da error. Contiene un error

de sintaxis muy común al escribir programas en C. ¿Cuál es el error?

/* Programa con error */

#include <stdio.h>

int main( void )

{

printf( "Hola a todos!\n" )

return 0;

}

Page 9: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 8

Capítulo 2 – Variables

Introducción

El lenguaje C maneja datos tanto numéricos (enteros y reales) como de tipo carácter. En este

último caso hay que diferenciar entre los caracteres tratados de manera individual, y las

cadenas de estos. En la siguiente tabla podemos ver un ejemplo de lo expuesto (las comillas

que aparecen en los tipo carácter y cadenas son necesarias al usar este tipo de datos en C).

Enteros 19 -152

Reales 1.4 -156.2 19.13e+12

Carácter `a` `3` `\n`

Cadenas "Hola Mundo" "Adiós\n"

Tipos de datos

Una variable de tipo entero puede ser:

Con signo

(complemento a 2)

Char Short Int long

Sin signo

(binario natural)

unsigned char unsigned short Unsigned int unsigned

long

Tamaño (bytes)

(orientativo. Es

dependiente de la

máquina)

1 2 4 4

Ejercicio. Calcular con lápiz y papel el rango de cada tipo de dato entero.

En la siguiente tabla aparecen los distintos formatos de variables de tipo real. Estos datos se

almacenan en punto flotante, siguiendo, generalmente, la norma IEEE 754

Tipo Float double long double

Tamaño (bytes) 4 8 16 (ansi)

Page 10: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 9

Ejercicio/Ejemplo. Uso de variables. Mediante un editor escribe el siguiente código,

compílale y ejecútale

/* Primera aproximación al uso de variables */

#include <stdio.h>

int main( void )

{

/* Ejemplo de declaración de variable sin asignación */

int a, b, UnEntero1;

char c;

unsigned long x;

float f;

/* Declaración y asignación */

int d=-52;

unsigned char UnaLetra=„a‟;

double Grande=-141.255e+7;

/* Ejemplo de asignación de valor a variables */

a=23;

c=‟s‟;

f=3.78;

printf (“valor asignado a la variable a: %d a c: %c a f: %f y a Grande: %lf\n”, a, c,

f, Grande);

printf (“Valor en decimal de la variable UnaLetra: %d. Valor interpretada como

carácter: %c\n”, UnaLetra, UnaLetra);

/* Ejemplo de asignación en otros sistemas de numeración */

a=0x050; /* Constante en hexadecimal */

b=0311; /* Constante en octal */

printf (“Valor de a en hexadecimal: %x y en decimal: %d. Valor de b en octal: %o

y en decimal: %d\n”, a, a, b, b);

return 0;

}

Responde a las siguientes preguntas:

1. ¿Cuál es la función de la letra que está a continuación del símbolo “%” en printf?

2. Viendo lo mostrado por el segundo printf (el que muestra la variable “UnaLetra”,

¿Cuál es el valor ASCII en decimal del carácter „a‟?

3. Añade una línea que, usando la función printf, muestra por pantalla el carácter

correspondiente al valor ASCII en hexadecimal 50 (último valor de la variable a).

Page 11: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 10

Ejercicio/Ejemplo. Al compilar el siguiente programa dará error. Contiene otro error típico

en programas C. Buscar y corregir el error.

/* Programa con error */

#include <stdio.h>

int main( void ) {

/* Ejemplo de declaración de variable sin asignación */

int a, b, UnEntero1;

Char c;

unsigned long x;

float f;

a=23;

c=‟s‟;

f=3.78;

printf (“valor asignado a la variable a: %d a c: %c a f: %f y a Grande: %lf\n”, a, c,

f, Grande);

return 0;

}

Declaración de variables

C es (en general) un lenguaje compilado, y todas las variables han de ser declaradas antes de

ser usadas. A la hora de identificar a una variable (darle nombre) hay que tener en cuenta las

siguientes reglas muy simples:

Se puede usar cualquier combinación de letras (A-Z, a-z) y números (0-9). También se

pueden usar los siguientes caracteres “-“ y “_”

Los dígitos numéricos nunca debe estar al principio del nombre.

No se deben usar acentos ni ñ.

Se distingue entre mayúsculas y minúsculas. Por ejemplo dos variable llamadas Pepe

y pepe, serán diferentes.

Page 12: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 11

Page 13: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 12

Capítulo 3 – Operadores

Tipos

En el lenguaje C podemos distinguir los siguientes tipos de operadores:

De asignación: Asigna un valor a una variable. Forma del operador: “=”. Ejemplos de

uso:

Int a=45;

b = „a‟;

Aritméticos: Sirven para crear expresiones aritméticas. operadores: suma (+), resta (-

), producto (*), cociente (/) y módulo (%). Ejemplos de uso:

var1 = 3.5 * a;

Hola = b * 7.0 + 5.7;

Autoincremento/autodecremento: Dada la frecuencia de uso de variables que se

incrementan o decrementan en una unidad, estos operadores surgen para simplificar la

escritura de ese tipo de operaciones. Operadores: autoincremento (++), incrementa en

una unidad el valor de la variable y autodecremento (--), decrementa en una unidad el

valor de la variable. Pueden ir a la derecha o a la izquierda de la variable. Ejemplo y

explicación de su funcionamiento:

a++; ó ++a; es lo mismo que escribir: a = a +1;

a--; ó --a; es lo mismo que escribir: a = a – 1;

Ejercicio 6. Buscar cuál es la diferencia de poner los operadores a la derecha o a la

izquierda de la variable

Operadores relacionales: Permiten comparar variables y/o constantes. Devuelven un

valor lógico: verdadero o falso. Operadores: igual (==), distinto (!=), mayor (>),

menor (<), mayor o igual (>=) y menor o igual (<=)

Ejercicio/Ejemplo 7. En realidad los operadores relacionales devuelven un entero, cuyo

valor se interpreta como falso si el valor devuelto es 0 y verdadero si el valor devuelto es

distinto de 0. Con el siguiente programa se puede comprobar esto:

/* Ejemplo de valor entero devuelto por los operadores relacionales */

#include <stdio.h>

Page 14: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 13

int main( void ) {

printf (“Valor devuelto si falso: %d, valor devuelto si verdadero: %d\n”, 6<5,

6!=5);

return 0;

}

Operadores lógicos: Permiten crear expresiones lógicas. El valor devuelto es

verdadero o falso. A este valor devuelto se le puedo aplicar lo indicado en el punto

anterior. Operadores: and (&&), or (||) y not (!). Normalmente se usan para concatenar

expresiones creadas con los operadores relacionales. Ejemplo:

a <= 5 || a > 3 Esta expresión será verdad si la variable a (suponiendo que sea

entera) vale 4 ó 5.

Operadores binarios: Sirven para operaciones de “bajo nivel”, es decir, permiten

operar con los datos en binario. Operadores:

o Desplazamiento aritmético en complemento a 2 a la derecha: C >> n. Donde C en

la variable/constante a desplazar y n es el número de desplazamientos. Recordar

que un desplazamiento a la derecha de una cantidad entera supone su división por

2.

o Desplazamiento aritmético en complemento a 2 a la izquierda: C << n. Donde C

en la variable/constante a desplazar y n es el número de desplazamientos.

Recordar que un desplazamiento a la izquierda de una cantidad entera supone su

multiplicación por 2.

o Operación lógico AND: &. Recordar que la operación AND sobre dos

combinaciones binarias implica la realización de la operación AND sobre los

valores de cada posición.

o Operación lógico OR: |. Recordar que la operación OR sobre dos combinaciones

binarias implica la realización de la operación AND sobre los valores de cada

posición.

o Operación lógico NOT: ~. En este caso es un operador unario, y su resultado es el

complemento del operando. Ejemplo: ~variable.

Page 15: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 14

Ejercicio/Ejemplo 8. El siguiente programa sirve para recordar de Fundamentos de

Informática II algunas de las utilidades de estos operadores:

/* Ejemplo de uso de operadores binarios*/

#include <stdio.h>

int main( void ) {

int a=-50, b;

/* Emplo de multiplicación/división rápida por potencias de 2 */

printf (“Resultado de desplazar a dos posiciones a la derecha: %d\n”, a>>2);

printf (“Resultado de desplazar a cuatro posiciones a la izquierda: %d\n”, a<<4);

/* Comprobación de si el dígito cuarto (empezando por la derecha) de la variable a

vale 0 ó 1 */

b=8;

if ( (b & a) == 0) {

printf(“el dígito vale 0\n”);

}

else { printf(“el dígito vale 1\n”);

}

return 0;

}

Otros operadores

o Operador coma (“,”): Sirve para agrupar expresiones: expr1,expr2,expr3. El

resultado es que se evalúan todas las expresiones y se devuelve como valor el

resultado de la expresión más a la derecha. Su uso más típico es en sentencias for

(sentencia que se verá más adelante), por ejemplo:

for (a=0,b=3; a<=50; a++,b++)

o Operador “?” o condicional: Su sintaxis es: expresión ? expresión1 :

expresión2. Si expresión es verdad se evalúa y devuelve expresión1, en caso

contrario se evalúa y devuelve expresión2. Ejemplo:

max = a>b ? a : b ;

Page 16: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 15

Conversión de tipos (casting).

Cuando en una expresión aritmética se mezclan variables de distintos tipos, el compilador de

C realiza una conversión implícita al tipo de mayor longitud/rango, siguiendo la siguiente

jerarquía:

int < unsigned < long < unsigned long < float < double.

Por ejemplo si multiplicamos un entero por un real, el compilador realizará una conversión de

tipo entero a real, y la multiplicación se realizará entre dos cantidades reales. Lo mismo

ocurre si el resultado de una expresión es de un tipo, y la asignación ser realiza a una variable

de tipo distinto. Sin embargo, el resultado de estas conversiones implícitas no siempre es el

deseado, por eso es aconsejable que sea el propio programador el que realice, en casos como

los comentados, la conversión de manera explícita. Para esto existe el operador de cambio de

tipo. La sintaxis es la siguiente:

(nuevo_tipo) expresión/variable.

Ejercicio/Ejemplo 9. El siguiente programa sirve para ver el problema que puede surgir si se

deja la conversión de tipo al compilador:

/* Ejemplo de conversión implícita/explícita de tipo*/

#include <stdio.h>

int main( void ) {

int a=5, b=3;

float f1, f2;

f1 = a / b; /* el resultado del cociente es un entero, que es convertido a float en la

asignación a f1 */

f2 = (float) a / (float) b; /* el cociente se realiza entre números reales */

printf(“Resultado conversion implicita: %f Resultado conversion explicita:

%f\n”,f1, f2);

return 0;

}

Page 17: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 16

Precedencia.

La precedencia o prioridad aplicada a los operadores a la hora de calcular una expresión es la

siguiente, ordenada la lista de mayor a menor prioridad (algunos operadores serán vistos más

adelante):

() [] -> .

! ~ ++ -- - (type) * & sizeof (todos son unarios)

* / %

+ -

<< >>

< <= > >=

== !=

&

^

|

&&

||

?:

= += -= *= /= %= ^= &= |=

,

Page 18: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 17

Page 19: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 18

Capítulo 4 - Operaciones Entrada-Salida

En esta sección vamos a ver las funciones más importantes en el lenguaje C para la entrada y

salida de datos de y hacia la entrada y la salida estándar, respectivamente, que, recordemos,

que son el teclado y el monitor.

Operaciones sencillas de E/S.

Las funciones que veremos en esta sección permiten la entrada/salida de caracteres. Ambas

están definidas en el fichero de cabecera stdio.h, por lo que este fichero deberá ser incluido en

el programa.

· Función de entrada de carácter: getchar (). Obtiene un carácter de la entrada estándar,

siendo este carácter el valor devuelto. El carácter tecleado no es “capturado” por esta función

hasta que no se pulsa retorno de carro. Es importante tener en cuenta si se utilizan varias

funciones getchar() seguidas que el retorno de carro es tratado como un carácter más (lo

veremos en el ejemplo).

· Función de salida de carácter: putchar (char c). Muestra el carácter c por la salida

estándar.

Ejercicio/Ejemplo. El siguiente programa sirve para ver el problema que puede surgir si se

deja la conversión de tipo al compilador:

/* Ejemplo de E/S de caracteres*/

#include <stdio.h>

int main( void )

{

char a, b;

printf(“Teclea un caracter y después pulsa retorno de carro (return)\n”);

a = getchar();

getchar(); /* para “capturar el retorno de carro */

printf(“Teclea otro caracter y después pulsa retorno de carro (return)\n”);

b = getchar();

printf (“los caracteres introducidos son: %c y %c\n”, a, b);

return 0;

}

Responde a las siguientes preguntas:

1. Elimina del programa anterior la línea “getchar(); /* para “capturar el retorno de

carro */” (puedes hacerlo comentando la línea sin borrarla) y vuelve a compilarlo y

ejecutarlo. ¿Por qué no nos deja introducir el segundo carácter? ¿Cuál es el valor de

la variable b?

Page 20: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 19

Ejemplo. El siguiente programa muestra un ejemplo de captura de varios caracteres

tecleados de manera seguida:

/* Ejemplo 2 de E/S de caracteres*/

#include <stdio.h>

int main( void )

{

char char1, char2, char3, char4;

printf(“Teclea una palabra de cuatro caracteres y después pulsa retorno de carro

(return)\n”);

char1 = getchar();

char2 = getchar();

char3 = getchar();

char4 = getchar();

printf (“La palabra introducida es: %c%c%c%c\n”, char1, char2, char3, char4);

return 0;

}

Operaciones de E/S con formato

Las funciones que veremos en esta sección permiten la entrada/salida de cualquier tipo de

variable. El tipo es especificado como argumento de la función. Ambas están definidas en el

fichero de cabecera stdio.h, por lo que este fichero deberá ser incluido en el programa.

Función int printf(const char *format). Imprime por la salida estándar una secuencia

de caracteres cuya estructura está definida en format. Se permite dar salida a cualquier

tipo de dato predefinido. format tiene la estructura de una cadena de caracteres normal

pero admite además caracteres de conversión (%letra) para indicar qué tipo de dato se

ha de imprimir. La estructura de una cadena de formato es:

%[flags][.width][.prec][F|N|h|l]type

Donde type es un carácter de conversión. El campo flag afecta al tipo de justificación; width

es la anchura utilizada para imprimir, .prec es la precisión (número de decimales) si el dato

a imprimir es un número en coma flotante. El último campo opcional afecta a la

interpretación del argumento (se deja al estudiante buscar el significado de este campo). Los

tipos de datos a imprimir (campo type) son los siguientes:

%c Caracter

%d Entero decimal

%ld Entero largo (long int)

%e Flotante se representa con exponente

%f Flotante se representa sin exponente

Page 21: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 20

%lf double

%i entero decimal, hexadecimal u octal

%g Menor entre %e y %f

%o Entero octal, sin el cero inicial

%u Entero decimal sin signo

%x Entero representado en hexadecimal sin 0x

%s Strings (cadenas de caracteres).

int scanf(const char *format, ...). Permite la entrada de datos de forma estructurada

por teclado. En la cadena de formato se pueden poner todos los caracteres de

conversión (%) de la tabla anterior. En el ejemplo se explicará más detenidamente la

sintaxis de esta función.

Ejemplo. El siguiente programa muestra un ejemplo de uso de scanf y printf:

#include <stdio.h>

int main( void )

{

int i;

double f;

scanf (“%d %lf”, &i, &f);

printf (“i=%d f=%lf\n”,i, f);

return 0;

}

Explicación de la sintaxis de scanf

Los argumentos a esta función se pueden dividir en dos partes:

A la izquierda de la coma y entre comillas la cadena de caracteres donde se

indica el tipo de datos a leer de teclado, especificados de la misma manera que

la usada en printf. El número y tipos a especificar puede ser cualquiera.

A la derecha de la coma van las variables donde guardar los valores leídos,

más concretamente, hay que especificar la dirección de memoria central

donde se almacenan estas variables. Esta es una consideración muy importante

a tener en cuenta a la hora de usar scanf. Para obtener la dirección de memoria

donde se almacena una variable se usa el operador unario &, operador que se

estudiara en profundidad más adelante cuando se hable de punteros. Este

operador devuelve la dirección de memoria donde se almacena la variable

especificada a su derecha. En el caso del ejemplo, &i devuelve la dirección de

memoria donde se almacena la variable i. Igual para &f.

¡Un espacio en blanco significa terminar la lectura de caracteres!

Page 22: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 21

Page 23: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 22

Capítulo 5 - Control de Flujo

Sentencia if

Permite la ejecución condicional de un conjunto de sentencias. Su sintaxis es:

if (condición)

Sentencia simple/bloque_1

else

Sentencia simple/bloque_2

Si condición es verdad (recordemos: valor devuelto por la expresión lógica distinto de 0), se

ejecuta Sentencia simple/ bloque_1, si es falso (recordemos: valor devuelto por la expresión

lógica 0), se ejecuta Sentencia simple/ bloque_2. La sentencia else es opcional.

Ejemplo. Ejemplo de sentencia if

#include <stdio.h>

int main( void ) {

int valor1, valor2;

printf (“Introduzca dos valores enteros distintos entre sí\n”);

scanf (“%d %d”, &valor1, &valor2);

if (valor 1 > valor 2)

printf (“El primer dato es mayor que el segundo\n”);

else

printf (“El primer dato es menor que el segundo\n”);

return 0;

}

Page 24: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 23

Bucle while (o ó mas veces)

Permite la ejecución iterativa de un conjunto de sentencias mientras se cumpla una

determinada condición. La condición es cualquier expresión lógica. Su sintaxis es:

while (condición)

Sentencia simple/bloque

Bucle do – while (1 ó mas veces)

Similar al bucle while pero el conjunto de sentencias se ejecuta al menos una vez. Su sintaxis

es:

do

Sentencia simple/bloque

while (condición)

Bucle for (x veces prefijadas)

Permite la ejecución iterativa de un conjunto de sentencias. Su sintaxis es:

for (inic; perman; actualiz)

Sentencia simple/bloque

Donde:

· inic es una expresión que sólo se ejecuta una vez al principio del bucle. El

bucle for suele utilizarse en combinación con un contador. Un contador es una

Page 25: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 24

variable que lleva la cuenta de las veces que se han ejecutado las instrucciones sobre las

que actúa el comando for. Por tanto inic suele contener una expresión que nos permite

inicializar ese contador.

· perman es la expresión que nos indica cuando debe finalizar el

bucle, por tanto se tratará de una expresión condicional. Su

interpretación sería algo como: repite la sentencia (o sentencias) mientras se

cumpla perman. Esta expresión se evaluará en cada ciclo del bucle para determinar si

se debe realizar una nueva iteración. Es MUY IMPORTANTE tener en cuenta que

perman se evalúa al principio del bucle, y no al final. Por tanto es posible no ejecutar

el bucle ninguna vez.

· actualiz exp3 es una expresión que se ejecuta al final de cada iteración. Puesto que

como ya se ha indicado el bucle for se utiliza junto a un contador, actualiz,

en general, contiene una instrucción que actualiza la variable contador.

Ejemplo. El siguiente programa cuenta hasta 10, empezando por 0:

#include <stdio.h>

int main( void ) {

int cont;

for (cont=0; cont <=10; cont++)

printf(“Valor del contador: %d\n”, cont);

}

Ejemplo. Ejemplo anterior realizado con un bucle while:

#include <stdio.h>

int main( void ) {

int cont;

cont = 0;

while (cont <=10) {

printf(“Valor del contador: %d\n”, cont);

cont ++; }

return 0; }

Page 26: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 25

Saltos incondicionales

Las siguientes sentencias permiten la realización de saltos incondicionales en un

programa C: break y continue.

La ejecución del primero de ellos, continue, implica que se reevalúe la

condición de salida del bucle, es decir, después de ejecutar continue la

siguiente instrucción que se ejecutará será el for o el while.

Ejemplo. Ejemplo de uso de la función continue. Este programa lee desde teclado 10

números cuyo valor tiene que estar entre 1 y 100, si no es así se le vuelve a pedir al usuario

que introduzca un valor, descartando el introducido no válido.

#include <stdio.h>

int main( void )

{

int n;

int cont=0;

do

{

printf ("\nIntroduce un número entre 1 y 100:");

scanf ("%d",&n);

if ((n<1)||(numero>100))

continue;

cont++;

} while (cont<50);

return 0;

}

La función de break hace que la ejecución del programa continúa en la línea

siguiente al bucle, es decir, tras su ejecución se abandona el bucle y se continúa la

ejecución en la línea inmediatamente siguiente al éste.

Ejemplo. Ejemplo de uso de la función break. Este programa lee desde teclado valores

numéricos y los muestra por pantalla, salvo que el número introducido sea el 2.

#include <stdio.h>

int main( void )

{

int n;

do

{

printf ("\nIntroduce un número entero:");

scanf ("%d",&n);

Page 27: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 26

if (n == 2)

break;

printf (“El número introducido es: %d\n”, n);

} while (1);

return 0;

}

Condicional múltiple switch case

Es una sentencia de selección múltiple, que compara sucesivamente el valor de una expresión

con una lista de constantes enteras o de caracteres. Cuando se encuentra una correspondencia,

se ejecutan las sentencias asociadas con la constante. La sintaxis de esta sentencia es la

siguiente:

switch (expresión)

{

case constante1:

Sentencia/s

break;

· · ·

case costanten:

Sentencia/s

break;

· · ·

[default:

Sentencia/s]

}

Si el valor de expresión coincide con cualquiera de las constantes a la derecha de una

sentencia case, entonces se ejecutan las sentencias que estén a continuación de ese “case”

hasta llegar a la sentencia break. Un caso especial es la sentencia default. Ésta es opcional, si

aparece la sentencias que están a continuación de ella se ejecutarán si el resultado de

expresión no coincide con ninguna de las constantes anteriores. La comprobación de valores

se realiza de arriba abajo, es decir, el resultado de expresión primero se comprueba con

constante1, después con constante2 y así sucesivamente hasta llegar al final.

No puede haber dos constantes en el mismo switch que tengan los mismos valores. Por

supuesto que una sentencia switch contenida en otra sentencia switch pude tener constantes

que sean iguales.

Si se utilizan constantes de tipo carácter en la sentencia switch, se convierten

automáticamente a sus valores enteros siguiendo el código ASCII.

Page 28: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 27

Ejemplo. Ejemplo de uso de la función switch para crear un menú.

#include <stdio.h>

int main( void )

{

int n;

do {

printf (“introduzca un valor entero entre 1 y 3:”);

scanf ("%d",&n);

switch (n)

{

case 1:

printf(“Ha escogido la opción 1\n”);

break;

case 2:

printf(“Ha escogido la opción 2\n”);

break;

case 3:

printf(“Ha escogido la opción 3\n”);

exit (3);

break;

default:

printf(“Opción no válida\n”);

}

} while (1)

return 0;

}

Responde a las siguientes preguntas:

1. ¿Qué hace la función exit? ¿Qué significa su argumento (valor a su derecha entre

paréntesis? ¿Se podría eliminar la sentencia break que sigue a “exit (3)”?

2. ¿Qué pasa si se quita la sentencia break asociada a “case 1:”?

Page 29: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 28

Capítulo 6 – Funciones

Definición de Función

En el lenguaje C una función se define de la siguiente manera:

tipo nombre (tipo param1, tipo param2, ...)

{

/*cuerpo de la función*/

...

[return expresión;]

}

Donde:

tipo es tipo del dato que devuelve. Si no devuelve nada se declarará de tipo “void”.

Sólo se pueden devolver tipos asignables: enteros, reales, punteros, estructuras y void.

Si no se especifica el tipo, se supone que es entero.

nombre es el nombre con que la función es identificada (mayúscula primera letra).

Parámetros de la función. Es una lista de nombres de variables separados por comas

con sus tipos asociados, que recibirán valor en el momento de llamar a la función. Los

paréntesis siempre deben aparecer, aunque la función no tenga argumentos. Estas

variables sólo estarán definidas dentro de la función, es decir, son locales a la función,

salvo que hayan sido definidas como globales (ver al final de este apartado), creándose

al comienzo de la ejecución de la función y destruyéndose al finalizar ésta. Esto es

aplicable a cualquier otra variable declarada dentro de la función, excepto si se

declaran como static (esta sentencia debe aparecer antes del tipo de la variable). En

este caso el compilador no las destruye y guarda su valor para la próxima llamada,

aunque la variable sigue teniendo limitado el ámbito al interior de la función.

La sentencia return es opcional, sólo debe aparecer si la función retorna un valor.

Puede aparecer en cualquier punto del cuerpo de una función.

En C no se permite la definición anidada de funciones, es decir, definir una función dentro de

otra. Si se permite la recursividad.

Una variable es global cuando se declara fuera de una función, y se puede utilizar en todo el

programa desde el punto de la declaración. Todas las variables usadas en los ejemplos

mostrados en estos apuntes son locales, es decir, declaradas dentro de un bloque de

sentencias, y su ámbito de aplicación es dentro del bloque en que son declaradas. No es

aconsejable el uso de variables globales.

Page 30: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 29

Declaración de una Función

Toda función debe ser declarada antes de ser definida. La forma de declarar una función es la

siguiente:

tipo nombre (tipo param1, tipo param2, ...);

La declaración de una función de esta forma se llama prototipo.

Las funciones son siempre globales, de manera que su declaración debe ser realizada al

principio del programa; si la primera función definida en éste es la main(), antes de esta

definición. La declaración puede evitarse si la función es definida antes de ser invocada, sin

embargo, es aconsejable declarar al comienzo del programa los prototipos de las funciones

que vamos a definir, incluyendo comentarios sobre su finalidad.

Llamadas a funciones

Las funciones pueden ser llamadas desde cualquier punto de un programa.

La llamada de una función se produce mediante el uso de su nombre en una sentencia,

pasando una lista de argumentos que deben coincidir en número y tipo con los especificados

en la declaración, en caso contrario se produciría una conversión de tipos cuyos resultados

pueden no ser los esperados. En general, los parámetros se pueden pasar por valor y por

referencia, usando en este caso punteros (dirección de memoria donde se almacena la

variable), que serán vistos más adelante. En este último caso será posible modificar el valor

de la variable usada en la llamada.

Page 31: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 30

Ejemplo. Ejemplo de uso de funciones donde es obligatorio la declaración

#include <stdio.h>

/* Prototipo de la función */

int Maximo(int var1, int var2); /*Devuelve el mayor de var1 y var2 */

/* Función principal */

int main (void) {

int i = 3, j = 5;

printf (“Maximo (%d, %d) = %d\n”, i, j, Maximo (i,j));

return (Maximo (i, j));

}

/* Definición de la función */

int Maximo (int a, int b)

/* Esto también se podría hacer:

int Maximo (a,b)

int a,b; */

{

if (a < b)

return (b);

else

return (a);

}

Page 32: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 31

Ejemplo. Ejemplo anterior pero definiendo la función de manera que no sea necesaria su

declaración.

#include <stdio.h>

/* Definición de la función */

int Maximo (int a, int b)

/* Esto también se podría hacer:

int Maximo (a,b)

int a,b; */ {

if (a < b)

return (b);

else

return (a);

}

/* Función principal */

int main (void) {

int i = 3, j = 5;

printf (“Maximo (%d, %d) = %d\n”, i, j, Maximo (i,j));

return (Maximo (i, j));

}

Page 33: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 32

Ejemplo. Ejemplo de función tipo void y sin parámetros

#include <stdio.h>

#include <stdlib.h>

/* Declaración de la función */

void suerte ();

/* Función principal */

int main (void) {

int i;

for (i=0; i<10; i++)

suerte();

return 0;

}

/* Definición de la función */

void suerte () {

int i;

i= 1 + (int) (10.0 * rand() / (RAND_MAX + 1.0));

/* La constante RAND_MAX esta definida en el fichero stdlib.h */

printf (“Tu número de la suerte es %d\n", i);

}

Page 34: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 33

Ejercicio/Ejemplo. Ejemplo error típico en el uso de funciones

#include <stdio.h>

/* Prototipo */

void Cambia (int var1, int var2);

int main () {

int i=1, j=2;

Cambia (i, j);

printf (“i=%d, j=%d”, i, j);

return 0;

}

/* Definición */

void cambia (int i, int j) {

int tmp;

tmp=i;

i = j;

j = tmp;

}

Responde a la siguiente pregunta:

1. ¿Por qué no se han intercambiado los valores de las variables i y j tras la ejecución

de la función Cambia() en main()?

Page 35: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 34

Capítulo 7 – Vectores

Conceptos generales

Un vector es una asignación contigua de memoria donde se almacena una colección de datos

todos del mismo tipo.

La forma de declarar vectores en C es la siguiente:

cualificador tipo nombre[expresión][expresión]…;

Donde expresión es un valor constante.

Se puede realizar la asignación en el momento de la declaración de la siguiente

manera:

cualificador tipo nombre[expresión][expresión]... ={valor, ...};

Donde valor también tiene que ser una constante. Si en la declaración se realiza la

asignación se puede eliminar la expresión.

No se comprueba la longitud del vector a la hora de acceder a él. Es

responsabilidad del programador controlar los accesos fuera de rango, ya que no

siempre genera un error en la ejecución. Este es un motivo de error muy típico al

realizar programas C.

La forma de hacer referencia o acceder a un elemento del vector es:

nombre[expresión][expresión]...

Donde expresión es una constante que se denomina índice, e indica el elemento del

vector al que queremos acceder. Este índice es un entero positivo que comienza por 0,

y su valor máximo será n-1 con n el número de elementos de cada “dimensión” del

vector.

Ejemplo. De uso de vectores.

#include <stdio.h>

int main () {

int x[5], i;

x[0] = 1;

for (i=1; i<5; i++)

{

printf (“Dame el valor %d del vector:”, i);

Page 36: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 35

scanf (“%d”, &x[i]);

}

printf(“Valores del vector: %d %d %d %d %d %d\n”, x[0],x[1],x[2],x[3],x[4]);

return 0;

}

En la siguiente tabla se muestra la relación entre elemento del vector y posición de memoria

que ocupa.

Un vector de datos enteros: int x[5]; (Cada int ocupa 4 bytes)

Dirección de memoria Contenido

m x[0]

m+4 x[1]

m+8 x[2]

m+12 x[3]

m+16 x[4]

Ejemplo. De error en el uso de vectores, al acceder fuera de rango.

#include <stdio.h>

main () {

int a[3];

a[10000] = 41;

printf (“%d\n”, a[10000]);

}

Page 37: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 36

Cadenas de caracteres

Las cadenas de caracteres son vectores de datos tipo char, con la característica adicional de

que acaban en el carácter nulo „\0‟. Si se da valor al número de elementos de la cadena en su

declaración habrá que tener en cuenta este carácter adicional. Por ejemplo para guardar una

cadena de 10 caracteres, se debe reservar espacio para 11.

Ejemplo. De uso de cadenas de caracteres.

#include <stdio.h>

int main () {

char cad1[]=”hola”, cad2[20];

printf (“Introduce una cadena de menos de 19 caracteres:”);

scanf (“%s”, &cad2[0]);

//scanf con %s introduce automáticamente el carácter „\0‟ tras el último carácter de

la cadena tecleada

printf(“cad1: %s cad2: %s\n”, cad1, cad2);

// printf con %s solo muestra los caracteres del vector desde el índice 0, hasta que

encuentre el carácter „\0‟

return 0;

}

No se pueden hacer asignaciones del tipo:

cad2="hola mundo";

Hay muchas funciones de biblioteca estándar para tratarlas. Por ejemplo, para asignar valor a

una cadena tras su declaración se puede usar la función strcpy (para su uso hay que incluir en

el programa el fichero de cabecera string.h):

strcpy (cad2, "hola mundo");

También la función strcmp que compara elementos sucesivos de dos cadenas, hasta que

encuentra dos elementos distintos, o hasta que se acaban las cadenas. Devuelve: valor

negativo si primera menor que la segunda (valor lexicográfico), un cero si son iguales o

un valor positivo si la primera es mayor que la segunda.

strcmp (info.cadena,”hola”);

Ya hemos visto funciones que permiten la captura desde entrada estándar (sscanf) o muestran

en la salida estándar (printf) cadenas de caracteres. Aquí vamos a añadir dos que pueden

resultar útiles:

Page 38: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 37

char *gets(char *s). Lee una línea de la entrada estándar (stdin) y la guarda en la

dirección indicada en el puntero a cadena s, hasta que se encuentre bien un caracter

terminador nueva-línea, bien EOF (End Of File, constante que indica el final de

fichero definida en stdio.h). Añade automáticamente el carácter „\0‟ al final de la

cadena leída. Devuelve s en caso de éxito o NULL en caso de error o cuando se llegue

al final del fichero mientras que no se haya leído ningún caracter.

int puts(const char *s) Escribe en la salida estándar la cadena apuntada por s y un

retorno de carro. Devuelve un número no negativo si acaban bien, o EOF en caso de

error.

Vectores y punteros

El nombre del vector es un puntero al primer elemento del vector. Esta propiedad ya

ha sido usada en varios de los ejemplos anteriores. Ya que determinadas

funciones necesitan que se especifique el vector mediante el puntero a su primer

elemento. Un ejemplo de esto es printf cuando el dato a imprimir es una cadena (%s).

Ejemplo. Vamos a modificar el ejemplo del primer apartado de esta sección

(características generales) usando en scanf la relación entre punteros y vectores

indicada.

#include <stdio.h>

int main () {

int x[5], i;

x[0] = 1;

for (i=1; i<5; i++) {

printf (“Dame el valor %d del vector:”, i);

scanf (“%d”, x+i); //Recordar la aritmética de punteros

}

printf(“Valores del vector: %d %d %d %d %d %d\n”, x[0],x[1],x[2],x[3],x[4]);

return 0;

}

Page 39: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 38

Cuando se trabaja con cadenas de caracteres la expresión “cadena” (aquí las comillas forman

parte de la expresión) devuelve un puntero a la cadena. Así, por ejemplo, printf(“%s”, hola)

dará error, ya que printf espera un puntero cuando se usa %s; la versión correcta será:

printf(“%s”, “hola”)

Vectores como argumentos a funciones

Si se quiere pasar todo un vector a una función habrá que hacerlo por referencia, es

decir, se pasa el puntero al inicio del vector, es decir, el nombre del vector, como acabamos de

ver en el aparatdo anterior. En este caso hay que tener en cuenta que la función desconoce el

tamaño del vector, por lo que será el programador el responsable de que no se acceda más allá

del límite, por ejemplo, pasando también como argumento a la función el tamaño del vector.

Argumentos a un programa c

Recordemos de UNIX, que llamamos argumentos de un comando o programa

ejecutable a cualquier cadena de caracteres que se pone a la derecha del nombre del comando.

Por ejemplo, en el comando cp fich1 fich2 los argumentos serán fich1 y fich2. El lenguaje C

permite que se puedan introducir argumentos en línea de comandos, es decir, en el momento

de la ejecución del programa. La declaración de estos argumentos se hace en la función

main(), de la siguiente manera:

main( int argc, char *argv[])

El primer argumento se suele llamar argc, pero se le puede asignar cualquier otro

nombre, y es un entero cuyo valor es el número de argumentos pasados al programa

incluyendo como argumento el nombre del propio programa. Al segundo argumento se suele

llamar argv, pero, como antes, se le puede asignar cualquier otro nombre. Este segundo

argumento es un vector de punteros a carácter. Dada la dificultad conceptual de este tipo de

vectores vamos a abandonar momentáneamente la explicación de los argumentos al programa

C, para centrarnos en los vectores de puntero.

Un puntero es un dato, y como para cualquier otro tipo de dato se permite declarar un

vector de punteros. La forma de hacerlo será:

cualificador tipo *nombre[expresión][expresión]…;

Cada elemento del vector será, en este caso, un puntero a un dato de tipo tipo, es decir,

cada elemento del vector contiene la dirección de memoria de un dato de tipo tipo.

Page 40: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 39

Ejemplo. Cálculo de la distancia, norma 1, entre dos vectores de números reales de tamaño

cualquiera.

#include <stdio.h>

#include <math.h>

int main ()

{

double *x[2], dist;

int tam_vec, i;

printf (“Dame el tamaño del vector:”);

scanf (“%d”, &tam_vec);

// Reservamos memoria

if ( (x[0]=(double *)malloc(tam_vec * sizeof(double))) == NULL)

{

printf(“ERROR al reservar memoria para el primer vector\n”);

return 1;

}

if ( (x[1]=(double *)malloc(tam_vec * sizeof(double))) == NULL)

{

printf(“ERROR al reservar memoria para el segundo vector\n”);

return 1;

}

// Pedimos datos

for (i=0; i<tam_vec; i++)

{

printf (“Dame el valor %i de primer vector:”,i);

scanf (“%lf”, x[0]+i); //x[0] es un puntero al primer elemento del vector 1

}

for (i=0; i<tam_vec; i++)

{

printf (“Dame el valor %i de segundo vector:”,i);

scanf (“%lf”, x[1]+i); //x[1] es un puntero al primer elemento del vector 2

}

// Calculamos distancia

dist = 0.0;

for (i=0; i< tam_vec; i++)

dist += fabs((x[0][i] – x[1][i]));

printf(“Distancia: %f \n”, dist);

return 0;

}

Page 41: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 40

Volvamos a los argumentos a un programa C en línea de comandos, centrando nuestra

atención en el segundo parámetro de main, el que hemos llamado argv (recordemos que le

podemos dar cualquier otro nombre. Este parámetro es un vector de punteros a char, más

concretamente, es un vector de punteros a cada una de los argumentos introducidos en la

ejecución del programa, considerando cada uno de estos (incluido el propio nombre del

programa) una cadena de caracteres.

Vemos esto mediante un ejemplo. Supongamos que ejecutamos el programa a.out con

los siguientes argumentos: a.out uno 2 3.89 “cua tro”. Pues bien, argv[0] será un puntero

(dirección de memoria del primer carácter) al nombre del programa (a.out), argv[1] será un

puntero a la cadena de caracteres introducida como primer argumento (uno), argv[2] será un

puntero a la cadena de caracteres introducida como segundo argumento (2), argv[3] será un

puntero a la cadena de caracteres introducida como tercer argumento (3.89) y argv[4] será un

puntero a la cadena de caracteres introducida como cuarto argumento (cua tro).

Ejemplo. Programa que muestra los argumentos pasados en línea de comandos

#include<stdio.h>

int main (int argc, char *argv[])

{

int i;

printf (“Número de argumentos pasados: %d\n”,argc);

for (i= 0; i < argc; i++)

{

printf (“El argumento %d vale: %s\n”,i, argv[i]);

}

return 0;

}

Es importante tener en cuenta que todos los argumentos son pasados a main() como cadenas

de caracteres. Es el programador el que tendrá que, usando las funciones adecuadas, pasar los

datos de tipo cadena al tipo que desee. Una de estas funciones es, por ejemplo, sscanf().

Ejercicio/Ejemplo. De cambio de tipo de un argumento a programa usando sscanf().

#include <stdio.h>

//Cambiamos de nombre a los parámetros a main

int main (int num_arg, char *arg[]) {

int arg2;

if ( sscanf(arg[2], "%d", &arg2) != 1) {

Page 42: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 41

fprintf(stderr,"*** ERROR en la lectura del segundo argumento. Valor leido:

%s\n", arg[2]);

exit(1);

}

. . .

}

Responde a las siguientes preguntas:

1. ¿Qué valor devuelve la función sscanf()?

2. ¿Cómo funciona fprintf? ¿A qué salida se está mandando el mensaje de error, en caso

de que se genere?

Para acabar, en la figura 1 se puede ver un ejemplo gráfico simplificado de la ubicación en

memoria de los argumentos pasados a un programa: argv será la dirección de memoria del

primer elemento del vector de punteros argv[], es decir, la dirección de memoria del elemento

argv[0]; a su vez argv[0] apunta al primer elemento (carácter) de la cadena compuesta por el

nombre del programa, es decir, argv[0] es a su vez un puntero a una cadena de caracteres. De

igual manera se razona para argv[1] y argv[2] con respecto a las cadenas introducidas como

primer y segundo argumento. Una conclusión de lo expuesto es que argv es un puntero a un

puntero, y como tal puede ser tratado.

Fig 1.- Esquema simplificado del almacenamiento en memoria de los argumentos

pasados a un programa en línea de comandos. Se supone que el programa ejecutado es:

a.out uno 1. Esta figura muestra también la relación entre punteros y vectores con

respecto a los argumentos a un programa.

Page 43: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 42

Capítulo 8 - Punteros

Conceptos generales

Los punteros son una de las herramientas más útiles, pero a la vez, complejas y

peligrosas de C. Un puntero es una variable entera sin signo que almacena la

dirección de memoria de otra variable o dato. Para ser más exactos, almacena la

dirección del primer byte que la variable ocupa en memoria. Esto es importante

tenerlo en cuenta, a la hora de entender la aritmética de punteros.

La declaración de un puntero se realiza de la siguiente manera:

[cualificador] tipo *nombre;

Donde cualificador recordemos que puede ser extern o static y es opcional, sólo será

necesario si la variable queremos que se comporte de la forma indicada para esos

cualificadores. Tipo es cualquiera de los vistos ahora y alguno que añadiremos más

adelante, e indica el tipo de la variable almacenada en la dirección de memoria

apuntada por el puntero. El carácter “*” es el que indica que la variable que estamos

definiendo es un puntero. Y, por último, nombre es el identificador de la variable

puntero.

Es importante tener en cuenta que el hecho de declarar un puntero implica que se

reservará espacio en memoria para guardar un puntero, no para el tipo de datos al que

apunta.

Ejemplo.

La declaración:

int *i;

implica que se está declarando un puntero que vamos a llamar ”i” que apunta a un

entero, es decir, la variable i contendrá una dirección de memoria central donde se

almacenará un entero;, más exactamente, contiene la dirección de memoria del primer

byte del entero almacenado. Con esta declaración se reserva espacio para almacenar “i”,

es decir, el puntero, no para almacenar el entero. Esto último se tendrá que hacer con la

declaración correspondiente, como veremos en siguientes ejemplos.

De igual manera se declararían punteros a tipos float, long, char, etc.

Operaciones con punteros

Existen sólo dos operaciones que se puedan usar con punteros: la suma y la resta. Más

concretamente las operaciones permitidas son el incremento/decremento, la suma/resta

de valores enteros y la suma/resta de punteros.

Las operaciones más útiles son el incremento/decremento, como veremos al hablar de

vectores. Cada vez que se incrementa un puntero, apunta a la posición de memoria del

siguiente elemento de su tipo base. Cada vez que se decrementa, apunta a la posición

del elemento anterior. Los punteros aumentan o decrecen la longitud del tipo de datos

a los que apuntan.

Page 44: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 43

Ejemplo. El puntero punt apunta a un float (4 bytes). Supongamos que su valor es dir.

Entonces, después de la expresión punt++; punt contiene el valor dir+4, no el dir+1.

El siguiente programa permite ver esto:

float *punt, var;

punt = &var;

printf (“Valor de punt antes de incrementar su valor: %x. Valor después: %x\n”,

punt, punt++);

Comentario: dado que un puntero es una dirección de memoria, su valor se visualiza

de manera más compacta es hexadecimal.

El valor NULL

Un valor especial que se le puede asignar a un puntero es el valor NULL (constante

definida con valor 0 en el fichero de cabecera stddef.h, fichero incluido en el stdio.h).

Un puntero al que se le asigna este valor significa que no apunte a ninguna posición de

memoria.

Operadores

Existen dos operadores especiales relacionados con punteros:

El operador “&” (dirección de). Devuelve la dirección de memoria donde está

almacenada una determinada variable. La sintaxis es: &nombre_variable. Una de las

formas de asignar valor a un puntero (iremos viendo más) es mediante el uso de este

operador, como se verá en el ejemplo.

El operador“*”. Asociado a un puntero devuelve el valor de la dirección de memoria a

la que apunta el puntero. A este proceso se le llama indirección.

Ejemplo. De uso de los operadores “&” y “*” (a partir de aquí en numerosos ejemplos sólo

mostraremos la parte de código que nos interesa, se deja para el alumno añadir las líneas

necesarias para crear un programa que pueda ser compilado).

int *i, j;

j=5;

i=&j; // Asignamos a j la dirección de i

printf (“dirección de j (en hexadecimal)=%x\n”,i);

// Acceso a valor mediante dirección

printf (“valor de j=%d\n”,*i);

// Acceso a valor mediante variable, como lo hemos venido haciendo hasta ahora

printf (“valor de j=%d\n”, j);

Punteros como argumentos a funciones

Vimos al hablar de funciones que los parámetros se podías pasar por valor o por

referencia usando punteros. En este segundo caso, pasamos a la función la dirección

de la variable, por lo que si modificamos el contenido de esa dirección (no el

contenido del puntero, si no el contenido de la dirección apuntada por el puntero), esa

Page 45: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 44

modificación será vista al acabar la ejecución de la función. Ésta es una manera de que

una función pueda modificar variables de la función que la llamó.

Ejemplo. Repetimos el último Ejemplo del apartado de funciones, pero ahora usando

punteros que nos van a permitir intercambiar el valor de dos variables.

#include <stdio.h>

/* Prototipo */

void cambia (int var1, int var2);

int main () {

int i=1, j=2;

printf (“Valores antes de funcion Cambia: i=%d, j=%d”, i, j);

Cambia (&i, &j);

printf (“Valores despues de funcion Cambia: i=%d, j=%d”, i, j);

return 0;

}

/* Definición */

void cambia (int *a, int *b) {

int tmp;

tmp = *a;

*a = *b;

*b = tmp;

}

Memoria Dinámica

Otra forma de dar valor a un puntero es asignarle memoria dinámica mediante una

función de asignación de memoria. Recordar que al declarar un puntero simplemente

se está reservando memoria para almacenar una dirección de memoria, no se le está

asignando una dirección correcta, esto habrá que hacerlo posteriormente, como ya

hemos visto en ejemplos anteriores, y veremos también en esta sección.

Page 46: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 45

Las funciones de asignación de memoria reservan memoria de manera dinámica, es

decir, durante la ejecución del programa, devolviendo la dirección del primer byte de

la zona reservada. Las funciones más habituales son calloc y malloc, definidas en el

fichero alloc.h o bien en stdlib.h. Su sintaxis es la siguiente:

· malloc(size_t size). Donde el argumento es el número de bytes que se quieren

reservar.

· calloc(size_t n_items, size). Esta función reserva n_items bloques de size bytes cada

uno, es decir, n_bytes*size bytes de memoria.

Ejemplo. Ejemplo de uso de malloc que reservar memoria para almacenar n enteros,

donde n es un valor introducido por teclado. En el programa sólo mostramos la parte

de reserva de memoria. La asignación tendrá más sentido cuando usemos estructuras

de datos como vectores, arrays o estructuras, tipos de datos que veremos más

adelante.

#include <stdio.h>

int main () {

int *x, num_dat;

printf (“Cuantos valores quieres almacenar:”);

scanf (“%d”, &num_dat);

// Si malloc falla devuelve el valor NULL,

// antes de continuar comprobamos este posible error

if ( (x=(int*)malloc(num_dat * sizeof(int))) == NULL) {

printf(“ERROR al reservar memoria\n”);

return 1;

}

return 0;

}

La memoria no usada se puede liberar con la función free(puntero_a_memoria).

Para más información sobre estas funciones, se puede consultar el manual de UNIX

o bibliografía sobre el tema.

Page 47: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 46

Capítulo 9 - Estructura de Datos

Conceptos generales

Es una colección de variables del mismo o distinto tipo que se referencia bajo un

único nombre, proporcionando un medio eficaz de mantener junta la información

relacionada.

La definición de una estructura se realiza de la siguiente manera:

struct nombre {

lista de variables

};

Donde struct es la palabra clave que indica al compilador que se va a definir una

estructura, nombre es el identificador de la estructura, y en lista de variables es donde

se declaran las variables que van a componer esa estructura.

Ejemplo. De definición de una estructura.

struct complejo {

double real;

double imag;

};

Definida la estructura se pueden declarar variables de este tipo. Hay varias maneras

de realizar esto.

1. Directamente en la definición:

struct nombre {

lista de variables

} nombre_variable1, nombre_variable2, … ;

2. Tras la definición, de la siguiente manera:

struct nombre {

lista de variables

};

struct nombre nombre_variable1, nombre_variable2, … ;

3. Usando la sentencia typedef, sentencia que permite definir un tipo de dato en

función de los existentes. Su sintaxis es la siguiente: typedef tipo nombre;. A partir de

esta sentencia podremos usar nombre para declarar variables de tipo tipo. Uso:

typedef struct {

lista de variables

} nombre;

nombre nombre_variable1, nombre_variable2, … ;

Page 48: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 47

Tanto la asignación de valor, como el acceso al asignado a cada variable de la

estructura se hace de la siguiente manera: variable.miembro. Donde variable es el nombre

de la variable declarada como de algún tipo de estructura y miembro es cualquiera de las

variables declaradas en el cuerpo de la definición de la estructura (lista de variables).

Ejemplo. De definición de una estructura, declaración de variables de ese tipo y

acceso a sus miembros.

// Usando la forma 1 de declarar una variable de tipo estructura

struct complejo {

double real;

double imag;

} z;

z.real = 1.2;

z.imag = 3.4;

printf(“Parte real: %f. Parte imaginaria: %f\n”, z.real, z.imag);

// Usando la forma 2 de declarar una variable de tipo estructura

struct complejo {

double real;

double imag;

};

struct complejo z;

z.real = 1.2;

z.imag = 3.4;

printf(“Parte real: %f. Parte imaginaria: %f\n”, z.real, z.imag);

// Usando la forma 3 de declarar una variable de tipo estructura

Typedef struct {

double real;

double imag;

} complejo;

complejo z;

z.real = 1.2;

z.imag = 3.4;

printf(“Parte real: %f. Parte imaginaria: %f\n”, z.real, z.imag);

Page 49: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 48

Punteros a estructuras

Como con cualquiera de los tipos de variables vistas se pueden declarar

punteros a estructuras. En este caso el acceso a los miembros de la estructura apuntada

se realiza de la siguiente manera: puntero_estructura->miembro.

Ejemplo. De uso de punteros a estructura

typedef struct complejo {

double real;

double imag;

} complejo;

complejo z, *t;

t=&z;

t->real = 1.0;

t->imag = 2.1;

Uniones

Las uniones son similares a las estructuras, con la diferencia de que en las

uniones se almacenan en los campos solapándose unos con otros en la misma

disposición; al contrario que en las estructuras, donde los campos se almacenan unos a

continuación de otros. En esencia, las uniones sirven para ahorrar espacio en memoria.

Para almacenar los miembros de una unión, se requiere una zona de memoria

igual a la que ocupa el miembro más largo de la unión. Todos los miembros son

almacenados en el mismo espacio de memoria y comienzan en la misma dirección. El

valor almacenado es sobrescrito cada vez que se asigna un valor al mismo miembro o

a un miembro diferente, aquí radica la diferencia con las estructuras.

La declaración de uniones es similar a la de las estructuras:

Después de definir un tipo union, se puede declarar una o más variables de ese tipo de

la siguiente forma: union tipo_union [variables];

Page 50: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 49

Una declaración union define un tipo. La llave derecha que termina la lista de

miembros puede ser seguida por una lista de variables de la siguiente manera:

Dicho de una forma simple, una unión le permite manejar los mismos datos

con diferentes tipos, o utilizar el mismo dato con diferente nombre, a continuación le

presento un ejemplo:

En éste ejemplo tenemos dos elementos en la unión: la primera parte es el

entero llamado valor el cual es almacenado en algún lugar de la memoria de la

computadora como una variable de dos bytes. El segundo elemento está compuesto de

dos variables de tipo char llamadas primero y segundo. Estas dos variables son

almacenadas en la misma ubicación de almacenamiento que valor porque ésto es

precisamente lo que una unión hace, le permite almacenar diferentes tipos de datos en

la misma ubicación física. En éste caso Usted puede poner un valor de tipo entero en

valor y después recobrarlo en dos partes utilizando primero y segundo, ésta técnica es

utilizada a menudo para empaquetar bytes cuando, por ejemplo, combine bytes para

utilizarlos en los registros del microprocesador.

Page 51: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 50

La unión no es utilizada frecuentemente y casi nunca por programadores

principiantes, en este momento no necesita profundizar en el empleo de la unión así

que no dedique mucho tiempo a su estudio, sin embargo no tome a la ligera el

concepto de la unión, podría utilizarlo a menudo.

Tipos enumerados

Una enumeración es una lista de constantes enteras con nombre. Su función es

similar a la sentencia #define (se verá más adelante) en el sentido que permite crear

constantes que serán accedidas mediante un nombre, pero para secuencias de valores.

Se comportará como un nuevo tipo de dato que solo podrá contener los valores

especificados en la enumeración.

Ejemplo: uso de enum

enum dias_semana {LUNES=1, MARTES=2, MIERCOLES=3, JUEVES=4,

VIERNES=5, SÁBADO=6, DOMINGO=7 };

dias_semana dia;

dia = LUNES;

dia = 1; /* Ambas asignaciones son equivalentes */

Page 52: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 51

Page 53: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 52

Capítulo 10 - El Preprocesador

El preprocesador de C

Se denomina preprocesador a un programa que actúa antes que el compilador. Es una

etapa previa a la compilación entre cuyas tareas están la inclusión de ficheros, expansión de

macros y proceso de directivas.

Las sentencias del preprocesador pueden aparecer en cualquier punto del programa

(aunque la mayoría suelen estar al principio) y se caracterizan porque empiezan por el

caracter “#”. Las más importantes son:

· #define. Define una macro o una constante. Su sintaxis es #define x y, y lo que hace el

preprocesador es sustituir en el resto del programa donde encuentre el texto x por y.

Ejemplo.

#define PI 3.1416 // Cada aparición de PI será sustituida por 3.1416

#define MES_ERR “ERROR en la ejecución del programa\n” // Donde pongamos

MES_ERR será sustituido por la cadena de la derecha

¡No hay que poner ; al final de #define!

Podemos usar parámetros en la sustitución de macros.

Ejemplo.

#define max(A,B) ( (A)>(B) ? (A) : (B) )

y usarla como

x=max(p+q,r+s);

que sería sustituida por

x=((p+q)>(r+s) ? (p+q) : (r+s));

· #undef. Borra una macro de la tabla de definiciones.

Page 54: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 53

· #if, #ifdef, #ifndef, #else y #endif. Se puede preguntar por el valor de una constante o la

existencia o no de una macro. En caso de ser cierta la condición se compila el código entre #if

y #else, en caso de ser falsa se compila el código entre #else y #endif

Ejemplo.

#ifndef PI

#define PI 3.1416

#endif

· #include. Permite incluir un fichero dentro del programa C. Este fichero puede ser de

cabecera (.h) u otro programa C. Los ficheros de cabecera contienen:

Los prototipos de funciones.

Definiciones de constantes y macros

No deben contener código (declaraciones de funciones...)

Ejemplo. De uso de instrucciones del preprocesador

#include <stdio.h>

#include <math.h>

/* #include “mifichero.h” */

#define TAMMAX 10

#define MES_DESP “finalizada la ejecucion del programa\n”

main ()

{

double a[TAMMAX];

int i;

for (i=0; i<TAMMAX; i++)

{

scanf (“%lf”, &(a[i]));

printf (“%lf”, sin(a[i]));

}

printf(MES_DESP);

return 0;

}

Page 55: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 54

Capítulo 11 – Ficheros

Conceptos generales

El manejo de ficheros en C se realiza mediante una estructura denominada FILE. Esta

estructura está definida en el fichero stdio.h. Más concretamente, los ficheros se manejan con

punteros a ese tipo de estructuras:

FILE *nombre;

Donde nombre es el identificador con el que haremos referencia al fichero en las distintas

funciones que usemos para operar con él. Cada vez que operamos sobre un fichero se

modifica su estado, con lo que las funciones que lo manipulan siempre modifican la variable

(por eso es un puntero).

Lo primero que hay que hacer para operar con un fichero es “abrirle” mediante la función

fopen(), cuya sintaxis es:

fopen (nombre_fichero, modo)

Donde nombre_fichero es un puntero a una cadena de caracteres cuyo contenido es el

nombre del fichero (debe incluir la ruta). modo es un puntero a una cadena de caracteres que

especifica el tipo de operación que queremos realizar sobre el fichero. La forma de especificar

ésta es:

“r”, “w”, “a”. Se va a realizar una operación de lectura, escritura posicionando el flujo

al principio del fichero o escritura posicionando el flujo al final del fichero, en modo

ASCII.

“r+”, “w+”, “a+”. Se va a realizar una operación de lectura y escritura posicionando el

flujo al principio del fichero, escritura posicionando el flujo al principio del fichero y

lectura o escritura posicionando el flujo al final del fichero y lectura, en modo ASCII.

Si se añade al final de cualquiera de las opciones anteriores el caracter b la operación

del lectura y escritura se realizarán en modo binario.

La función fopen() devuelve un puntero a una estructura FILE si el fichero se ha

abierto correctamente o el valor NULL si ha habido error. Es importante comprobar esta

posibilidad en el programa antes de continuar.

Para cerrar un fichero que ya no se vaya a usar se utiliza la función flose(nombre). Con

nombre el nombre del puntero a FILE con que hayamos identificado al fichero que queremos

cerrar.

Page 56: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 55

Entrada/salida

Existen numerosas funciones para realizar operaciones de entrada/salida sobre

ficheros. Las más usadas son:

fprintf(FILE *nombre, const char *format ). Donde FILE *nombre es la variable

puntero a FILE que usemos para identificar el fichero y const char *format tiene el

mismo significado y formato que en printf(). Esta función se utiliza para escribir datos

en ASCII en un fichero. En caso de éxito, esta funciones devuelven el numero de

caracteres impresos (no incluyendo el caracter `\0' usado para terminar la

salida de cadenas). Si se encuentra un error de salida, se devuelve un valor negativo.

Tanto en ésta, como en el resto de funciones que veremos, el valor devuelto sirve para

comprobar que la operación se ha realizado con éxito.

fscanf(FILE *nombre, const char *format). Los argumentos tienen el mismo

significado que en fprintf(). Se usa para leer datos de un fichero en ASCII. El valor

devuelto es el número de datos, no de caracteres, leídos.

fwrite(const void *ptr, size_t tam, size_t nmiemb, FILE *nombre). Función para

escritura de datos en binario en un fichero. Escribe nmiemb elementos de datos, cada

uno de tam bytes de largo, al fichero apuntado por nombre, obteniéndolos del

sitio apuntado por ptr, esto es, ptr es un puntero a una variable, vector, estructura, etc,

tal que su tamaño sea de tam*nmiemb bytes. tam y nmiemb son datos enteros.

Devuelve el número de elementos (no de bytes) escritos correctamente. Si ocurre un

error o se llega al fin-de-fichero, el valor devuelto es un número menor del esperado (o

cero).

fread(void *ptr, size_t tam, size_t nmiemb, FILE *nombre). Función para lectura

de datos en binario en un fichero. El significado de los parámetros de la función es el

mismo que para fwrite salvo ptr que es un puntero a la zona de memoria donde se

almacenará la información leida. El valor devuelto es el mismo que en fwrite pero en

este caso haciendo referencia al número de datos leídos.

Otras funciones para entrada/salida son: fgets, fgetchar, fputs, fputchar. Su

funcionamiento es similar a las de nombre parecido (sin la f inicial) que sirven para

entrada/salida desde la estándar correspondiente. La búsqueda de más información se

deja para el estudiante.

fseek( FILE *nombre, long desplto, int origen). Sirve para el control de flujo de

datos sobre un fichero, más concretamente mueve el indicador que marca la posición

de escritura/lectura en el fichero correspondiente. La nueva posición del indicador,

medida en bytes, se obtiene añadiendo desplto bytes a la posición especificada por

origen. Para especificar el punto de origen del desplazamiento se pueden usar la

siguientes constantes:

SEEK_SET. Comienzo del fichero.

SEEK_CUR. Posición actual.

SEEK_END. Fin de fichero.

En caso de que todo haya ido correcto en la operación esta función devuelve un 0, y si ha

habido error un -1.

rewind( FILE *nombre). Es la versión rápida de fseek(nombre, 0, SEEK_SET), es

decir, mover el apuntador al comienzo del fichero. Esta función no devuelve nada.

feof(FILE *nombre). Devuelve un valor distinto de 0 si el indicador de fichero no ha

llegado al final, y 0 en caso contrario.

Page 57: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 56

Ejemplo. De manejo de ficheros. Este programa debe recibir 2 argumentos. El primero es un

fichero de texto con cantidades reales. Lee esas cantidades y las almacena en formato float

(binario) en el fichero incluido como segundo argumento. Cada valor leído es mostrado por

pantalla usando fprintf para mostrar el uso del puntero a la salida estándar “stdout”.

#include<stdio.h>

main (int argc, char **argv)

{

FILE *fpin, *fpout_fich, *fpout_std;

float dat;

int cont=0;

if (argc < 3)

{

fprintf (stderr,”ERROR numero de argumentos insuficiente\n”);

exit (1);

}

if ( (fpin = fopen(argv[1], "r")) == NULL)

{

fprintf (stderr,"ERROR No se pudo abrir %s\n", argv[1]);

exit (2);

}

if ( (fpout_fich = fopen(argv[2], "wb")) == NULL)

{

fprintf (stderr,"ERROR No se pudo abrir %s\n", argv[2]);

exit (2);

}

fpout_std = stdout;

fscanf (fpin,”%f”,&dat);

while (!feof(fpin)) {

if ( fwrite(&dat, sizeof(float), 1, fpout_fich) != 1)

{

fprintf(stderr, “ERROR al escribir dato %d en %s\n”, cont, arg[2]);

exit(3);

}

fprintf (fpout_std,"Dato escrito %.2f\n",dat); // se muestra con 2 decimales

fscanf (fpin,”%f”,&dat);

cont++;

}

fclose (fpin);

fclose (fpout_fich);

return 0;

}

Ejercicio. Modificar la condición de finalización de lectura de fichero en el

ejemplo anterior, usando el valor devuelto por fscanf().

Page 58: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 57

Page 59: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 58

Capítulo 12 – Herramientas

Introducción

En esta sección indicaremos una serie de trucos y herramientas que facilitan la

realización y depuración de programas en C. Queda fuera del alcance de esta introducción al

lenguaje C la explicación en profundidad de las herramientas que a continuación se indicarán,

por lo que serán los alumnos interesados los que tengan que profundizar en su

funcionamiento.

Depuración de un programa

Es bastante frecuente al crear un programa C que dé errores tanto en compilación

como en ejecución no siempre fáciles de detectar.

Una opción a seguir para detectar la zona que genera el error al compilar es la de ir

comentando partes del programa, hasta detectar la zona con error.

En cuanto a errores en ejecución, los consejos a seguir para detectarlos son:

Añadir mensajes para seguir el hilo de la ejecución y vigilar los valores de variables.

Acotar la sección de código que contiene el error.

Evaluar los parámetros que provocan el error.

Una herramienta que permita la depuración de un programa es la gdb. Esta

herramienta permite observar lo que ocurre dentro del programa en el momento de su

ejecución. Realiza cuatro operaciones básicas:

Ejecución del programa.

Detener la ejecución bajo ciertas condiciones.

Examinar que ha sucedido cuando el programa se ha detenido

Cambiar el estado de la ejecución del programa.

Si se quiere trabajar con el depurador mediante un interfaz gráfico se puede usar la

herramienta ddd.

Make

La herramienta make es una utilidad que permite mantener, actualizar y regenerar

eficientemente un programa que depende de múltiples archivos, determinando

automáticamente qué partes de este gran programa necesitan ser recompilado ejecutando los

comandos para esto.

Esta utilidad es tanto más conveniente cuanto más complejo sea el programa

ejecutable que se está construyendo. La situación ideal es cuando el fichero ejecutable consta

de muchos módulos que pueden ser compilados separadamente.

Page 60: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 59

Embellecedor de C

Una estrategia muy útil y aconsejable para la creación de código C es indentar

adecuadamente el código de las distintas partes del fichero fuente. De este modo, por ejemplo,

con un simple vistazo podremos determinar si hemos cerrado o no una sentencia bloque-

Dependiendo del sistema operativo en que estemos trabajando, el comando puede

variar. Así, para las versiones LINUX instaladas en el laboratorio tenemos el comando indent.

Por defecto lee datos de la entrada estándar y la respuesta la proporciona por la salida

estándar. También puede admitir argumentos, pero preste atención, pues si no se indica lo

contrario, el fichero modificado reemplaza el original.

El comando indent para hacer su trabajo hace un pequeño análisis sintáctico, y por lo

tanto puede indicar ciertos errores, como son un número no balanceado de apertura de

paréntesis y cierre de paréntesis.

Otros

Sytem (clear) = limpia pantalla

Page 61: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 60

Apéndice A

Page 62: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 61

Page 63: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 62

Apéndice B

Page 64: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 63

Page 65: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 64

Apéndice C

Page 66: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 65

Page 67: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 66

Apéndice D

Page 68: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 67

Page 69: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 68

Apéndice E

Page 70: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 69

Page 71: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 70

Apéndice F

Page 72: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 71

Page 73: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 72

Apéndice G

Page 74: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 73

Page 75: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 74

Page 76: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 75

Page 77: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 76

Apéndice H

Page 78: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 77

Page 79: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 78

Page 80: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 79

Page 81: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 80

Page 82: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 81

Page 83: Introducción a la programación en C

Introducción a la programación en C by CTG © Página 82

Bibliografía

Diego R. Llanos Ferraris, “Fundamentos de Informática y Programación en C”. Paraninfo,

2010. ISBN 13: 978-84-9732-792-3.

Brian Kernighan & Denis Ritchie. “El lenguaje de programación C”. Prentice Hall.

Byron S. Gottfried, “Programación en C”, McGraw-Hill. 2ª Edición.