Está en la página 1de 11

Ejercitario de C++

Vol. 2
Propiedad exclusiva de Team Compu
A pedido del pblico sale el volumen 2 del resumen/ejercitario que todos aman.
Solo voy a escribir sobre punteros y mtodos de ordenacin ya que creo que es
lo nico que le falto al anterior.

Juan Jos Cabrera Ugarte

Team Compu - C++ Vol 2


No espere que el resumen pasado les sirviese de tanto as que vamos a intentar que
este no se quede atrs. Para empezar con punteros vamos a imaginarnos que son como el
ndice de un libro: Dicen dnde est la informacin que buscamos pero en realidad ellos no
contienen esa informacin.

Punteros:
Se acuerdan que les haba dicho que las funciones usan memorias separadas? Bueno, para
entender cmo funcionan los punteros conviene imaginarnos la memoria como una planilla de
Excel: en cada celda se puede guardar un byte de informacin y stas estn referidas con un
nombre o cdigo nico. Los punteros son algo complicados as que vamos a explicar cada parte
con lujo de detalle, perdn si a alguno de ustedes le molesta esto.
Operador de direccin (&):
Los punteros en la informtica se llaman as porque apuntan a una direccin en la
memoria, pero Cmo diferencia de cuando le damos un valor a una direccin de
memoria? Para eso existe el &.
Supongamos que tenemos una variable myvar guardada en la memoria. Ahora
escribimos el siguiente cdigo:
1 foo = &myvar;

Esto lo que hace es guardar la direccin de memoria de myvar en la variable foo. As es


como la computadora interpreta el &, al poner en frente de una variable no le estamos
diciendo que guarde en foo el valor de la otra variable sino su ubicacin.
Ahora supongamos que escribimos lo siguiente:
1 myvar = 25;
2 foo = &myvar;
3 bar = myvar;

Para simplificar la comprensin de esto vamos a suponer que la direccin de memoria


se gua por nmeros decimales (en realidad son hexadecimales, pero eso voy a explicar
despus) y entonces el cdigo lo que hara sera algo como esto

Primero se guarda el 25 en myvar en un lugar cualquiera de la memoria (en este


ejemplo: 1776). Luego asignamos a foo la posicin de myvar, por eso vemos que se
guard 1776 y no 25. Finalmente asignamos a bar el valor de myvar.

Con el ejemplo anterior creo que se debera entender bien cmo funciona el &, as que
pasamos a lo siguiente en punteros.
Operador de indireccin (*):
El nombre copie del material gua de Rojitas y me entero que se llama as, pero en
punteros esto es tanto o inclusive ms importante que el operador &. Ahora sabemos
cmo guardar la direccin de memoria en una variable, pero eso no es suficiente para
considerarlo un puntero.
Manejar la ubicacin en la memoria es interesante en muchas ocasiones, como vamos
a ver al aplicar en matrices y vectores, pero de qu nos sirve manejar la direccin si
no podemos acceder al valor guardado en esa direccin? Para eso existe el *.
Teniendo siempre en cuenta el ejemplo anterior, escribimos el siguiente cdigo:
1 baz = *foo;

Bsicamente, el * sirve para acceder al valor guardado en la posicin de memoria


ingresado. Del ejemplo anterior tenemos que foo = 1776, que es la ubicacin en la
memoria de myvar. Pero al colocar el * antes de foo lo que en realidad hacemos es
guardar el valor que est en la posicin 1776 de la memoria (o sea, la posicin de
myvar), que es 25, en baz. Admito que es confuso, pero por suerte esta imagen se
explica a si misma bastante bien.

Ah ven como foo lo que hace es decir en dnde esta guardada la informacin nomas,
sin tener dicha informacin guardada en s mismo.
Con esto debera quedar claro tambin cmo funciona el operador * y probablemente se
habrn dado cuenta que estos operadores se complementan entre s: Siendo uno el que asigna
la direccin de memoria y el otro el que accede a dicha ubicacin. Ahora podemos empezar a
declarar punteros.
Declaracin de punteros:
As como todas las variables, los punteros tambin tienen tipos (int, char, float, etc.) y
lastimosamente, al igual que en los vectores y matrices, un puntero del tipo int solo
puede apuntar a una variable de tipo int.

Si, son muy plagas, pero su sintaxis por suerte no es muy complicada:
1 int * entero;
2 char * letra;
3 double * decimal;

Creo que no hace falta explicacin ya que es slo la sintaxis de cmo se declara, as
que pasamos a lo interesante
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

// ejemplo de punteros
#include <iostream>
using namespace std;

x es 10
y es 20

int main ()
{
int x, y;
int * puntero;
puntero = &x;
*puntero = 10;
puntero = &y;
*puntero = 20;
cout << "x es " << x << endl;
cout << "y es " << y << endl;
return 0;
}

Esto es un ejemplo comn de cmo funcionan los punteros, primero declaramos las
variables enteras y el puntero entero. Luego asignamos puntero a la direccin de x y a
continuacin le asignamos el valor de 10 a la posicin que apuntaba (o sea, la variable
x). Luego repetimos el proceso para y, slo que ahora le asignamos 20 y luego
imprimimos en la pantalla las variables para ver si en realidad se hizo el cambio.
En ejemplos simples como el anterior se podra pensar que el que invento los punteros fue un
gil sin vida que lo nico que hizo fue complicar todo, pero en realidad los punteros son una de
las herramientas ms potentes de C++ y en matrices/vectores veremos su potencial.
Punteros en vectores:
Se acuerdan que no se pueden imprimir los vectores directamente? Salan unos
nmeros raros que no se entendan, bueno, esos nmeros eran las direcciones de
memoria del vector. Si se preguntaron alguna vez por qu pasaba eso se debe a que el
vector acta como un puntero, es decir, en realidad el vector es un conjunto de
direcciones de memoria y no tiene valor hasta que especificamos la ubicacin
especfica con la sintaxis vector[i].
En los vectores usamos i para indicar la posicin, y al escribir vector[i] llama al valor
guardado en ese ndice. En los punteros se asigna la posicin con & y se llama al valor
guardado en ese ndice con *. Al mezclar los punteros con los vectores existen muchas
formas para asignar los ndices, pero creo que se entendera mejor con un ejemplo que
con palabras:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

// punteros en vectores
#include <iostream>
using namespace std;

10, 20, 30, 40, 50,

int main ()
{
int v[5];
int * p;
p = v;
*p = 10;
p++;
*p = 20;
p = &v[2];
*p = 30;
p = v + 3;
*p = 40;
p = v;
*(p+4) = 50;
for (int i=0; i<5; i++)
cout << v[i] << ", ";
return 0;
}

El programa en s no es la gran cosa, slo es trabajar con un vector e imprimir sus


valores, pero igual explicaremos como opera desde adentro:
10. p=v asigna la ubicacin de la primera casilla de v al puntero p. Luego se carga el
valor 10 en esa ubicacin.
11. Si suponemos que v[0] estaba en 1776, v[1] estar en 1777 ya que los vectores
reservan series de casillas contiguas para guardar sus valores. Aprovechando
esto podemos usar p++ para pasar del primer elemento al segundo luego
asignarle el valor de 20.
12. p=&v[2] capaz sea el ms fcil de entender, como v[2] ya es un valor lo que
hace es asignarle a p la ubicacin de ese valor y luego carga 30 en ese lugar.
13. As como p++ sirvi para cambiar de posicin v+3 lo que hace es ir a 3 lugares
de la posicin inicial y luego guardar 40 en esa ubicacin.
14. Esta lnea capaz se vea igual a la #10, pero a la hora de asignar el valor se ve la
diferencia. *(p+4) lo que hace es asignar el valor a 4 lugares de donde est
apuntando p, es tambin una forma viable de asignar valores, aunque parezca
rara al comienzo.
Luego sigue la impresin del vector, la cual creo que no amerita explicacin.
Aritmtica de punteros:
Cosas como la lnea #14 del ejemplo anterior capaz sean cosas raras al principio, pero
una vez que se entiende la aritmtica detrs de esto es ms simple. A continuacin
dar los ejemplos asumiendo que p es un puntero ya referenciado a una ubicacin de
la memoria.
Trabajar con p directamente lo que hace es cambiar la direccin a la que este apunta,
la aritmtica para las variables es la misma que para los punteros (++, --, *, /, %, etc).
Lo complicado esta al trabajar con la posicin al llamar al valor con *:

*p++: aumenta el valor de *p en 1


*(p++): llama al valor que se encuentra a un lugar de p
*(p+3): llama al valor que se encuentra a 3 lugares de p

*p*=5: multiplica por 5 el valor de *p y lo vuelve a guardar en esa ubicacin


*(p++)/=3: aumenta la posicin a la que apunta y luego divide su valor entre 3
para despus volver a almacenarlo en la ubicacin a la que apunta

Estas y muchas otras combinaciones se pueden utilizar, si bien son un poco complicadas al
comienzo son muy tiles cuando se aplican en programas complejos.
Notas extras:
Para trabajar con puntero y matrices el funcionamiento es idntico al de vectores, solo
que el puntero no va a tomar la matriz como tal, sino como un vector alargado con
todas las componentes una seguida de la otra.
Se puede apuntar un puntero a otro puntero, pero esto requiere una declaracin un
tanto rara (tipo_del_puntero ** nombre_de_puntero;) y esto ni aparece en el material
de Rojitas, perdn Solaeche por ocupar tu memoria con informacin innecesaria.

Mtodos de ordenacin:
Ya pasamos lo que creo que era lo ms complicado de entender que eran los punteros, y el
hecho de que me ocupo casi 5 pginas es un claro ejemplo de su complejidad. Ahora vamos a
ver los distintos mtodos de ordenacin y voy a tratar de explicar cmo funcionan, aunque
igual van a tener que memorizar al algoritmo en s.
Mtodo de Burbuja:
El mtodo que posiblemente sea el ms conocido, tambin es el mtodo ms seguro
pero el que consume ms memoria y el ms lento:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

// metodo de burbuja
#include <iostream>
using namespace std;
int validar();
int main()
{
cout << "Introducir el numero de componentes que tendra el vector: ";
int i, j, n=validar();
float v[n], aux;
cout << "\n\nIntroduzca los valores para las componentes del vector";
for(i=0; i<n; i++)
{
cout << "\n\tv[" << i+1 << "]=";
cin >> v[i];
}
for(j=0;j<n;j++)
{
for(i=0; i<n-1; i++)
{
if(v[i] > v[i+1])
{
aux = v[i];
v[i] = v[i+1];
v[i+1] = aux;
}
}

28
29
30
31
32
33
34
35
35
36
37
38
39
40
41
42
43
44

}
cout << "v[ ";
for(i=0; i<n; i++)
cout << v[i] << " ";
cout << "]";
system("pause>nul");
}
int validar()
{
float x;
cin >> x;
while (x<=0 || x!=int(x))
{
cout << "Digite un numero entero y positivo";
cin >> x;
}
return int(x);
}

Si, muy largo y memorizar todo sera una locura, lo bueno es que no es necesario. El
algoritmo del mtodo burbuja en s son solo las siguientes lneas:
17
18
19
20
21
22
23
24
25
26
27
28

for(j=0;j<n;j++)
{
for(i=0; i<n-1; i++)
{
if(v[i] > v[i+1])
{
aux = v[i];
v[i] = v[i+1];
v[i+1] = aux;
}
}
}

Este algoritmo lo que hace es recorrer el vector n veces y comparando cada


componente con las siguientes. El primer for sirve para repetir n veces el proceso,
mientras que el segundo es el encargado de ordenar comparando cada elemento con
el adyacente (por eso el segn for tiene n-1, ya que el ltimo elemento no tiene con
quien compararse).
Mtodo de Insercin:
Este mtodo es considerado el mtodo de ordenamiento comnmente utilizado por
los humanos, ahora veremos qu tanto de eso es cierto:
1
2
3
4
5
6
7
8
9
10

// metodo de insercin
#include <iostream>
using namespace std;
int validar();
int main()
{
cout << "Introducir el numero de componentes que tendra el vector: ";
int i, j, k, n=validar();
float v[n], aux;

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
35
36
37
38
39
40
41
42
43
44
45
46

cout << "\n\nIntroduzca los valores para las componentes del vector";
for(i=0; i<n; i++)
{
cout << "\n\tv[" << i+1 << "]=";
cin >> v[i];
}
for(k=0; k<=n; k++)
{
for(i=0; i<n; i++)
{
j = i;
aux = v[i];
while(j>0 and aux<v[j-1])
{
v[j] = v[j-1];
j--;
}
v[j] = aux;
}
}
cout << "v[ ";
for(i=0; i<n; i++)
cout << v[i] << " ";
cout << "]";
system("pause>nul");
}
int validar()
{
float x;
cin >> x;
while (x<=0 || x!=int(x))
{
cout << "Digite un numero entero y positivo";
cin >> x;
}
return int(x);
}

Al igual que en el mtodo de burbuja, el algoritmo en s es mucho ms corto:


17
18
19
20
21
22
23
24
25
26
27
28
29
30

for(k=0; k<=n; k++)


{
for(i=0; i<n; i++)
{
j = i;
aux = v[i];
while(j>0 and aux<v[j-1])
{
v[j] = v[j-1];
j--;
}
v[j] = aux;
}
}

Inicialmente lo introduje como el mtodo que usamos los humanos, eso es porque
toma cada valor y compara con todos los valores anteriores, ubicndolo en donde
debera estar. En esta imagen pueden ver cmo funciona en tiempo real.

Mtodo de Seleccin:
Finalmente el tercer mtodo y tambin el ms inestable segn muchos materiales,
este mtodo es muy poco recomendado aunque capaz sea uno de los ms sencillos de
entender:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
35
36
37
38
39
40
41
42
43
44

// metodo de seleccion
#include <iostream>
using namespace std;
int validar();
int main()
{
cout << "Introducir el numero de componentes que tendra el vector: ";
int i, j, k, n=validar();
float v[n], aux;
cout << "\n\nIntroduzca los valores para las componentes del vector";
for(i=0; i<n; i++)
{
cout << "\n\tv[" << i+1 << "]=";
cin >> v[i];
}
for(j=0; j<n-1; j++)
{
k = j;
for(i=j+1; i<n; i++)
{
if(v[i]<v[k])
k = i;
}
aux=v[k];
v[k]=v[j];
v[j]=aux;
}
cout << "v[ ";
for(i=0; i<n; i++)
cout << v[i] << " ";
cout << "]";
system("pause>nul");
}
int validar()
{
float x;
cin >> x;
while (x<=0 || x!=int(x))
{
cout << "Digite un numero entero y positivo";
cin >> x;
}
return int(x);
}

En los casos anteriores separamos el algoritmo de ordenacin del cdigo principal, y


este caso no ser la excepcin:

17
18
19
20
21
22
23
24
25
26
27
28

for(j=0; j<n-1; j++)


{
k = j;
for(i=j+1; i<n; i++)
{
if(v[i]<v[k])
k = i;
}
aux=v[k];
v[k]=v[j];
v[j]=aux;
}

Lo que hace este mtodo es recorrer todo el vector, en cada lugar busca en el resto del
vector hasta encontrar el menor y posicionarlo en la ubicacin evaluada. Este mtodo
es probablemente el que uno normalmente imaginara cuando se le pide ordenar un
vector.
Y bueno, eso fue todo para este resumen, si surgi alguna duda que no llegue a explicar muy
bien no duden en preguntar.

Ejercicios
1. Escribir un programa que permita cargar un vector de N componentes, el usuario
deber cargar el valor de N y las componentes individuales usando punteros. Luego
imprimirlo en pantalla.
2. Calcular la traza de una matriz usando punteros y luego imprimirlo en pantalla. La
matriz podr ser aleatoria o no, como el programador prefiera.
3. Usando punteros calcular el menor y mayor elemento de:
Un vector de 12 componentes
Una matriz de 3x4
4. Escribir un programa que, usando punteros, intercambie las componentes de las
diagonales de una matriz.
5. Usando punteros generar una matriz aleatoria de MxN componentes y luego ordenarla
por los 3 mtodos estudiados.
6. Escribir un programa que genere un vector de 5 componentes aleatorias, luego
imprima la direccin en la memoria de cada componente. Hallar una explicacin del
porqu aumentan segn un valor fijo y verificar si es o no independiente de los valores
del vector.
7. Escribir un programa que imprima la transpuesta de una matriz cargada por el usuario,
se deber implementar una funcin para dicho proceso.
8. Se dispone de dos vectores, maestro y esclavo, de componentes enteras y positivas e
igual nmero de elementos. Se deben imprimir en dos columnas adyacentes. Se
ordena el vector maestro, pero siempre que un elemento de maestro se mueva, el
elemento correspondiente de esclavo debe moverse tambin; es decir, cualquier
accin hecha con maestro[i] debe hacerse a esclavo[i]. Despus de realizar la
ordenacin se imprimen de nuevo los vectores. Escribir un programa que realice esta
tarea. Observacin: Utilizar como algoritmo de ordenacin, el mtodo de insercin.
Ejercicio by Rojitas
Personalmente busque mucho y en los finales no suelen salir punteros as que con este nivel
de ejercicios creo que deberan estar preparados para lo que venga.

También podría gustarte