Anda di halaman 1dari 12

Vectores, Matrices y Punteros en c++

con 36 comentarios
Estimados lectores y fans, les pido disculpas por este humilde y sencillo post, se que este
mini-tutorial super bsico es una humillacin a su inteligencia y profesionalismo, pero
comprendan que esto va dedicado a personas que como yo recin empiezan con sus
primeros pininos en C++. Espero de verdad le sea til a alguien.
Escribir todo esto, me cost una noche entera y mucho caf. Parte de los conceptos aqu
los aprend en clases de la U y mucho tambin lo aprend por cuenta propia. As que
agradecimientos al teacher Patricio del cual aprend muchsimo. Una vez ms a ustedes y a
los tantos miles de seguidores que me leen a diario las disculpas del caso.
Vamos ir avanzando de a pocos as que no se preocupen y desesperen porfavor, paciencia.
La idea es que esta seccin crezca con su ayuda, feedback y motivacin. Luego vamos a
ver ejemplos con objetos, clases, sobrecarga de operadores, mtodos de bsqueda, ms
ordenacin, punteros, listas, pilas, colas, templates por ahora sigo practicando y
haciendo simples cosas con este lenguaje. Los cdigos los compil con g++, el
compilador de GNU.
VECTORES
Un vector, tambin llamado array(arreglo) unidimensional, es una estructura de datos que
permite agrupar elementos del mismo tipo y almacenarlos en un solo bloque de memoria
juntos, uno despues de otro. A este grupo de elementos se les identifica por un mismo
nombre y la posicin en la que se encuentran. La primera posicin del array es la posicin
0.
Podramos agrupar en un array una serie de elementos de tipo enteros, flotantes,
caracteres, objetos, etc. Crear un vector en c++ es sencillo, seguimos la siguiente
sintaxix: Tipo nombre[tamanyo];
Ejm:
1 int a[5];//Vector de 5 enteros
2 float b[5];//vector de 5 flotantes
3 Producto product[5];//vector de 5 objetos de tipo Producto
Podramos tambin inicializar el vector en la declaracin:
1 int a[] = {5,15,20,25,30};
2 float b[] = {10.5,20.5,30.5,12.5,50.5}
3 Producto product[] = {celular,calculadora,camara,ipod,usb}
Como hay 5 elementos en cada array, automticamente se le asignar 5 espacios de
memoria a cada vector.Pero si trato de crear el vector de la forma int a[]; el compilador

mostrar un error, porque no indiqu el tamao del vector ni tampoco inicializ sus
elementos.
Asigno valores a los elementos de un vector indicando su posicin:
1 int a[4] = 30; // le asigno el valor 30 a la posicin 4 del vector, es
decir, al 5to elemento.
product[2].setPrecio(300) // le asigno un precio de 300 al producto en
2
la posicion 2, o sea al tercer elemento.
Obviamente el mtodo setPrecio() debe de estar implementado.
Para llenar, recorrer e imprimir un vector podemos utilizar un bucle for:
01 #include <iostream>
02 using namespace std;
03
04 int main()
05 {
06

int dim;

07
08

cout << "Ingresa la dimension del vector" << endl;


cin >> dim; // Supongamos que ingrese 10

09

int vector[dim]; // mi vector es de tamanyo 10

10
11
12
13
14

for(int i=0;i < dim;i++){


vector[i] = i * 10;
cout << vector[i] << " ";
}

15
16

return 0;

17 }
La salida del programa mostrar: 0 10 20 30 40 50 60 70 80 90
Fcil verdad? Bien ahora creen 2 o ms vectores y empiecen a hacer funciones bsicas
como sumar, restar, buscar, ordenar, moda, etc que ayudan mucho a ir desarrollando la
lgica. No vale copiar y pegar, mejor es practicar, practicar y practicar.
Aqu una funcin simple para sumar 2 vectores a y b y poner el resultado en un tercer
vector c
01 #include <iostream>
02 using namespace std;
03

04 void sumar(int a[], int b[], int c[],int dim){


05

for (int i=0; i<dim; i++) {


c[i]=a[i] + b[i];

06
07
08 }

09
10 void imprimir(int v[],int dim)
11 {
12
13
14
15
16 }

for(int i=0;i<dim;i++){
cout << v[i] << " ";
}
cout << endl << endl;

17
18 int main()
19 {
20

int dim;

21

cout << "Ingresa la dimension" << endl;


cin >> dim;

22
23
24

int a[dim];

25

int b[dim];

26

int c[dim];

27
28

for(int i=0;i<dim;i++){

29
30

a[i] = i * 10;
b[i] = i * 5;

31

32
33
34

cout << "Vector A " << endl;


imprimir(a,dim);

35
36

cout << "Vector B " << endl;

37

imprimir(b,dim);

38
39

sumar(a,b,c,dim);

40

cout << "Vector C " << endl;

41
42

imprimir(c,dim);

43

return 0;

44 }
Este programa me botara (si ingreso una dimensin de 10):
Vector A
0 10 20 30 40 50 60 70 80 90
VECTOR B
0 5 10 15 20 25 30 35 40 45
VECTOR C
0 15 30 45 60 75 90 105 120 135
Entonces para tomar en cuenta:
Todo vector debe tener definido un tipo de dato.
Todo vector necesita de una dimensin o tamanyo.
El cdigo de arriba se puede mejorar muchsimo con objetos y clases, este es solo un
pequeo ejemplo.
MATRICES
Una matriz es un vector de vectores o un tambin llamado array bidimensional. La manera
de declarar una matriz es c++ es similar a un vector:
1 int matriz[fils][cols];
int es el tipo de dato, matriz es el nombre del todo el conjunto de datos y debo de
especificar el numero de filas y columnas. Las matrices tambin pueden ser de distintos
tipos de datos como char, float, double,etc.
Las matrices en c++ se almacenan al igual que los vectores en posiciones consecutivas de
memoria. Usualmente uno se hace la idea que una matriz es como un tablero. Pero
internamente el manejo es como su definicion lo indica, un vector de vectores, es decir,
los vectores estan uno detras del otro juntos.
La forma de acceder a los elementos de la matriz es utilizando su nombre e indicando los
2 subindices que van en los corchetes. Si Coloco int matriz[2][3]=10; //estoy asignando al
cuarto elemento de la tercera fila el valor 10. No olvidar que tanto filas como columnas se
enumeran a partir de 0.
Bueno y para recorrer una matriz podemos usar igualmente un bucle. En este caso 2 for
1 for(int i=0;i<fils;i++){
2
3
4

for(int j=0;j<cols;j++){
matriz[i][j] = i % j;
}

5}
PUNTEROS
El valor de todas las variales que manejamos en nuestros programas se almacenan en

memoria y tienen una direccin. Un puntero es una variable especial que apunta a la
direccin de memoria de una variable. El puntero tiene a su vez su propia direccin. Todas
estas direcciones tienen un formato hexadecimal.
Los punteros son herramientas muy poderosas con muchas utilidades y enormes ventajas
como veremos ms adelante. A grandes rasgos, un puntero me permite desplazarme en la
memoria, apuntar, redireccionar a ciertas variables, funciones, mtodos, objetos sin
necesidad de mover grandes bloques de datos, lo cual nos ahorra muchsimo el consumo
de memoria en los programas.
Un puntero se debe declarar de acuerdo al tipo de dato al que apunta. Ejem:
1 int *var; //Un puntero llamado var que podra apuntar a cualquier
variable de tipo entero.
2 char *u;//puntero de tipo char
3 Persona *per;//puntero de tipo persona
Para determinar,asignar la direccin de una variable en c++, se usa el operador & y para
obtener el contenido de un puntero utilizamos el operador * Ejem:
1 int a;//entero
2 int *b;//puntero a entero
3 a = 20;//a tiene 20
4 b=&a;//asigno la direccion de a al puntero b
5
6 cout << b << endl; // imprira la direccion de memoria de a;
7 cout << *b;// imprimira 20, osea el contenido de a
Ahora analicemos las siguientes instrucciones y veamos como las variables van cambiando
de valor en tiempo de ejecucin:
01 #include <iostream>
02 using namespace std;
03 int main () {
04

int a=10;

05

int b=20;

06

int *p,*p2;//punteros de tipo entero

07
08

cout << "ANTES" << endl;

09

cout << "Variable a = " << a << endl;

10
11
12

cout << "Direccion de a = " << &a << endl << endl;

13

cout << "Variable b = " << b << endl;

14

cout << "Direccion de b = " << &b << endl << endl;

15
16

cout << "Contenido de p (BASURA)= " << *p << endl;//tiene basura al


principio, podria inicializar con *p=0

17

cout << "Direccion de p = " << &p << endl << endl;

18
19
20

cout << "DESPUES" << endl;


a++;//incremento a

21

p= &a; //p ahora tiene a la direccion de a

22
23

cout << "Contenido de p =

" << *p << endl;

24
25

p = &b;//p ahora tiene la direccion de b


*p +=20; // le sumo 20 al contenido de p, es decir, estoy
26
incrementando el valor de b
27
28

cout << "Variable a = " << a << endl;

29

cout << "Variable b = " << b << endl << endl;

30
31
32

p=&a;//p ahora tiene la direccion de a


*p = a * 5;//contenido de p es igual al contenido de a * 5

33
34

cout << "Contenido de p = " << *p << endl;

35

cout << "Variable a = " << a << endl << endl;

36
37

cout << "Contenido de p2 (BASURA) = " << *p2 << endl;//tiene basura
al principio, podria inicializar con *p2=0

38

cout << "Direccion de p2 = " << &p2 << endl << endl;

39
40

p2 = p;//el contenido de p es asignado al contenido de p2

41

*p2 +=15;//incremento 15 al contenido de p2

42
43

cout << "Contenido de p2 = " << *p2 << endl;//igual al contenido de


p

44

p++;//p apunta a otra direccion de memoria,se desplaza 4 bytes en


memoria

45

cout << "Contenido de p (BASURA) = " << *p << endl;//el contenido


de esa nueva direccion

46

47

return 0;

48 }
La salida del programa:
ANTES
Variable a = 10
Direccion de a = 0x22ff74
Variable b = 2
Direccion de b = 0x22ff70
Contenido de p (BASURA)= -1017291943
Direccion de p = 0x22ff6c
DESPUES
Contenido de p = 11
Variable a = 11
Variable b = 40
Contenido de p = 55
Variable a = 55
Contenido de p2 (BASURA) = 2293680
Direccion de p2 = 0x22ff68
Contenido de p2 = 70
Contenido de p (BASURA) = 2293680
El contenido de p y p2 al principio es basura porque no tienen ningun valor asignado aun.
Podriamos asignar el valor NULL a un puntero para luego posteriormente en algun
problema que se me presente saber el estado del puntero y saber si contiene algo o no,
as:
int *p= NULL;
ARITMTICA DE PUNTEROS
En las ultimas sentencias del programa anterior:
p++;
cout << *p;
Pueden visualizar que estoy incrementando el puntero p en 1. Esto quiere decir que el
puntero se desplazara 4 bytes en memoria (en este caso por ser entero) y entonces
apuntara a otra direccion. Por eso es que el nuevo contenido de p es basura o bueno el
contenido de lo que tiene esa nueva direccion a la que apunta.
Supongamos que definir un entero y puntero de tipo char:
1 char c;
2 char *d;
3

4 d= &c;//asigno la direccion de c a d
5 c='u';//asigno el valor u a mi variable c
6 c--;//desplazo una posicion a c
7 cout << *d;//
No Imprimira u porque fijense que desplaz c en sentido negativo 1 byte (los char
ocupan a 1 byte). Es decir, que si d estaba apuntado a una direccion como por ejemplo
0x22ff99, despues del c estara apuntando a algo como 0x22ff98
Para tomar en cuenta cosas que no puedo hacer con punteros:
01 int a=15;
02 int *p;
03
04 double *q;
05 void *r;
06
p = a; //No puedo hacer esto porque estoy asignando una variable a un
puntero y un puntero es una direccion.
p = &50; // 50 es un valor constante en este caso y no una variable,por
08
lo tanto no tiene direccion
07

09 p = &(a+1); //una expresion no tiene direccion


10 p = 30;//igual que el primer error, 30 es un entero.
11 &a = p;//no puedo cambiar la direccion de una variable
12 p = q;//p es puntero de tipo entero y q de tipo double
Un puntero de tipo void, es un puntero al cual le podemos asignar cualquier tipo de
puntero. Por lo tanto si podriamos hacer esto:
r = p;
VECTORES Y PUNTEROS
Cuando declaramos un vector int v[10];El nombre del vector, o sea v, es un puntero al
primer elemento del vector, es decir a v[0].Entonces como un vector es un puntero al
primer elemento del mismo, tambin podramos hacer aritmtica de punteros con el
vector.
1 (v+1) ;//apuntara a v[1];
2 *(v+5);//me refiero al contenido de v[5]
3
4 //Y tambin a los punteros les puedo poner ndices:
5
6 int *p; //puntero de tipo entero
p = &v[0];//p apunta a la direccion del vector v[0] o tambien a v. p =
v
8 p[8] = 80; //le asigno el valor 80 al puntero en la posicion 8, es decir
7

a v[8]
VECTORES DINMICOS
Lo que vimos en el inicio de este post, son vectores estticos, puesto que tienen una
cantidad fija de memoria asignada y tamao definido que no podemos modificarlo. Sin
embargo, un vector podra tener una cantidad variable de datos, a este se le llama un
vector dinmico.
Para usar vectores dinmicos necesitamos gestionar memoria dinmica. Si bien es cierto
que es trae enormes ventajas, el hacer un mal uso de la memoria dinmica nos podra
traer problemas desastrozos. Por eso es importante que que cuando creemos vectores
dinmicos tambin liberemos la memoria utilizada. Obviamente eliminaremos la memoria
utilizada cuando ya no necesitamos ms usar, en este caso, un determinadao vector.
El operador new sirve para reservar memoria dinmica.
El operador delete se usa para liberar la memoria dinmica reservada con new.
Para liberar memoria de un array dinmico usamos delete[]
El espacio de memoria que hemos reservado con new tendr vida hasta que finalize la
ejecucin del programa o cuando liberemos ese espacio con delete. Siempre es
recomendable liberar memoria para posteriormente no tener problemas con excesivo
consumo de memoria.
Un simple ejem:
01 #include <iostream>
02 using namespace std;
03
04 int main()
05 {
06

int *pv;

07

int dim;

08
09
10

cout << "Ingresa el tamanyo del vector" << endl;


cin >>dim;

11

pv = new int[dim];

12
13
14

for(int i=0;i<dim;i++){
pv[i] = i * i;

15
16

cout << pv[i] << " ";

17
18

delete[] pv;

19

return 0;

20 }
MATRICES Y PUNTEROS
Supongamos que se declar una matriz int m[5][5]
Como dijimos anteriormente, el nombre o identificador de un vector es un puntero al
primer elemento del vector. En el caso de matrices el nombre de la matriz, en este
ejemplo v, es un puntero que apunta al primer elemento del primer vector de la matriz.
Entonces m es un doble puntero.m es igual a &m[0] que es igual a la direccion de
&m[0][0].
Si declaramos un puntero int *pm y luego igualamos pm = m, p ahora puede desplazarse
por los valores de m.
*p;//contenido de m[0],el cual apunta al primer elemento de ese vector, es decir, m[0][0]
Tambin puedo referirme a los contenidos con aritmtica de punteros
*(p+1);//Desplazo una posicion a p,se refiere al contenido de m[1],el
cual apunta al primer elemento de ese vector, es decir, m[1][0]
*(*(p+1)+1);//desplazo una posicin en el vector principal y este a su
2 vez se desplaza una posicion en ese vector. es decir,me refiero al
contenido de m[1][1];
1

3
4 p[2][4] = 20;//asigno el valor 20 a la posicion 2,4 de la matriz
5 *(*(p+2)+4) = 20 // es lo mismo que la asignacion anterior
6 *(pm[2]+4) = 20 // tambien los mismo
7
8 //En conclusin:
9 p[i][j] = *(*(p+i)+j) = *(pm[i]+j)
MATRICES DINMICAS
Para crear una matriz dinmica debemos de crear un doble puntero int **pm y samos al
igual que los vectores el operador new para reservar memoria y delete para liberar.
Primero tenemos que crear el vector que contendr a otros vectores especificando el
numero de vectores que tendra este vector principal. Ejem:
1 pm = new int* [fils];//creo el vector de punteros principal
2 for(int i=0;i<fils;i++){
pm[i] = new int [cols];//para crear los vectores dentro del vector
principal
4}
3

Ahora s vamos al grano y veamos un simple programa que crea una matriz dinmica,
asigna valores, muestra el contenido de cada uno de los elementos los elementos as
como sus direcciones de memoria.
Tambin mostramos la matriz usando aritmtica de punteros,ah va:
01 #include <iostream>
02 using namespace std;
03
04 int main()
05 {
06

int **pm;//puntero a una matriz

07

int fils,cols;

08
09
10

cout << "Ingresa el nro de filas: ";


cin >>fils;

11
12

cout << endl;

13
14

cout << "Ingresa el nro de columnas: ";


cin >>cols;

15
16

pm = new int* [fils];

17

for(int i=0;i<fils;i++){

18
19

pm[i] = new int [cols];


}

20
21

cout << "Elementos de la Matriz con sus direcciones" << endl;

22

for(int i=0;i<fils;i++){

23
24
25
26
27
28
29
30

for(int j=0;j<cols;j++){
pm[i][j] = i + j;
cout << pm[i][j] << "--> ";
cout << &pm[i][j] << " ";
}
cout << endl;
}
cout << endl;

31
32

cout << "La matriz con aritmetica de punteros" << endl;

33

for(int i=0;i<fils;i++){

34

for(int j=0;j<cols;j++){

35
36

*(*(pm+i)+j) = i + j;//aritmetica de punteros


cout << *(*(pm+i)+j) << "-->";

37
38

cout << &pm[i][j] << " ";

39
40

}
cout << endl;
}

41
42

for(int i=0;i<fils;i++){

43
44

delete[] pm[i];//elimino cada vector de la matriz


}

45

delete[] pm;//elimino el vector principal

46

return 0;

47 }
La salida del programa:
Ingresa el nro de filas: 6
Ingresa el nro de columnas: 4
01 //Elementos de la Matriz con sus direcciones
02 0> 03d2c90 1> 03d2c94 2> 03d2c98 3> 03d2c9c
03 1> 03d2ca8 2> 03d2cac 3> 03d2cb0 4> 03d2cb4
04 2> 03d2cc0 3> 03d2cc4 4> 03d2cc8 5> 03d2ccc
05 3> 03d3ab8 4> 03d3abc 5> 03d3ac0 6> 03d3ac4
06 4> 03d3ad0 5> 03d3ad4 6> 03d3ad8 7> 03d3adc
07 5> 03d3ae8 6> 03d3aec 7> 03d3af0 8> 03d3af4
08
09 //La matriz con aritmetica de punteros
10 0> 03d2c90 1> 03d2c94 2> 03d2c98 3> 03d2c9c
11 1> 03d2ca8 2> 03d2cac 3> 03d2cb0 4> 03d2cb4
12 2> 03d2cc0 3> 03d2cc4 4> 03d2cc8 5> 03d2ccc
13 3> 03d3ab8 4> 03d3abc 5> 03d3ac0 6> 03d3ac4
14 4> 03d3ad0 5> 03d3ad4 6> 03d3ad8 7> 03d3adc
En mi caso esa son las direcciones de memoria. Bueno ya que hemos revisado conceptos
bsicos a continuacin veamos la Clase Matriz, su definicin, algunos mtodos y su
implementacin.