Documente Academic
Documente Profesional
Documente Cultură
_Gua de Trabajo No 4_
Indicaciones_ Resuelva o plantee una solucin a una serie de interrogantes y problemas que a continuacin se le
presentan, donde se destacan los puntos a u nivel bsico/intermedio del uso de punteros y estructuras en la
programacin con lenguaje C.
En esta seccin se practicar el uso de punteros, desde su concepcin hasta el uso de vectores y punteros a
funciones.
Antes de iniciar se aclaran unos conceptos bsicos y necesarios para una fcil comprensin del tema.
La Memoria_ La memoria se organiza en bits. Los bits son la unidad de memoria mas pequea y su valor puede
ser 1 0. Para trabajar con comodidad se usan bytes, que son agrupaciones de 8 bits. Se usan 8 porque es un
numero lo suficientemente grande y porque permite una conversin directa muy sencilla entre binario y
hexadecimal.
La memoria RAM y el Disco Duro son zonas de memoria que los programas utilizan para poder ser ejecutados o
almacenados respectivamente. En la RAM las direcciones de memoria se numeran en hexadecimal, como se ha
mencionado anteriormente la conversin entre binario y hexadecimal es sencilla y directa:
Ejemplo:
100101011112 4AF16
(Agrupando bloques de cuatro bits, partiendo del menos significativo, se puede hacer la conversin directa, de
binario a hexadecimal), por esta razn es muy comn encontrar nmeros hexadecimales en las direcciones de
memoria.-
_Sistemas Operativos_
_17-09-2015_
Que es un Puntero?
La manera mas fcil de definir un puntero es: Un puntero es una variable, nada mas que eso.
Tenemos muchos tipos de variables, donde su diferencia en lo que podemos almacenar en ellas, Tenemos
variables en las que podemos almacenar nmeros enteros, en coma flotante, letras.- Entonces la pregunta es:
Que podemos guardar en un una variable de tipo puntero?.- Pues algo tan simple como una direccin de
memoria.- Entonces ahora podemos decir que:
Un puntero es una variable que contiene (apunta a) una direccin de memoria.
Cuando compilamos un programa, el compilador traduce todas las lineas de cdigo fuente en sentencias o
instrucciones que pueden ser entendidas y ejecutadas por la CPU.- Al ejecutar el archivo con el cdigo fuente
compilado, este se convierte en un proceso y su se vuelca a la memoria principal, el operativo mete toda la
informacin de este nuevo procesos en las estructuras que utiliza para planificar su ejecucin, adems de
asignarle las zonas de memoria para alojar el cdigo en si y la memoria reservada para las variables. Entonces
cuando definimos o declaramos una variable lo que estamos diciendo es que se reserve una zona de memoria en
la que podamos almacenar datos.
Por ejemplo cuando definimos una variable de tipo entero:
int numero;
se reserva una cantidad de memoria que depender del tipo de variable. En este caso el tipo int ocupa 4 bytes.
(Podemos utilizar el operador sizeof, para saber la cantidad de memoria que utiliza un tipo de dato determinado:
[printf(Tamao de int: %i\n, sizeof(int)]).
En este caso podemos ver la memoria RAM como un tabla de direcciones, cada una con un espacio en el que
podemos almacenar datos.
Por ejemplo, en este programa:
#include <stdio.h>
int main(void) {
int a, b;
a = 0;
b = a + 8;
return 0;
}
se reserva 8 bytes para albergar dos valores enteros. Imagine que la variable a ocupa los bytes 1000-1003 y la
variable b los bytes 1004-1007.- Podemos representar la memoria as:
_Sistemas Operativos_
_17-09-2015_
Observe que, inicialmente, cuando se reserva la memoria, sta contiene un patrn de bits arbitrario. La sentencia
a = 0 se interpreta como ((almacena el valor 0 en la direccin de memoria de a)), es decir, ((almacena el valor 0
en la direccin de memoria 1000)). La asignacin b = a + 8 se interpreta como ((calcula el valor que resulta de
sumar 8 al contenido de la direccin de memoria 1000 y deja el resultado en la direccin de memoria 1004)).
Los punteros son una herramienta potente, distintiva y fundamental del lenguaje C, y su compresin profunda es
esencial para escribir aplicaciones avanzadas. Los arrays en C (vectores y matrices) tiene una relacin ntima con
los punteros; en cierto modo son dos representaciones equivalentes de los mismos datos.
El operador & es el operador de direccin. La funcin scanf, disponible al incluir stdio.h, permite leer datos
por teclado. La funcin scanf se usa de un modo similar a printf: su primer argumento es una cadena con marcas
de formato. A sta le siguen una o ms direcciones de memoria. Si desea leer por teclado el valor de una de la
variable entera a, puede hacerlo as:
scanf ("%d", &a);
Observe que la variable cuyo valor se lee por teclado va obligatoriamente precedida por el operador &: es as
como obtenemos la direccin de memoria en la que se almacena el valor de la variable.
Declaracin de un puntero
Un puntero, en C, se declara como sigue (deben declararse antes de usarlos, igual que el resto de variables:
tipo_dato
*nombre_puntero;
Donde tipo_dato es cualquier tipo definido. As, un puntero a carcter se declarara de la siguiente forma:
char *pchar;
Ejemplo:
/*
* File:
punteros1.c
* Author: logan
*
* Created on 09 de Agosto de 2015, 05:49 PM
*/
#include <stdio.h>
#include <stdlib.h>
int main() {
int x;
int y;
int *px;
x = 5;
px = &x;
y = *px;
return 0;
}
_Sistemas Operativos_
_17-09-2015_
*px
*
Nota: Un puntero representa la direccin de memoria del objeto al que apunta, NO su valor.
_Punteros a Carcter
En C, no hay variables del tipo cadena de caracteres; ests se manejan por medio de variables del tipo puntero a
carcter o por medio de arrays de caracteres.
Ejemplo:
1. /*
2. * File:
main.c
3. * Author: logan
4. *
5. * Created on 09 de Agosto de 2015, 07:04 PM
6. */
7.
8. #include <stdio.h>
9. #include <stdlib.h>
10.
11. int main( ) {
12.
13. char *cadena;
14. cadena = "Hola Mundo_";
15.
16. printf("Valor de cadena = %p\n", cadena);
17. printf("Valor indirecto de cadena = %c\n", *cadena);
18. puts(cadena);
19.
20. return 0;
21. }
_Sistemas Operativos_
_17-09-2015_
Salida:
Valor de cadena = 0x8048530
Valor indirecto de cadena = H
Hola Mundo_
En la linea 13 declara que la variable cadena es un puntero a carcter, es decir, una direccin de memoria en la
que se almacena un carcter. Puesto que cadena es un puntero a carcter, y no una cadena de caracteres, la
instruccin en la linea 14 no asigna la cadena Hola Mundo.- a la variable cadena, De esta forma, el puntero
cadena apunta al primer carcter del string Hola Mundo.En C, todas las cadenas de caracteres se almacenan en memoria con un carcter nulo \0 al final, el cual indica el
fin de las mismas; de esta forma no hay que preocuparse de su longitud. La instruccin 18 imprime en la salida
estndar el string al que apunta cadena. La funcin puts imprime el carcter almacenado en cadena, es decir H, y
luego imprime todos los caracteres consecutivos en memoria hasta que llega al \0, y lo sustituye con un \n, el
cual tambin es impreso.
En la linea 14 se declara que la variable msj es un puntero a carcter. En 14, la declaracin crea un puntero para
la variable msj, designando &msj, el cual apunta a cuatro bytes (tamao de una variable puntero, un valor int). En
la linea 15, la llamada a malloc inicializa el puntero msj, es decir, le asigna una direccin de memoria (4 bytes)
que se almacenan en &msj. Esta direccin de memoria, msj, apunta a su vez a los 13 bytes reservados por
malloc.
_Sistemas Operativos_
_17-09-2015_
Los punteros y sus valores indirectos.El siguiente programa ilustra el uso de punteros para manejar cadenas de caracteres:
1. /*
2. * File:
main.c
3. * Author: logan
4. *
5. * Created on 09 de Agosto de 2015, 23:44 PM
6. */
7.
8. #include <stdio.h>
9. #include <stdlib.h>
10. #include <string.h>
11.
12. int main( ) {
13.
14. char *nombre;
15. nombre = (char *) malloc(10);
16. printf("Como te llamas: ");
17. scanf("%s", nombre);
18. printf("Hola %s tu inicial es: %c\n", nombre, *nombre);
19. printf("Tu direccin en memoria es: %p\n", nombre);
20.
21. return 0;
22. }
En la linea 15 se reservan 10 bytes de memoria consecutivos para caracteres, y devuelve un puntero a los
mismos que se asignan a nombre. Note que se ha reservado 10 bytes de memoria, lo cual permite la captura y
almacenamiento de una cadena con un mximo de 9 caracteres, ya que el ultimo byte se requiere para el carcter
nulo \0.
Punteros y Arrays
En C, hay una relacin muy estrecha entre punteros y arrays (vectores) de datos de cualquier tipo; de hecho, los
punteros y los arrays don dos formas complementarias de representar los mismos datos. Todo programa en el
que se use notacin de arrays puede reformularse con notacin de punteros, y viceversa.
1. /*
2. * File:
main.c
3. * Author: logan
4. *
5. * Created on 09 de Agosto de 2015, 05:49 PM
6. */
7.
8. #include <stdio.h>
9. #include <stdlib.h>
10. #include <string.h>
11.
12. int main( ) {
13.
14. int i = 0;
15. char *msj;
16. msj = (char *) malloc(30);
17. strcpy(msj, "Hola, Mundo.-");
18. puts(msj);
19.
20. while(msj[i] != NULL) {
21.
printf("%c\t", msj[i]);
22.
i++;
23. }
24.
_Sistemas Operativos_
_17-09-2015_
25.
26.
27.
28.
29.
30.
31.
32.
33.
34. }
putchar('\n');
i = 0;
while(*(msj) != 0) {
printf("%c\t", *(msj));
msj++;
}
return 0;
Salida:
Hola, Mundo.H
o
l
H
o
l
a
a
,
,
M
M
u
u
n
n
d
d
o
o
.
.
Hay que notar la diferencia conceptual entre las instrucciones 22 y 30, en 22 simplemente, se incrementa una
variable entera en una unidad. En 30, el operador incremento desplaza el puntero en memoria el numero de bytes
que ocupa su valor indirecto, como msj es un puntero a carcter, solo en este caso particular el desplazamiento
es de un byte.
_17-09-2015_
_Sistemas Operativos_
_17-09-2015_
En C una estructura es una coleccin de variables que se referencian bajo el mismo nombre. Una estructura
proporciona un medio conveniente para mantener junta informacin que se relaciona. Una definicin de estructura
forma una plantilla que se puede usar para crear variables de estructura. Las variables que forman la estructura
son llamados elementos estructurados.
_Sistemas Operativos_
_17-09-2015_
Por ejemplo:
/*
* File:
main.c
* Author: logan
* Created on 11 de Agosto de 2015, 04:39 PM
*/
#include <stdio.h>
#include <stdlib.h>
int main( ) {
struct xyz {
char campo_1[60];
int campo_2;
float campo_3;
};
return 0;
}
Esto define una nuevo tipo de datos denominado struct xyz con los tres campos indicados. Las estructuras son a
veces llamadas tipos de datos abstractos. Por tanto, podemos declarar variables, var1 y var2, d ese tipo:
struct xyz var1, var2;
Pero como esta es una notacin un tanto incomoda, con dos nombres para designar un tipo de datos, es
conveniente definir con tydedef un sinnimo para el tipo struct xyz, de la siguiente forma:
typedef struct {
char campo_1[60];
int campo_2;
float campo_3;
} tipo;
Con esto se define el nuevo tipo de datos tipo, el cual es la estructura de datos indicada. A partir de aqu, la
declaracin de variables de este tipo se hacen con la notacin clara y convencional:
tipo var1, var2;
A los campos de la variable var1 se accede de la forma siguiente:
var1.campo_1 = "Este campo es una cadena.-";
var1.campo_2 = 5;
/* este es un campo entero */
var1.campo_3 = 10.5;
/* este es un campo de numero real */
Los punteros a una estructura se definen como los de cualquier tipo estndar:
tipo *p;
Como otros punteros, p debe ser inicializado por malloc:
p = (tipo *) malloc (sizeof tipo);
A los campos de la estructura a la que apunta p se accede con la notacin siguiente:
p->campo_1 = "Este campo es una cadena.-";
p->campo_2 = 5;
/* este es un campo entero */
p->campo_3 = 10.5;
/* este es un campo de numero real */
El smbolo -> se teclea pulsando en secuencia menos y mayor que. Consideremos como ejemplo la definicin de
tipo de datos empleado:
typedef struct {
char nombre[20];
char apellido1[20];
_Sistemas Operativos_
_17-09-2015_
char apellido2[20];
short edad;
int sueldo;
} empleado;
Una vez definida la estructura empleado, las variables de este tipo se declaran del modo usual:
empleado emp1, emp2;
En particular, un array de variables de este tipo se declara de la misma forma que el de un tipo estndar de datos:
empleado a[100]; /* array de estructuras de dimensin 100 */
Si el array a ha sido cargado de datos, stos pueden visualizarse por pantalla de la forma siguiente:
for (int i = 0; i < 100; i++) {
printf("%s, %s, %s, %d, %d\n", a[i].nombre, a[i].apellido1, \
a[i].apellido2, a[i].edad, a[i].sueldo);
}
La declaracin de un array de punteros a una estructura se hace de la forma siguiente:
empleado *p[100]; /* array de punteros a una estructura de dimensin 100 */
Si este array de punteros ha sido inicializado y luego cargado de datos, estos pueden visualizarse por pantalla de
la siguiente forma:
for (int i = 0; i < 100; i++) {
printf("%s, %s, %s, %d, %d\n", p[i]->nombre, p[i]->apellido1, \
p[i]->apellido2, p[i]->edad, p[i]->sueldo);
}
Esto completa la descripcin de los conceptos, definiciones y operadores ms comunes asociados con las
estructuras de datos. Hay otro hechos pertinentes como el que el tipo de un campo de una estructura x puede
ser otra estructura, o puede ser tambin un puntero a si misma.
/*
* File:
main.c
* Author: logan
*
* Created on 11 de Agosto de 2015, 08:51 AM
*/
#include <stdio.h>
#include <stdlib.h>
int main( ) {
typedef struct {
char campo_1[60];
int campo_2;
float campo_3;
x *campo_4;
} x;
x var;
_Sistemas Operativos_
_17-09-2015_
_Estructuras Anidadas
Una estructura puede estar dentro de otra estructura a esto se le conoce como anidamiento o estructuras
anidadas. Ya que se trabajan con datos en estructuras, si definimos un tipo de dato en una estructura y
necesitamos definir ese dato dentro de otra estructura solamente se llama el dato de la estructura anterior.
Definamos una estructura en nuestro programa:
struct empleado {
char nombre_empleado[25];
char direccion[25];
char ciudad[20];
char provincia[20];
long int codigo_postal;
double salario;
};
Y luego necesitamos una nueva estructura en nuestro programa:
struct cliente {
char nombre_cliente[25];
char direccion[25];
char ciudad[20];
char provincia[20];
long int codigo_postal;
double saldo;
};
Podemos ver que tenemos datos muy similares en nuestras estructuras, as que podemos crear una sola
estructura llamada infopersona con estos datos idnticos:
struct infopersona {
char direccion[25];
char ciudad[20];
char provincia[20];
long int codigo_postal;
};
Ahora ya se puede crear las nuevas estructuras anteriores, anidando la estructura necesaria:
struct empleado {
char nombre_empleado[25];
/* creamos direcc_empleado con "struct" del tipo "estructura
infopersona" */
struct infopersona direcc_empleado;
double salario;
};
struct cliente {
char nombre_cliente[25];
/* creamos direcc_cliente con "struct" del tipo "estructura
infopersona" */
struct infopersona direcc_cliente;
double saldo;
};
_Sistemas Operativos_
_17-09-2015_
_Ejercicios Parte I
Ej1_ Dado el siguiente fragmento de cdigo, cuanto vale n1 y n2:
float n1;
float n2;
float *p1:
float *p2;
n1 = 4.0;
p1 = &n1;
p2 = p1;
n2 = *p2;
n1 = *p1 + *p2;
R/ n1 = 8.0
n2 = 4.0;
pnumero = &num1;
Ej4_ Desarrolle un programa que haciendo uso de la reserva dinmica de memoria almacene un nmero
determinado de valores (obtenidos de forma aleatoria, entre 0 y 100) y los ordene de mayor a menor.
_Sistemas Operativos_
_17-09-2015_
Ej5_ Desarrolle un programa que pida una serie de nmeros al usuario y halle el mximo, el mnimo y la
media aritmtica de ellos. Para ello se debe crear una variable puntero tipo float, se debe pedir al
usuario que introduzca el nmero de datos, y despus los datos a operar. Recuerde que se debe reservar
memoria de forma dinmica para almacenar el vector de los datos.
Ej6_ Desarrolle un programa que permita evaluar un polinomio de cualquier grado:
P(X)=a0+a1.x+a2.x2+a3.x3++an.xn
Como no se sabe de qu grado va a ser este polinomio, se debe crear una variable puntero del tipo
double: double *coeficientes;
A continuacin se debe pedir el grado del polinomio y reservar memoria para el array de coeficientes.
Luego, a travs de un bucle se empezar a pedir los coeficientes del polinomio. Finalmente se debe
pedir el punto (x) en el que se va a evaluar el polinomio, cuyo resultado se sacar por la consola.
Tambin se debe sacar por la consola el polinomio que se ha evaluado.Ej7_ Este ejercicio consiste en hacer un programa que cuente cuantas veces se repiten las vocales (se
deben contar las maysculas y las minsculas) en un texto dado por el usuario. La estructura del
programa debe ser la siguiente:
#include<stdio.h>
#include<string.h>
char *pedirTexto();
void contarVocales(char *,int[]);
void imprimir(int []);
void main() {
char *texto;
int num[5];
texto = pedirTexto();
contarVocales(texto, num);
imprimir(num);
}
A continuacin se explican cada una de las funciones llamadas desde main:
1. La funcin pedirTexto devuelve un puntero a la cadena que el usuario ha escrito.
2. La funcin contarVocales recibe el array que contiene el texto y otro array de enteros, en el
cual va a devolver cuantas veces se repite cada una de las vocales, es decir, en num[0] vendrn
las veces que se repite la vocal a, en num[1] la vocal e y as sucesivamente.
3. La funcin imprimir recibe el array de enteros e imprime en la consola lo que ha encontrado.
Ej8 .- Desarrolle un programa que permite al usuario introducir un nmero determinado de palabras y que
de como resultado la impresin de las palabras ordenadas de forma descendente. Para ello se va a
utilizar la funcin strcmp(char*, char*) de la librera estndar del C que permite comparar dos cadenas
de caracteres. (Consulte el man de strcmp para una mejor descripcin).-
_Ejercicios Parte II
Ej1_ Crear una aplicacin que contenga los siguientes elementos:
_Una estructura llamada Titular que represente clientes con su nombre, apellidos,
direccin y dui.
_Una estructura llamada CuentaCorriente que tenga como campos, dos titulares, un
nmero de cuenta (sern 20 caracteres) y el saldo de la cuenta (double).
_Crear la funcin crearCuenta que devuelva como resultado una cuenta cuyos datos deben
leerse por teclado, pero teniendo en cuenta que: Puede haber uno o dos titulares (al
menos uno), El nmero de cuenta deben de ser exactamente 20 nmeros y El saldo debe de
ser positivo.
_Crear la funcin abonarSaldo que reciba una cuenta y un valor decimal y cambie el
_Sistemas Operativos_
_17-09-2015_
_Sistemas Operativos_
_17-09-2015_