Sei sulla pagina 1di 47

TEMA 2. INTRODUCCION AL LENGUAJE C.

1
Evolución del lenguaje C

• Dennis Ritchie diseña el lenguaje C en los laboratorios AT & T Bell en 1972.

Buscaba un lenguaje práctico y flexible para el desarrollo de UNIX.

“The C Programming Lenguage”, Brian W. Kernighan y Dennis M. Ritchie,

1978.

• En 1989 apareció ANSI C y un año más tarde ISO C.

• Surge C++ y en 1989 se crea un comité ANSI para la estandarización de

este lenguaje.

• En 1991 Bjarne Stroustrup publica un manual de referencia de C++.

• Se crea el comité ISO WG21 que elabora un documento que será el

estándar C++.

2
2.1. Conceptos básicos de C.

2.1.1. Estructura de un programa en C.

Un programa en C consta de uno o más módulos llamados funciones.


El programa comenzará con la ejecución de la función main.
Cada función debe contener:
- Cabecera, con el nombre de la función y una lista de
parámetros entre paréntesis.
- Instrucción compuesta (entre llaves)

Ejemplo: Area de un círculo.

#include <stdio.h>
#define PI 3.14159
float procesar(float radio);
main()
{
float radio, area;
printf (“Radio = ?”);
scanf(“%f”, &radio);
area = procesar(radio);
printf(“Area = %f”, area);
}
float procesar(float r)
{
float a;
a = PI * r * r;
return(a);
}

3
2.1.2. El conjunto de caracteres de C.

- Letras mayúsculas
- Letras minúsculas
- Dígitos del 0 al 9
- Caracteres especiales: + - * / = % & # ¿ < > [ ] { } ( ) : ; ....
- Secuencias de escape: \b \n \t

2.1.3. Identificadores y palabras reservadas.

- Los identificadores son nombres que se les da a elementos del programa.


- Deben comenzar con letra y después admiten letras, dígitos y el carácter
subrayado.
- C distingue mayúsculas de minúsculas.

Palabras reservadas.

auto, extern, sizeof, break, float, static, case, for, struct, char, goto, switch,
const, if, typedef....

2.1.4. Tipos de datos.

int Cantidad entera 2 bytes


char Carácter 1 byte
float Número en coma flotante 4 bytes
double Número en coma flotante 8 bytes
de doble precisión

Cualificadores de tipos: short, long, signed, unsigned.

4
2.1.5. Constantes.

- Constantes enteras: en decimal, octal y hexadecimal.


- Constantes en coma flotante: número en base 10 que contiene un punto
decimal o un exponente o ambos.
- Constantes de carácter: un sólo carácter entre comillas simples.

Tabla de secuencias de escape.

Caracter Secuencia de escape Valor ASCII


Sonido \a 007
Retroceso \b 008
Tabulador horizontal \t 009
Tabulador vertical \v 011
Nueva línea \n 010
Avance de página \f 012
Retorno de carro \r 013
Comillas \” 034
Comilla simple \’ 039
Signo de interrogación \? 063
Barra inclinada \\ 092
Nulo \0 000

- Constantes de cadena de caracteres: varios caracteres entre comillas.


- Constantes enumeradas.

2.1.6. Variables.

Variables: elementos del entorno que almacenan información dentro de una


parte del programa.
Cada variable tiene asociado un nombre, un tipo y un valor.

5
2.1.7. Declaraciones.

Una declaración asocia un tipo de datos especificado a un grupo de variables.


Ejemplos:
int a, b, c;
float raiz1, raiz2;
char indicador, texto[80];
short q;
double p;

Se pueden asignar valores iniciales a las variables en la declaración de tipos:

int c = 12;
char estrella = ’*’;
float suma = 0.;
double factor = 0.23123e-6;
char texto[10] = ”casa”; (automáticamente añade \0 al final de casa)

2.1.8. Instrucciones.
Las acciones de un programa se ejecutan a través de instruciones.
Las instrucciones en C terminan siempre en ;
Las instrucciones compuestas se escriben entre llaves { }

Ejemplos:
a = 3;
c = a + b;
++i;
printf(“Area = %f”, area);

6
2.1.9. Constantes simbólicas.

# define nombre texto

Ejemplos:
#define INTERES 0.23
#define PI 3.14159
#define TRUE 1
#define FALSE 0

2.2. Operadores y expresiones.

2.2.1. Operadores aritméticos.


+ Suma
- Resta
* Multiplicación
/ División
% Resto de la división entera

2.2.2. Operadores monarios.


Operador incremento ++
Operador decremento --
Operador sizeof: Devuelve el tamaño en bytes de su operando.

Ejemplos:
printf(“Entero: %d\n”, sizeof i);
printf(“i=%d\n”, i++);
printf(“i=%d\n”, i);
((int) f) % 2 con f en coma flotante

7
2.2.3. Operadores relacionales y lógicos.

Operadores relacionales: < , <= , > , >=


Operadores de igualdad: ==, !=
La expresión resultante será de tipo entero (verdadero=1 y falso=0)
Operadores lógicos: &&, ||

2.2.4. Operadores de asignación.

Identificador = expresión

Ejemplos:
a = 3;
suma = a+b;

- En C están permitidas asignaciones múltiples:


identificador1 = identificador2 = expresión
Que es equivalente a
identificador1 = (identificador2 = expresión)

Ejemplo: i=j=5;

Además hay otros operadores de asignación: +=, -=, *=, /= y %=

La expresión de asignación:
variable1 += variable2
Es equivalente a: variable1 = variable1 + variable2

8
2.2.5. El operador condicional.

expresión1 ? expresión2 : expresión3


Si expresión1 es cierta (no nula) el operador devuelve el valor de expresión2,
en otro caso, el valor de expresión3.

Ejemplo: (i<0) ? 0 : 100

Jerarquía de prioridades de los operadores.

Categoría de operador Operadores Asociatividad

Operadores monarios - ++ - - ! sizeof(tipo) Dcha a izda.


Multiplicación, división y * / % Izda a dcha.
resto aritméticos
Suma y resta aritméticas + - Izda a dcha.
Operadores relacionales < <= > >= Izda a dcha.
Operadores de igualdad == != Izda a dcha.
Y lógica && Izda a dcha.
O lógica || Izda a dcha.
Operador condicional ?: Dcha a izda.
Operad. de asignación = += -= *= /= %= Dcha a izda.

9
2.2.6. Funciones de biblioteca.

Función Tipo
abs(i) int Valor absoluto de i
ceil(d) double Redondear por exceso al entero más próximo
cos(d) double Coseno de d
cosh(d) double Coseno hiperbólico de d
exp(d) double Elevar e a la potencia d
fabs(d) double Valor absoluto de d
floor(d) double Redondear por defecto al entero más próximo
fmod(d1,d2) double Resto de d1/d2 (parte no entera del cociente) con
el signo de d1
getchar() int Introducir un carácter del dispositivo de entrada
estándar
log(d) double Logaritmo natural de d
pow(d1,d2) double d1 elevado a la potencia d2
printf(...) int Mandar datos al dispositivo de salida estándar
putchar(c) int Mandar un carácter al dispositivo de salida
estándar
rand() int Devolver un entero positivo aleatorio
sin(d) double Devolver el seno de d
sqrt(d) double Devolver la raíz cuadrada de d
srand(u) void Inicializar el generador de números aleatorios
scanf(...) int Introducir datos del dispositivo de entrada estándar
tan(d) double Tangente de d
toascii(c) int Convertir el valor del argumento a ASCII
tolower(c) int Convertir una letra a minúscula
toupper(c) int Convertir una letra a mayúscula

10
2.3. Entrada y salida de datos.

2.3.1. Introducción.

#include <stdio.h> archivo de cabecera para la entrada/salida estándar.

2.3.2. Entrada de un carácter. Función getchar.

Variable_carácter=getchar()
La función devuelve un carácter leído del dispositivo de entrada estándar
(teclado). Si encuentra una condición de fin de archivo devuelve la constante
EOF.
Ejemplo:
char c;
c = getchar();

2.3.3. Salida de un carácter. Función putchar.

putchar(variable_caracter)
La función transmite un carácter al dispositivo de salida estándar (pantalla).

Ejemplo:
#include <stdio.h>
#include <ctype.h>
main()
{
char letras[80];
int cont, auxiliar;
for (cont = 0; (letras[cont ] = getchar()) != ‘\n’; ++cont);
auxiliar = cont;
for (cont = 0; cont < auxiliar; ++cont)
putchar(toupper(letras[cont]));
}

11
2.3.4. Entrada de datos. Función scanf.

scanf(cadena de control, arg1, arg2, ... argn)

Para introducir valores numéricos, caracteres, cadenas de caracteres.


Cadena de control tiene información sobre el formato de arg1, arg2, ... y está
formada por grupos de caracteres que tienen el signo % y el carácter de
conversión.
Caracteres de conversión de datos de entrada.
Carácter Significado
de conversión
c Carácter
d Entero decimal
e Coma flotante
f Coma flotante

g Coma flotante
h Entero corto
i Entero decimal, octal o hexadecimal
o Entero octal
s Cadena de caracteres seguida del carácter espaciado (se
añade \0 al final)
u Entero decimal sin signo
x Entero hexadecimal
[...] Cadena de caracteres que puede incluir caracteres de
espaciado
Ejemplo:
main()
{
char concepto[20];
int no_partida;
float coste;
.....
scanf(“%s %d %f”, concepto, &no_partida, &coste);
......
}

12
Ejemplo:
#include <stdio.h>
main()
{
char linea[80];
.....
scanf(“%[ ABCDEFGHIJKLMNOPQRSTUVXYZ]”, linea);
......
}

Ejemplo:
#include <stdio.h>
main()
{
char linea[80];
.....
scanf(“%[^\n]”, linea);
......
}
Es posible limitar el número de caracteres especificando una longitud de
campo máxima para cada dato.
Ejemplo:
#include <stdio.h>
main()
{
int a;
float b;
char c;
.....
scanf(“%3d %5f %c”, &a, &b, &c);
......
}
Si introducimos 10 256.875 T se asignarán los valores: a 10, b 256.8 y c 7

13
2.3.5. Salida de datos. Función printf.

printf(cadena de control, arg1, arg2, .... argn)

Transfiere los datos de los argumentos a la salida estándar con el formato que
se indica en la cadena de control.

Caracteres de conversión de datos de salida.

Carácter Significado
de conversión
c Carácter
d Entero decimal con signo
e Coma flotante con exponente
f Coma flotante sin exponente
g Coma flotante
i Entero con signo
o Entero octal sin el cero inicial
s Cadena de caracteres
u Entero decimal sin signo
x Entero hexadecimal sin el prefijo 0x

Ejemplo:
#include <stdio.h>
main()
{
char concepto[20];
int no_partida;
float coste;
.....
printf(“%s %d %f”, concepto, no_partida, coste);
......
}

14
Ejemplo:
#include <stdio.h>
main() /*leer y escribir una línea de texto*/
{
char linea[80];
scanf(“ %[^\n]”, linea);
printf(“%s”, linea);
}

Se puede especificar también una longitud de campo mínima:


Ejemplo:
#include <stdio.h>
main()
{
int i = 12345;
float x = 345.678;
printf(“%3d %5d %8d\n\n”, i, i, i);
printf(“%3f %10f %13f\n\n”, x, x, x);
printf(“%3e %13e %16e\n”, x, x, x);
}
Salida: 12345 12345 12345
345.678000 345.678000 345.678000
3.456780e+02 3.456780e+02 3.456780e+02

15
También es posible especificar la precisión:

Ejemplo:
#include <stdio.h>
main()
{
float x = 123.456;
printf(“%7f %7.3f %7.1f\n\n”, x, x, x);
printf(“%12e %12.5e %12.3e”, x, x, x);
}

Salida: 123.456000 123.456 123.5


1.234560e+02 1.23456e+02 1.235e+02

Además podemos incluir dentro de cada cadena de control un indicador


inmediatamente después del %.

Indicadores de uso común.

Indicador Significado

- ajuste a izda. del campo


+ cada dato numérico es precedido de un signo (+ ó -)
0 aparecen ceros en lugar de espacios en blanco
‘‘ cada dato numérico positivo es precedido de un espacio en
blanco
# con las conversiones tipo o y x, hace que los datos octales y
hexadecimales sean precedidos por 0 y 0x
# con las conversiones tipo e, f y g, hace que todos los
números en coma flotante aparezcan con punto

16
2.3.6. Funciones gets y puts.

Facilitan la transferencia de cadenas de caracteres entre la memoria y los


dispositivos de entrada/salida estándares.

gets(cadena)
puts(cadena)

Cada una de estas funciones acepta como argumento una cadena de


caracteres que pueden incluir caracteres de espaciado.

En el caso de gets, la cadena terminará con un caracter de nueva línea.

Ejemplo:

#include <stdio.h>
main()
{
char linea[80];
gets(linea);
puts(linea);
}

17
2.4. Instrucciones de control.

2.4.1 Instrucción if-else.

if (expresión) instrucción
La instrucción se ejecutará sólo si la expresión tiene un valor no nulo
(expresión cierta). La expresión puede ser simple o compuesta.

Ejemplo: if ((balance < 1000.)|| (estado == ’R’)) printf(“%f”, balance);

if (expresión) instrucción1 else instrucción2

Si expresión tiene un valor no nulo (expresión cierta) se ejecutará instrucción1,


en caso contrario (expresión falsa) se ejecutará instrucción2.

Ejemplo: if (estado == ‘S’)


tasa = 0.20 * pago;
else
tasa = 0.14 * pago;
También se puede poner como:
tasa = (estado == ‘S’) ? (0.20 * pago) : (0.14 * pago);

Se pueden anidar estructuras if-else unas dentro de otras.

18
2.4.2. Instrucción while.

while (expresion) instrucción

la instrucción se ejecutará repetidamente mientras el valor de la expresión sea


cierto (no nulo).

Ejemplo:
#include <stdio.h>
main()
{
int digito = 0;
while (digito <= 9) {
printf(“%d\n”, digito);
++digito;
}
}

2.4.3. Instrucción do-while.

do instrucción while (expresión)


Se ejecuta la instrucción mientras que el valor de la expresión sea cierto (no
nulo).

Ejemplo:
#include <stdio.h>
main()
{
int digito = 0;
do
printf(“%d\n”, digito++);
while (digito <= 9);
}

19
2.4.4. Instrucción for.

for (expresión1; expresión2; expresión3) instrucción

- expresión1 se utiliza para inicializar parámetros,


- expresión2 representa la condición que debe cumplirse (no nula) para que
continúe la ejecución del bucle
- expresión3 modifica el parámetro inicial asignado por expresión1.

Pueden aparecer varias expresiones1 o expresiones3 siempre y cuando se


separen por comas.

El ciclo es equivalente a:

expresión1;
while (expresión2) {
instrucción
expresión3;
}

Ejemplo:
#include <stdio.h>
main()
{
int digito = 0;
for (digito = 0; digito <= 9; ++digito)
printf(“%d\n”, digito);
}

20
2.4.5. Instrucción switch.

switch (expresion) instrucción


- Hace que se seleccione un grupo de instrucciones entre varios grupos
disponibles.
- Expresión devuelve un valor entero (o char).
- Instrucción muestra las distintas opciones a través de etiquetas. En general,
cada opción tendrá la siguiente sintaxis:
case expresión1:
case expresión2:
...........
case expresión m:
instrucción1
instrucción2
.......
instrucción n
Ejemplo:
switch (eleccion = getchar()) {
case ‘r’:
case ‘R’:
printf(“ROJO”);
break;
case ‘b’:
case ‘B’:
printf(“BLANCO”);
break;
case ‘a’:
case ‘A’:
printf(“AZUL”);
break;
default:
printf(“ERROR”);
}

La instrucción break hace que se transfiera el control fuera de la instrucción


switch evitando que se ejecute más de un grupo de instrucciones.

Si ninguna de las etiquetas coincide con la expresión se ejecuta la parte


default.

21
2.4.6. Instrucción break.
Se utiliza para terminar la ejecución de los bucles while, do-while, for, o para
salir de la instrucción switch.

Ejemplo:

scanf(“%f”, &x);
while (x <= 100) {
if (x < 0) {
printf(“ERROR”);
break;
}
/*procesar el valor no negativo de x*/
}

2.4.7. Instrucción continue.


Se utiliza para saltarse el resto de las instrucciones en la ejecución actual de un
bucle.

Ejemplo:

for (cont = 1; cont <= n; ++cont) {


printf(“x = “);
scanf(“%f”, &x);
if (x < 0) continue;
suma += x;
++nmedia;
}

22
2.4.8. Instrucción goto.

goto etiqueta;

donde etiqueta es un identificador que se utiliza para rotular la instrucción a la


que se transferirá el control.
La instrucción etiquetada tendrá el formato:
etiqueta: instrucción

Ejemplo:
/*bucle principal*/
scanf(“%f”, &x);
while (x<= 100) {
.......
if (x < 0) goto error;
......
scanf (“%f”, &x);
}

/*rutina de detección de error*/


error: {
printf(“ERROR – valor negativo de x”);
.............
}

23
2.5. Funciones.

2.5.1. Introducción.
- Funciones de librerías de C
- Funciones definidas por el programador

2.5.2. Definición de una función.

Cabecera de la función:
tipo nombre(tipo1 arg1, tipo2 arg2, .... tipon argn)
Tipo es el tipo de dato que devuelve la función
Los argumentos se denominan argumentos o parámetros formales.
Cuerpo de la función: instrucción compuesta que debe incluir una o más
instrucciones
return expresión para devolver el control al punto de llamada.

Ejemplo:
char minus_mayus (char c1)
{
char c2;
c2 = (c1 >= ’a’ && c1 <= ‘z’) ? (‘A’ + c1 – ‘a’) : c1;
return (c2);
}

24
2.5.3. Llamada a una función.

nombre(arg1, arg2, ..., argn)

Los argumentos serán ahora los parámetros reales de la función y pueden ser
constantes, variables o expresiones. La función devuelve un valor del tipo que
aparece en la definición.

Ejemplo:

#include <stdio.h>

char minus_mayus (char c1)


{
char c2;
c2 = (c1 >=’a’ && c1 <= ‘z’) ? (‘A’ + c1 – ‘a’) : c1;
return (c2);
}
void main(void)
{
char minusc, mayusc;

printf(“Introduce una letra minúscula”);


scanf(“%c”, &minusc);
mayusc = minus_mayus(minusc);
printf(“\nLa mayúscula equivalente es: %c\n\n”, mayusc);
}

25
2.5.4. Prototipos de funciones.

tipo nombre(tipo1 arg1, tipo2 arg2, .... tipon argn);


Se utilizan prototipos de funciones cuando la llamada a una función está antes
que la definición de la función.
Los argumentos son ficticios y pueden incluso no aparecer.

Ejemplo:
#include<stdio.h>
long int factorial(int n)
{
int i;
long int prod = 1;
if (n > 1)
for (i = 2; i <= n; ++i)
prod *= i;
return (prod);
}
main ()
{
int n;
printf(“\nn = “);
scanf(“%d”, &n);
printf(“\nn! = %ld”, factorial(n));
}

26
Ejemplo:
#include <stdio.h>
long int factorial(int n);
main ()
{
int n;
printf(“\nn = “);
scanf(“%d”, &n);
printf(“\nn! = %ld”, factorial(n));
}
long int factorial(int n)
{
int i;
long int prod = 1;
if (n > 1)
for (i = 2; i <= n; ++i)
prod *= i;
return (prod);
}

2.5.5. Paso de argumentos a una función.

Paso por valor


Cuando se pasa un parámetro real a una función se pasa una copia de la
variable, por tanto la función no cambiará el valor de ese parámetro.

27
2.6. Estructura de un programa. Tipos de variables.
2.6.1. Tipos de variables.
Según su tipo de almacenamiento:
auto, extern, static, register

Ejemplo:
auto int a, b, c;
extern float raiz1, raiz2;
static int cont = 0;
extern char asterisco;

2.6.2. Variables automáticas (auto).


- Se declaran dentro de una función y son locales a la función. También los
parámetros formales son variables automáticas.
- Si no se especifica lo contrario, la variable será automática.
- Se pueden asignar valores iniciales a las variables automáticas.
- Las variables automáticas no mantienen el valor cuando se transfiere el
control fuera de la función.

2.6.3. Variables externas (extern).


- Su ámbito de validez se extiende desde su definición y hasta el final del
programa manteniendo los valores que tomen en las distintas funciones.
- Se utilizan para trasmitir valores entre funciones.
- Se distingue entre:
- Definición de variable externa: Antes de las funciones en las
que aparece. Reserva memoria. Se pueden asignar valores.
No es necesario utilizar extern.

- Declaración de variable externa: Cuando la función que utiliza


la variable precede a la definición de la variable o está en otro
archivo. Comienza con la palabra extern. No se reserva
memoria. No puede haber asignación de valores.

28
2.6.4. Variables estáticas (static).

Las variables estáticas mantienen sus valores a lo largo de la vida del


programa.
En un programa monoarchivo tienen el ámbito de validez de las variables
automáticas.
Comienza la designación de tipo con la palabra static.

Si una variable local (o estática) de una función tiene el mismo nombre que una
externa, dentro de la función prevalece la variable local (o estática).

Ejemplo:
float a, b, c; /*variables externas*/
void ficticio(void);
main()
{
static float a; /*variable estática real a*/
......
}
void ficticio(void)
{
static int a; /*variable estática entera a*/
int b;
}

29
2.6.5. Programas de varios archivos.

La definición de una función dentro de un programa multiarchivo puede ser


externa (reconocida en todo el programa) o estática (reconocida sólo en el
archivo que se defina).
La definición será la siguiente:
tipo_almac. tipo_datos nombre (tipo1 arg1, tipo1 arg2....tipon argn)

Cuando se define una función en un archivo y se accede desde otro, este


segundo fichero debe tener una declaración de la función (el especificador
extern es opcional).

Ejemplo:

Primer archivo
#include <stdio.h>
extern void salida(void);
main()
{
salida();
}
segundo archivo
extern void salida(void)
{
printf(“HOLA”);
return;
}

También pueden existir variables externas asociadas a varios archivos.


La definición y posible inicialización estará en un archivo y cada vez que se
quiera utilizar se declarará en el archivo correspondiente.

30
2.7. Tablas.
2.7.1. Definición.
Colección de datos del mismo tipo, con un nombre común y uno o varios
índices (enteros no negativos) que recorren los datos.

tipo_almac. tipo_datos nombre[expresion];

Ejemplos:
int x[100];
char texto[80];
static char mensaje[25];
static float n[12];

Ejemplo:
#include <stdio.h>
#include <ctype.h>

#define TAMANO 80

main()
{
char letras[TAMANO];
int cont;
for (cont = 0; cont < TAMANO; ++cont)
letras[cont] = getchar();
for (cont = 0; cont < TAMANO; ++cont)
putchar(toupper(letras[cont]));
}

31
Las tablas automáticas, a diferencia de las variables automáticas, no pueden ir
inicializadas.
Para hacerlo, tendremos que definirlas como externas o estáticas. En ese caso,
los valores iniciales irán ordenados, separados por comas y entre llaves.

Ejemplo:
int digitos[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
static float x[6] = {0, 0.25, 0, -0.5, 0, 0}
char color[4] = {‘R’, ‘O’, ‘J’, ‘O’};

x será estática y digitos y color serán externas debido a su colocación en el


programa.

2.7.2. Operaciones con tablas.


Todas las operaciones (asignación, comparación...) deberán realizarse posición
a posición.

32
2.7.3. Tablas como parámetros de funciones.

Una tabla se puede pasar como parámetro de una función.


Estamos pasando la dirección del primer elemento de la tabla, por tanto,
estamos pasando un parámetro por referencia.

Ejemplo:
float media(int a, float x[]);
main()
{
int n;
float med;
float lista[100];
.......
med = media(n, lista);
.......
}
float media(int a, float x[])
{
..............
}

33
2.7.4. Tablas multidimensionales.

tipo_almac. tipo_dato nombre [expr.1][expr2]...[exprn]

Ejemplo:
float tabla[50][50];
char pagina[24][80];
static double registros[K][M][N];
int valores[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int val[3][4] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};

34
2.7.5. Tablas y cadenas de caracteres.
Existen funciones para el tratamiento de cadenas de caracteres en string.h
Ejemplo: Ordenar alfabéticamente una lista de cadenas de caracteres.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reordenar (int n, char x[][12]);
main
{
int i, n=0;
char x[10][12];
printf(“Introducir una cadena. Escribir \’FIN\’ para terminar \n”);
do {
printf(“cadena %d: “, n +1);
scanf(“%s”, x[n]);
} while (strcmp(x[n++], “FIN”));
n--;
reordenar(n, x);
printf(“\n\nLista reordenada de cadenas \n”);
for (i= 0; i < n; ++i) printf(“\ncadena %d: %s”, i +1, x[i]);
}
void reordenar(int n, char x[][12])
{ char temp[12];
int i, elem;
for (elem = 0; elem < n –1; ++elem)
for (i = elem + 1; i < n; ++i)
if (strcmp(x[elem], x[i]) > 0) {
strcpy(temp, x[elem]);
strcpy(x[elem], x[i]);
strcpy(x[i], temp);
}
return;
}

35
2.8. Punteros.
2.8.1. Conceptos básicos.
&v dirección de v
pv = &v asignamos a pv la dirección de v
*pv contenido de la dirección de v (valor)

Dirección de v Valor

pv v

2.8.2. Declaración de punteros.

tipo_dato *ptvar;

Ejemplo:

#include <stdio.h>
main()
{
int v = 3;
int *pv;
pv = &v;
printf(“\n*pv=%d v=%d“, *pv, v);

*pv = 0;
printf(“\n\n*pv=%d v=%d”, *pv, v);
}

Salida: *pv=3 v=3


*pv=0 v=0

36
2.8.3. Paso de punteros a una función.
Permite el paso de parámetros por referencia.

Ejemplo:
#include <stdio.h>
void func1(int u, int v);
void func2(int *pu, int *pv);
main()
{
int u = 1;
int v = 3;
printf(“\nAntes de la llamada a func1: u=%d v=%d”, u, v);
func1(u, v);
printf(“\nDespués de la llamada a func1: u=%d v=%d”, u, v);
printf(“\nAntes de la llamada a func2: u=%d v=%d”, u, v);
func2(&u, &v);
printf(“\nDespués de la llamada a func2: u=%d v=%d”, u, v);
}
void func1(int u, int v)
{
u = 0;
v = 0;
printf(“\nDentro de func1: u=%d v=%d”, u, v);
return;
}
void func2(int *pu, int *pv)
{
*pu = 0;
*pv = 0;
printf(“\nDentro de func2: *pu=%d *pv=%d”, *pu, *pv);
return;
}

37
Salida:
Antes de la llamada a func1: u=1 v=3
Dentro de func1: u=0 v=0
Después de la llamada a func1: u=1 v=3

Antes de la llamada a func2: u=1 v=3


Dentro de func1: *pu=0 *pv=0
Después de la llamada a func2: u=0 v=0

2.8.4. Punteros y tablas unidimensionales.

El nombre de una tabla es un puntero al primer elemento de la tabla.


int x[10] x &x[0]

i-ésimo elemento de la tabla: &x[i] (x+i)

38
2.8.5. Asignación dinámica de memoria.

Podemos definir una tabla como un puntero: int *x en lugar de int x[10]
Si x es una variable puntero tendremos que asignarle memoria dinámicamente:
x = (int *) malloc(10 * sizeof(int));

En este caso no se podrán asignar valores iniciales.

Ejemplo: Ordenar crecientemente una lista de números.

#include<stdio.h>
#include<stdlib.h>
void reordenar(int n, int *x);
main()
{
int i, n, *x;
printf(“ \n¿Cuántos valores serán introducidos? ”);
scanf(“%d”, &n);
printf(“\n”);
x = (int *) malloc(n * sizeof(int));
for (i = 0; i<n; ++i) {
printf(“i = %d x = “, i + 1);
scanf(“%d”, x + i);
}
reordenar(n, x);
printf(“\n\nLista de números reordenada: \n\n”);
for (i = 0; i < n; ++i)
printf(“i = %d x = %d\n“, i + 1, *(x + i));
}
void reordenar(int n, int *x)
{
int i, elem, temp;
for (elem = 0; elem < n – 1; ++elem)
for (i = elem + 1; i < n; ++i)
if (*(x+i) < *(x + elem)) {
temp = *(x + elem);
*(x + elem) = *(x + i);
*(x + i) = temp;
}
return;
}

Para liberar la memoria asignada : free(x);

39
2.8.6 Punteros y tablas multidimensionales.

tipo_dato tabla [expresión1][expresión2]

- Podemos definir una tabla bidimensional como un puntero a tablas


unidimensionales contiguas:

tipo_dato (*ptvar)[expresión2]

Ejemplo: La tabla int x[10][20] se puede definir como: int (*x) [20]

Ahora x[2][5] se puede expresar como *(*(x + 2) + 5)

- Una tabla bidimensional se puede definir también como una tabla de


punteros:

tipo_dato *ptvar[expresión1]

Ejemplo: int *x [10]

Ahora x[2][5] se puede expresar como *(x[2] + 5).

- Además una tabla bidimensional se puede definir a través de un doble


puntero: int ** m
de forma que asignaremos dinámicamente espacio de la siguiente forma:

m = (int **) malloc (NUMFILAS*sizeof(int *));


for (j=0; j<NUMFILAS; j++){
m[j] = (int *) malloc (NUMCOLUMNAS * sizeof(int));
}

40
2.9. Estructuras y uniones.
2.9.1 Definición de una estructura.
struct marca {
miembro1;
miembro2;
.....
miembrom;
};
los miembros pueden ser variables, punteros, tablas u otras estructuras.

Ejemplo:
struct cuenta {
int no_cuenta;
char tipo_cuenta;
char nombre[80];
float saldo;
};
struct cuenta antiguocliente, nuevocliente;

Esto equivale a la siguiente definición:


struct cuenta {
int no_cuenta;
char tipo_cuenta;
char nombre[80];
float saldo;
} antiguocliente, nuevocliente;

También se les pueden asignar valores iniciales:


static struct cuenta cliente = {12345, ‘R’, “José García”, 586.30};

2.9.2 Procesamiento de una estructura.


variable. miembro
Ejemplo: cliente.no_cuenta

41
2.9.3 Tipos de datos definidos por el usuario.

typedef tipo nuevo_tipo;


Permite definir nuevos tipos de datos que sean equivalentes a los tipos de
datos existentes.

Ejemplo:
typedef int edad;
edad varon, hembra;

Este esquema se utiliza habitualmente con estructuras para simplificar la


notación:
typedef struct {
miembro1;
miembro2;
....
miembrom;
} nuevo_tipo;

Ejemplo:
typedef struct {
int no_cuenta;
char tipo_cuenta;
char nombre[80];
float saldo;
} registro;
registro anteriorcliente, nuevocliente;

42
2.9.4 Estructuras y punteros.

Se pueden definir variables puntero que apunten a estructuras:


Ejemplo:
struct {
int no_cuenta;
char tipo_cuenta;
char nombre[80];
float saldo;
} cliente, *pc;

pc = &cliente;
Para acceder a un miembro en términos de su correspondiente variable
puntero
pc->no_cuenta
que equivale en este caso a: cliente.no_cuenta (*pc).no_cuenta

2.9.5 Paso de estructuras a una función.

Se pueden pasar miembros individuales o estructuras completas.


Una estructura completa se puede transferir pasando un puntero a la estructura
como argumento (paso por referencia).

43
Ejemplo:
#include <stdio.h>
typedef struct {
char *nombre;
int no_cuenta;
char tipo_cuenta;
float saldo;
} registro;

void ajustar(registro *pt);

main()
{
static registro cliente = {“Lázaro”, 3333, ‘A’, 33.33};
printf(“%s %d %c %.2f\n”, cliente.nombre, cliente.no_cuenta,
cliente.tipo_cuenta, cliente.saldo);
ajustar(&cliente);
printf(“%s %d %c %.2f\n”, cliente.nombre, cliente.no_cuenta,
cliente.tipo_cuenta, cliente.saldo);
}

void ajustar(registro *pt)


{
pt->nombre = “José”;
pt->no_cuenta = 9999;
pt->tipo_cuenta = ‘R’;
pt->saldo = 99.99;
return;
}

Salida: Lázaro 3333 A 33.33


José 9999 R 99.99

44
2.9.6 Estructuras autorreferenciadoras.

struct marca {
miembro1;
miembro2;
.....
struct marca *nombre;
};

Ejemplo:
struct lista_elementos {
char elem[40];
struct lista_elementos *sig;
};

45
2.9.7 Uniones.
Las uniones se componen de miembros que comparten el mismo área de
almacenamiento.
union marca {
miembro1;
miembro2;
......
miembrom;
};

Ejemplo:
union id {
char color[12];
int talla;
} camisa, blusa;

46
2.10. Enumeraciones.

enum marca {miembro1, miembro2, ... miembrom};

tipo_almacenamiento enum marca variable1, variable2, ...variablen;

o lo que es lo mismo:

tipo_almacenamiento enum marca {miembro1, miembro2, ... miembrom}


variable1, variable2,....variablen;

Ejemplo:
enum colores {negro, azul, cian, verde, magenta, rojo, blanco, amarillo} color;

Las constantes de enumeración representarán ahora los siguientes valores


enteros: negro-0, azul-1, cian-2,.....,amarillo7 (Se pueden cambiar).

Ejemplo:
enum boolean {FALSE, TRUE};
FALSE-0 y TRUE-1.

47

Potrebbero piacerti anche