Programación C
Programación C
Programación en C++
Primera Edición
1. Introducción a C++ 1
1.1. Qué es programar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2. Lenguaje de programación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3. Qué es un IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.1. CodeBlocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.2. Geany . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3.3. Dev C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3.4. OnlineGBD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.4. Instrucciones básicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.5. Mi primer programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.5.1. Estructura del código fuente . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.6. Comentarios en C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.7. Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.7.1. Tipos de variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.8. Entrada y salida de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.9. Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.9.1. Operadores aritméticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.9.2. Operadores de asignación . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.10. Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.11. Conversión de tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.12. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3. Datos estructurados 28
3.1. Vectores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.1.1. Inicialización de vectores . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.2. Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.2.1. Inicialización de matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.3. Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2
3.4. Estructuras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.4.1. Estructuras Anidadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.5. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4. Números aleatorios 38
4.1. Generación de números aleatorios enteros . . . . . . . . . . . . . . . . . . . . . . 38
4.2. Generación de números aleatorios decimales . . . . . . . . . . . . . . . . . . . . . 40
4.3. Evaluación de integrales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.4. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5. Funciones 45
5.1. Definición de función . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.2. Parámetros por defecto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
5.3. Tipos de datos que devuelve una función . . . . . . . . . . . . . . . . . . . . . . . 47
5.4. Funciones void . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
5.5. Almacenamiento de variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5.5.1. La Pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
5.5.2. Estado de la pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
5.6. Funciones recursivas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.7. Paso por variable o referencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.7.1. Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.7.2. Paso por referencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
5.8. Paso de parámetros tipo estructura . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.9. Sobrecarga de funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
5.10. Paso de parámetros de tipo vector . . . . . . . . . . . . . . . . . . . . . . . . . . 59
5.11. Paso de parámetros de tipo array . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.12. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
1 | Introducción a C++
El lenguaje C++ (se lee C plus plus) fue creado a mediados de los años 80 y es uno de los
lenguajes de programación más utilizados. De hecho muchos de los programas que utilizamos
diariamente están hechos en lenguaje C++, por ejemplo: los sistemas operativos Windows, Linux
y macOS, los programas de Office, el sistema Android, entre muchos otros.
Como ejemplo nos vamos a ubicar sobre un auto de Fórmula 1, si deseamos que el auto acelere
esto se lo diremos presionando el acelerador, o si deseamos que disminuya la velocidad esto se
lo diremos presionando el freno.
Con los ordenadores sucede lo mismo. Harán lo que les hayamos dicho que hagan. Las instruc-
ciones que damos al ordenador, se pueden dar directamente, en su propio lenguaje, o pueden
estar ya integradas en un paquete que instalemos.
1
CAPÍTULO 1. INTRODUCCIÓN A C++ 2
De modo general, programar consiste en dar una serie de instrucciones a la máquina para que
esta se comporte de una determinada manera. Estas instrucciones se guardan dentro de un pro-
grama informático o aplicación.
Como los programas pueden guardarse en la memoria del ordenador, el usuario, cada vez que
quiera realizar una tarea que ya está definida en un programa, sólo tiene que abrirlo y ejecutar.
El código máquina: El lenguaje (señales eléctricas almacenadas como unos y ceros) que
entiende el ordenador, y en el cual debe recibir las órdenes para ejecutarlas.
Estos dos lenguajes no son iguales, por lo que necesitamos un instrumento que pueda traducir
el código fuente a código máquina, si queremos que el ordenador entienda lo que le decimos en
el código fuente. Este instrumento es el compilador.
Por otra parte, el programador necesita una aplicación en donde poder escribir el código fuente.
CAPÍTULO 1. INTRODUCCIÓN A C++ 3
3. Visualización documentos: Ventana en la cual se muestran los archivos sobre los cuales se
están trabajando. Permite identificar la jerarquía de los archivos.
4. Compilador y depurador: A partir del archivo en código fuente, crea un archivo en código
máquina, además, se indican los errores que tiene el código.
1.3.1. CodeBlocks
Es una de las principales aplicaciones de Entorno de Desarrollo Integrado para C++. Para su
descarga ingresamos a su sitio oficial: http://www.codeblocks.org/downloads/26.
Allí tenemos varias opciones para descargar la aplicación. Dependiendo del sistema operativo
que disponga el ordenador, iremos a la sección de Windows, Linux 32, Linux 64, o Mac OS X.
CAPÍTULO 1. INTRODUCCIÓN A C++ 4
1.3.2. Geany
Es una aplicación de Entorno de Desarrollo Integrado que se adapta bastante bien a la pro-
gramación con C++. Para su descarga ingresamos a su sitio oficial: http://www.geany.org/
Download/Releases
La instalación de los IDEs se realiza todo por defecto (a todo le damos siguiente).
1.3.4. OnlineGBD
Es una aplicación online muy utilizada en la actualidad que permite correr códigos en C++,
Java, Phyton, entre otros.
Si no se utiliza la instrucción using namespace std, entonces los nombres cout y endl del
código anterior se deberían escribir como std::cout y std::endl.
int main( )
Esta estructura es la función principal que contiene el código. Lo que se escriba dentro de
las llaves de esta función es el código fuente en sí, es decir el programa que se ejecutará.
La primera palabra int, nos dice el tipo del valor de retorno de la función, en este caso
un número entero. La función main siempre devuelve un entero. La segunda palabra es el
nombre de la función, en general será el nombre que se usa para realizar el llamado a la
función.
En segundo lugar, el operador de inserción (<<), que indica que lo que sigue debe inser-
tarse (mostrarse en pantalla).
Por último, una frase entre comillas (Hola Mundo), que es el contenido insertado.
Estas dos últimas partes se repiten para volver a insertar otro elemento, es decir repetimos
el operador de inserción (<<) y luego indicamos lo que debe insertarse, en este caso es un
salto de línea que se indica mediante la instrucción endl.
return 0;
La palabra return es reservada propia de C++. Indica al programa que debe abandonar la
ejecución de la función y continuar a partir del punto en que se la llamó. El 0 es el valor de
retorno de nuestra función. Cuando main retorna el valor 0 indica que todo ha marchado
bien.
Comentario en bloque: Texto encerrado entre /* y */, puede ocupar más de una línea.
No se pueden anidar, es decir, no se puede colocar un comentario dentro de otro.
CAPÍTULO 1. INTRODUCCIÓN A C++ 7
Comentario de línea: Texto que inicia con //. Una vez escritos estos dos caracteres lo
que queda de línea se considera un comentario.
1.7. Variables
Lo contrario de una salida de datos (mensajes en pantalla) es una entrada de datos. En la entrada
de datos el usuario escribe un dato por teclado, y éste dato es recogido por el ordenador.
Sin embargo, para poder recoger los datos necesitamos antes tener un recipiente en donde guar-
darlo, y éste será la variable. A continuación, se muestra un programa que emplea variables para
almacenar un texto y un número.
Una variable es una parte de la memoria del ordenador en donde se almacena un dato.
CAPÍTULO 1. INTRODUCCIÓN A C++ 8
Cada variable necesita un nombre que la identifique, y que la diferencie de las demás. Adicio-
nalmente, en C++ debemos indicar el tipo de dato que queremos almacenar (número, cadena
de letras, etc.).
Al dato que se almacena en la variable se le llama valor. Podemos cambiar el valor (el dato que
se almacena) de una variable, siempre que sea del tipo indicado.
1. bool: Las variables de este tipo sólo pueden tomar dos valores true o false. Sirven para
evaluar expresiones lógicas.
Por lo general utiliza 1 byte de memoria, valores: true o false.
2. char: Es el tipo básico alfanumérico, es decir que puede contener un carácter, un dígito
numérico o un signo de puntuación.
Utiliza generalmente 1 byte de memoria, permite almacenar un carácter, valores; 256
caracteres.
3. unsigned short int: Las variables enteras almacenan números enteros dentro de los límites
de su tamaño, a su vez, ese tamaño depende de la plataforma del compilador, y del número
de bits que use por palabra de memoria
Utiliza generalmente 2 bytes de memoria, valores: de 0 a 65535.
5. int:
Utiliza generalmente 4 bytes de memoria, valores: de -2147483648 a 2147483647.
6. float: Las variables de este tipo almacenan números en formato de coma flotante y expo-
nente, para entendernos, son números con decimales.
Utiliza generalmente 4 bytes de memoria, valores: de 1,2 × 10−38 a 3,4 × 10+38 .
7. double: Las variables de este tipo almacenan números en formato de coma flotante y
exponente, al igual que float, pero usan mayor precisión.
Utiliza generalmente 8 bytes de memoria, valores: de 2,3 × 10−308 a 1,8 × 10+308 .
11 return 0;
12 }
En el siguiente enlace se muestran todos los tipos de variables que admite C++:
⋄ http://www.cplusplus.com/doc/tutorial/variables/
donde: variable 1, variable 2 y variable n son variables. Esta instrucción provoca la lectura de
datos desde la entrada estándar, que por defecto está asociada al teclado, y su almacenamiento
en las variables especificadas en la instrucción.
Los nombres de las instrucciones anteriores provienen de Character OUTput y Character INput.
1.9. Operadores
Los operadores son elementos que disparan ciertos cálculos cuando son aplicados a variables u
otros objetos en una expresión. Primero revisemos algunas definiciones importantes:
CAPÍTULO 1. INTRODUCCIÓN A C++ 10
Operando: cada una de las cantidades, constantes o variables o expresiones que intervie-
nen en una expresión.
Expresión: según el diccionario, “Conjunto de términos que representan una cantidad”,
entre nosotros es cualquier conjunto de operadores y operandos, que dan como resultado
una cantidad.
Existe una división en los operadores atendiendo al número de operandos que afectan (unitarios,
binarios o ternarios).
En cuanto a los operadores binarios existen varios: ’+’, ’-’, ’*’ y ’/’, tienen un comportamiento
análogo, ya que admiten variables enteras y de coma flotante.
<expresión> + <expresión>
<expresión> - <expresión>
<expresión> * <expresión>
<expresión> / <expresión>
Evidentemente se trata de las conocidísimas operaciones aritméticas de suma, resta, multiplica-
ción y división.
1 # include < iostream >
2 using namespace std ;
3
4 int main (){
5 int a , b ;
6 cout << " Ingrese dos numeros enteros positivos : " << endl ;
7 cin >> a >> b ;
8 // Empleamos operadores binarios
9 cout << " Suma : " << a + b << endl ;
10 cout << " Resta : " << a - b << endl ;
11 cout << " Multiplicacion : " << a * b << endl ;
12 cout << " Division : " << a / b << endl ;
13
14 return 0;
15 }
CAPÍTULO 1. INTRODUCCIÓN A C++ 11
El operador de módulo %, devuelve el resto de la división entera del primer operando entre el
segundo. Por esta razón, no puede ser aplicado a operandos en coma flotante.
<expresión> % <expresión>
Por último, otros dos operadores unitarios un tanto especiales, ya que sólo pueden trabajar
sobre variables, pues realizan una asignación. Se trata de los operadores ’++’y ’- -’. El primero
incrementa el valor del operando y el segundo lo decrementa, ambos en una unidad.
<variable> ++ (post-incremento)
++ <variable> (pre-incremento)
<variable>-- (post-decremento)
-- <variable> (pre-decremento)
Si se desea escribir una expresión como a = a+8, en la que se incrementa el valor de una va-
riable en una cantidad, entonces se puede utilizar el operador += de la siguiente forma: a += 8.
Esta última expresión incrementa la variable que aparece a la izquierda del operador += en una
cantidad dada.
Los operadores -=, *=, /= y %= tienen un comportamiento análogo a += pero aplicados a la resta,
multiplicación, división y módulo, respectivamente.
1.10. Constantes
Una constante es una variable que almacena un valor que no varía a lo largo de la ejecución
de un programa. En C++ se puede definir una constante anteponiendo al tipo de variable la
palabra reservada const.
Por convención, los nombres de las constantes se escriben en mayúsculas y se ubican en las
primeras líneas del código.
CAPÍTULO 1. INTRODUCCIÓN A C++ 13
En el caso de una operación entre un número entero y un número real el entero se convierte
implícitamente a real, realizándose la operación entre reales.
(tipo) operando
1.12. Ejercicios
1. Escriba un programa que reciba dos números enteros y muestre en pantalla el producto
de dichos números.
3. Realice un programa que calcule el valor que toma la siguiente función para valores dados
de x e y: √
x3
f (x, y) = 2
y +1
4. Escriba un programa que reciba la temperatura media de la ciudad de Quito medida
en grados Celcius y muestre en la salida estándar la temperatura expresada en grados
Fahrenheit, Kelvin y Rankine.
Operador Significado
< menor que
> mayor que
<= menor o igual que
>= mayor o igual que
== igual que
!= distinto de
A continuación, un programa que verifica si los dos números enteros ingresados por el usuario
son iguales:
15
CAPÍTULO 2. SENTENCIAS CONDICIONALES Y REPETITIVAS 16
Operador Significado
&& conjunción
|| disyunción
! negación
Una expresión lógica compuesta puede contener operadores aritméticos, relacionales y lógicos.
Se recomienda emplear paréntesis en las expresiones lógicas compuestas, con el fin de separar e
identificar cada una de las expresiones lógicas simples.
A continuación, un programa que verifica si los dos números ingresados por el usuario son iguales
y pares a la vez:
1 # include < iostream >
2 using namespace std ;
3
4 int main (){
5 int a , b ;
6 bool res ;
7 cout << " Ingrese dos numeros enteros " << endl ;
8 cin >> a >> b ;
9
10 // Expresion logica compuesta
11 res = ( a == b ) && ( a %2 == 0);
12 cout << " Resultado : " << res << endl ;
13
14 return 0;
15 }
En los siguientes enlaces se presentan a mayor detalle los operadores lógicos y relacionales:
http://y2u.be/7rnxBgZsWQ0
http://y2u.be/MUznvpgtn9g
if(expresión lógica){
bloque de instrucciones 1
} else {
bloque de instrucciones 2
}
CAPÍTULO 2. SENTENCIAS CONDICIONALES Y REPETITIVAS 17
A continuación, un ejemplo que permite identificar si el número entero ingresado por el usuario
es par o impar:
1 # include < iostream >
2 using namespace std ;
3
4 int main (){
5 int a ;
6 cout << " Ingrese un numero entero " << endl ;
7 cin >> a ;
8
9 // Sentencia condicional
10 if (( a % 2) == 0){
11 cout << " El numero ingresado es par " << endl ;
12 } else {
13 cout << " El numero ingresado es impar " << endl ;
14 }
15 return 0;
16 }
Las raíces reales de un polinomio de segundo grado de la forma: ax2 + bx + c = 0, pueden ser
obtenidas mediante la expresión:
√
−b ± b2 − 4ac
x1,2 =
2a
a continuación, se presenta un programa que permite obtener dichas raíces en el caso que existan.
CAPÍTULO 2. SENTENCIAS CONDICIONALES Y REPETITIVAS 18
switch (expresion){
case literal1:
bloque de instrucciones 1
break;
case literal2:
bloque de instrucciones 2
break;
......
case literaln:
bloque de instrucciones n
break;
default:
bloque de instrucciones por defecto
break;
}
La sentencia switch primero evalúa la expresión, misma que aparece en el paréntesis. La expresión
debe producir un resultado de tipo entero, caractér o lógico. A continuación, se compara el
resultado de evaluar la expresión con los literales que aparecen en los casos.
Si el resultado de evaluar la expresión coincide con el literal de algún caso, entonces se ejecuta
el conjunto de instrucciones asociado al caso y el conjunto de instrucciones asociadas al resto de
casos que aparecen con posterioridad hasta que se ejecuta la instrucción break que provoca que
se salga de la ejecución de la instrucción switch.
La sintaxis es la siguiente:
while(expresión lógica){
bloque de instrucciones
}
En primer lugar, se evalúa la expresión lógica. Si el resultado de la evaluación es el valor falso, en-
tonces termina la ejecución de la instrucción while. Si el resultado de la evaluación es verdadero,
entonces se ejecuta el conjunto de instrucciones asociado a la instrucción while. Una vez ejecu-
tado el conjunto de instrucciones se vuelve a evaluar la expresión lógica y se procede como antes.
Ahora analicemos un programa que suma todos los números ingresados por el usuario, para
finalizar el proceso es necesario teclear el número 999:
1 # include < iostream >
2 using namespace std ;
3
4 int main () {
5 int num , suma ;
6
7 cout << " ------- Programa Suma ------- " << endl ;
8 num = 0;
9 suma = 0;
10
11 while ( num != 999){
12 suma += num ;
13 cout << " Ingresa un numero ( teclea 999 para terminar ): "
14 << endl ;
15 cin >> num ;
16 }
17 cout << " La suma total es : " << suma << endl ;
18
19 return 0;
20 }
CAPÍTULO 2. SENTENCIAS CONDICIONALES Y REPETITIVAS 22
Finalmente, se muestra un programa que recibe dos números a, x con |x| < 1 y determina el
menor valor de n para el que se cumple la expresión:
a ∑
n
− axi < 10−7
1 − x i=0
La sintaxis es la siguiente:
do {
bloque de instrucciones
} while (expresión lógica);
Una vez ejecutado el conjunto de instrucciones se evalúa la expresión lógica. Si el resultado de
la evaluación es verdadero se vuelve a ejecutar el conjunto de instrucciones, así hasta que la
expresión lógica sea falsa, en cuyo momento termina la ejecución de la instrucción.
Para finalizar esta sección revisemos un programa que determina si un número entero positivo
ingresado por el usuario es primo:
CAPÍTULO 2. SENTENCIAS CONDICIONALES Y REPETITIVAS 25
Una variable puede definirse en cualquier lugar en el que se puede escribir una instrucción.
El ámbito de la variable abarca desde su lugar de definición hasta el final del bloque
más interno en que se ha definido la variable (un bloque es un conjunto de instrucciones
encerradas entre llaves).
Se puede definir una variable en la parte de iniciación de una sentencia for. En ese caso el
ámbito de la variable es el cuerpo y cabecera de la instrucción for.
Se puede definir más de una vez una misma variable, es decir, con el mismo identifica-
dor dentro del cuerpo de una función siempre que las definiciones ocurran en bloques no
solapados o en bloques solapados de distinto nivel de profundidad.
Un código que intenta explicar de mejor modo el ámbito de aplicación de las variables:
CAPÍTULO 2. SENTENCIAS CONDICIONALES Y REPETITIVAS 26
Una aplicación importante del ámbito de las variables se presenta en la sentencia switch, al
poner entre llaves los bloques de instrucciones y el break; de cada caso. Al hacer esto si definimos
variables dentro de las llaves solamente serán efectivas para ese caso, pero si no hacemos uso
de ellas las variables definidas dentro de un caso serán validas para todos los casos dentro de la
sentencia switch.
2.5. Ejercicios
1. Realice un programa que lea de la entrada estándar números hasta que se introduzca un
cero. En ese momento el programa debe terminar y mostrar en la salida estándar el máximo
y mínimo número ingresado.
El programa debe leer de la entrada estándar un número entero positivo n y debe mostrar
en la salida estándar el resultado de cada una de las sumas.
CAPÍTULO 2. SENTENCIAS CONDICIONALES Y REPETITIVAS 27
f (xi−1 )
xi = xi−1 − , i = 1, 2, 3, . . .
f ′ (xi−1 )
a) f (x) = ex + x3 − 5, con x0 = 0.
b) f (x) = x2 + x ∗ cos(x), con x0 = −2.
5. Escriba un programa que lea de la entrada estándar un número entero positivo n, a con-
tinuación, determine del conjunto de números 1, 2, . . . , n:
a) El número de múltiplos de 3.
b) La cantidad de números primos.
c) La cantidad de números impares.
En los primeros capítulos del curso se han estudiado los tipos de datos primitivos de C++, es
decir, los tipos de datos numéricos, lógicos y carácter. Ahora, analizaremos los tipos de datos
estructurados, estos se utilizan para almacenar colecciones de datos del mismo tipo o diferentes
tales como: vectores, estructuras y cadenas de caracteres.
3.1. Vectores
Un vector es una estructura unidimensional que almacena una secuencia de datos del mismo
tipo. Los elementos de un vector se almacenan en zonas contiguas de memoria y se puede acceder
a ellos de manera directa mediante un índice o posición.
tipo nombre[tamaño];
donde tipo es el tipo de los elementos del vector, nombre es el nombre de la variable que sirve
para referenciar al vector y tamaño indica el número de elementos del vector.
No es válido definir el tamaño de un vector a partir de una variable ingresada por el usuario.
int x; // Variable
cout << "Ingrese un entero" << endl;
cin >> x;
double vector[x]; // No valido
28
CAPÍTULO 3. DATOS ESTRUCTURADOS 29
nombre[posicion];
donde nombre es el nombre de la variable de tipo vector y posicion es una expresión entera que
indica el índice del elemento del vector al que se quiere acceder.
La utilidad de los vectores es que permiten crear múltiples datos de un mismo tipo con una
única sentencia de definición y una única variable. Además, el acceso a los datos almacenados
en el vector es muy eficiente y sencillo a partir de su posición.
3.2. Matrices
Una matriz es una estructura bidimensional que almacena una secuencia de datos del mismo tipo
en filas y columnas. Los elementos de una matriz se almacenan en zonas contiguas de memoria
y se puede acceder a ellos de manera directa mediante la posición (fila y columna).
CAPÍTULO 3. DATOS ESTRUCTURADOS 31
tipo nombreMatriz[filas][columnas];
donde tipo corresponde al tipo de elementos que se van almacenar, nombreMatriz corresponde al
nombre de la estructura matriz, filas y columnas son expresiones enteras que indican el número
de filas y columnas, respectivamente, que tendrá la estructura matriz.
Al igual que en los vectores, los índices de las filas y columnas de una matriz empiezan en cero.
32 }
33
34 // Resultado
35 cout << " El resultado es : " << endl ;
36 for ( int i =0; i <2; i ++){
37 for ( int j =0; j <2; j ++){
38 cout << Suma [ i ][ j ] << " " ;
39 }
40 cout << endl ;
41 }
42 return 0;
43 }
En cuanto tenemos declarado una matriz, es posible asignarle valores a cada una de sus casillas,
evidentemente estos valores deben coincidir con el tipo de dato que le asignamos a dicha matriz.
A continuación, un programa que almacena la notas del examen de dos grupos de 10 alumnos
cada uno y compara el promedio de cada curso:
1 # include < iostream >
2 using namespace std ;
3
4 int main (){
5 int Notas [][10] = {{17 , 20 , 13 , 14 , 15 , 19 , 17 , 18 , 19 , 10} ,
6 {18 , 12 , 19 , 14 , 15 , 16 , 17 , 13 , 19 , 20 }};
7
8 // Promedio por curso
9 double prom1 =0 , prom2 =0;
10 for ( int i =0; i <10; i ++){
11 prom1 += 0.1* Notas [0][ i ];
12 prom2 += 0.1* Notas [1][ i ];
13 }
14
15 // Comparacion promedios
16 if ( prom1 > prom2 ){
17 cout << " El primer curso tiene mejor promedio " << endl ;
18 } else if ( prom1 < prom2 ){
19 cout << " El segundo curso tiene mejor promedio " << endl ;
20 } else {
21 cout << " Ambos cursos tienen igual promedio " << endl ;
22 }
23
24 return 0;
25 }
CAPÍTULO 3. DATOS ESTRUCTURADOS 33
3.3. Arrays
C++ permite trabajar con arrays multidimensionales, es decir, de varias dimensiones.
tipo nombreArray[tam1][tam2]...[tamn];
donde tipo es el tipo de los elementos del array, nombreArray es el nombre de la variable asocia-
da al array y tam1, tam2, . . . , tamn son expresiones constantes de tipo entero que indican los
tamaños de las distintas dimensiones del array.
Se debe tener mucho cuidado con el manejo de los índices en los arrays para no confundir las
dimensiones sobre las cuales se pretende trabajar.
3.4. Estructuras
C++ permite que el programador defina nuevos tipos de datos. Una forma de hacerlo es me-
diante una estructura. Una estructura define un nuevo tipo de dato que está compuesto por una
colección de datos de tipos existentes ya sean tipos básicos o estructurados como arrays, cadenas
de caracteres o estructuras ya definidas. Las estructuras son muy útiles pues permiten definir
tipos de datos que se ajustan con exactitud a las necesidades de representación de cualquier
objeto. Con una estructura se puede representar un alumno, un seguro, un vehículo, etc.
Rojo
Toyota
Modelo 2018
230 CV
Verde
Ford
Modelo 2016
280 CV
Azul
Mercedes Benz
Modelo 2020
350 CV
datos que componen el nuevo tipo. A cada uno de los datos se le llama campo o miembro. La
definición de cada campo tiene la estructura de la definición de una variable, es decir, en primer
lugar se especifica el tipo del campo y a continuación su nombre.
3.5. Ejercicios
1. Realice un programa que calcule el producto de dos matrices cuadradas. El usuario debe
ingresar la dimensión n de las matrices a emplearse.
2. Realice un programa que lea de la entrada estándar una matriz de orden 3 × 3. Y mediante
la regla de Sarrus, obtenga el determinante de la matriz.
3. Defina una estructura que indique el tiempo empleado por Richard Carapaz en cubrir
cada una de las etapas del Giro de Italia. La estructura debe tener 4 campos: etapa, horas,
minutos y segundos. Escriba un programa que dado un vector con las etapas y tiempos
empleados, calcule lo siguiente:
4. Realice un programa que pueda ser de utilidad para la elección de la directiva estudiantil
de la EPN. El programa debe leer primero el número de candidatos que se presenten
para obtener un cargo. Para cada uno de los candidatos, el programa deberá almacenar la
siguiente información:
Nombre
CAPÍTULO 3. DATOS ESTRUCTURADOS 37
Cédula
Género
Fecha de nacimiento
5. Realice un programa que trabaje con un vector de personas. Cada persona se almacena en
una estructura con los siguientes campos:
Nombre
Peso (kg)
Estatura (m)
El programa debe comenzar leyendo de la entrada estándar los datos de varias personas.
Y realizará lo siguiente:
Mostrar en la salida estándar un listado con los datos de las personas, el mismo que
debe incluir el índice de masa corporal de cada persona, éste índice se calcula como:
peso
IM C =
estatura2
Mostrar en la salida estándar el nombre de la persona con menor y mayor IMC.
Mostrar un listado de nombres de las personas cuya estatura supera la media.
4 | Números aleatorios
Los números aleatorios son pieza clave en la programación de juegos de azar, simulaciones,
cifrado de datos, en modelos estadísticos, etc. En esta capítulo aprenderemos a generar números
aleatorios para automatizar el proceso de llenado de arreglos y más.
xn = axn−1 mód m
donde a y m son enteros positivos dados y lo anterior significa que axn−1 se divide entre m y el
residuo se considera como el valor de xn .
xn
Así, cada xn toma valores entre: 0, 1, . . . m − 1 y la expresión
(llamada número pseudoalea-
m
torio) se considera como una aproximación del valor de una variable aleatoria uniforme en el
intervalo (0, 1).
La generación de números aleatorios en C++ se realiza por medio de la función rand(), mis-
ma que se encuentra definida en la librería cstdlib. La función rand() devuelve un número
entero aleatorio en el rango de 0 a RAND_MAX, donde RAND_MAX es el límite superior y es-
te último depende de la capacidad computacional del ordenador, así como del sistema operativo.
38
CAPÍTULO 4. NÚMEROS ALEATORIOS 39
Si ejecutamos varias veces el programa anterior se puede observar que los números obtenidos
en cada ejecución coinciden. Esto se debe principalmente a que la semilla es exactamente la
misma en cada ejecución. Para solventar este problema se recomienda resetear la semilla en
cada llamado del código por medio del siguiente comando:
srand(time(NULL));
donde srand accede al valor de la semilla y time reemplaza el valor de la semilla por la fecha y
hora de ejecución.
Siempre que se desee replicar un experimento o análisis lo recomendado es fijar una semilla.
A continuación, un programa que genera 5 números aleatorios enteros distintos en cada ejecución:
1 # include < iostream >
2 # include < cstdlib >
3 using namespace std ;
4
5 int main (){
6 int vec [5];
7
8 // Semilla aleatoria
9 srand ( time ( NULL ));
10
11 // Generamos valores entre 0 y RAND_MAX
12 for ( int i =0; i <5; i ++){
13 vec [ i ] = rand ();
14 cout << vec [ i ] << " " ;
15 };
16
17 return 0;
18 }
CAPÍTULO 4. NÚMEROS ALEATORIOS 40
A continuación, un programa que genera 100 números aleatorios entre [0, 20] y obtiene la suma
de dichos números:
1 # include < iostream >
2 # include < cstdlib >
3 using namespace std ;
4
5 int main (){
6 int vec [100];
7
8 // Semilla aleatoria
9 srand ( time ( NULL ));
10
11 // Valores aleatorios
12 cout << " Los valores generados son : " << endl ;
13 for ( int i =0; i <100; i ++){
14 vec [ i ] = rand () % 21;
15 };
16
17 // Calculo suma
18 int suma = 0;
19 for ( int i =0; i <100; i ++){
20 cout << vec [ i ] << endl ;
21 suma += vec [ i ];
22 };
23
24 cout << " La suma de los valores generados : " << endl ;
25 cout << suma << endl ;
26
27 return 0;
28 }
Para calcular el valor de θ note que si U está distribuida uniformemente en (0, 1), entonces
podemos expresar θ como:
θ = E[g(U )]
Si U1 , U2 , . . . , Uk son variables aleatorias independientes y uniformes en (0, 1), esto implica que
g(U1 ), g(U2 ), . . . , g(Uk ) son variables aleatorias independientes e idénticamente distribuidas con
media θ.
Por lo tanto, por la ley fuerte de los grandes números, se tiene, con probabilidad igual a 1 que:
∑
k
g(Ui )
→ E[g(U )] = θ, cuando k → ∞
i=1
k
donde h(y) = (b − a)g (a + [b − a]y). Así, podemos aproximar θ al generar de manera continua
números aleatorios y luego considerar el valor promedio de h evaluada en estos números aleato-
rios.
4.4. Ejercicios
1. Si x0 = 9 y
xn = 4 · xn−1 mód 20
determine x1 , x2 , . . . , x10 .
Una función es un fragmento de código que permite ejecutar una serie de instrucciones para-
metrizadas. Las funciones son de gran utilidad porque permiten estructurar el código de un
programa. Una función realiza una tarea concreta y puede ser diseñada, implementada y depu-
rada de manera independiente al resto del código.
A la primera línea se le llama signatura de la función e incluye el tipo del valor devuelto por la
función o valor de retorno, el nombre de la función y la lista de parámetros formales de la fun-
ción que consiste en un listado de variables separadas por comas y encerradas entre paréntesis.
Cada variable de la lista de parámetros formales viene precedida por su tipo. A continuación, y
delimitado por llaves, viene el bloque de instrucciones asociado a la función, también llamado
cuerpo de la función.
Las funciones devuelven únicamente tipos básicos: int, double, float, string, etc.
45
CAPÍTULO 5. FUNCIONES 46
12 }
13 return etiqueta ;
14 };
15
16 int main (){
17 double nota ;
18 cout << " Ingrese la nota obtenida en el examen : " << endl ;
19 cin >> nota ;
20 cout << " La escala alcanzada es : " << escala ( nota ) << endl ;
21
22 return 0;
23 }
Una función puede contener más de una instrucción return, en ese caso la ejecución de la función
terminará cuando se ejecute por primera vez una instrucción return.
A continuación, un programa que calcula el logaritmo en diferentes bases (por defecto se mantiene
la base 2):
De los tipos de datos que hemos visto los únicos para los que la asignación no está definida son
los tipos vector y array. Para el resto de tipos: tipos básicos, estructuras y cadenas de caracteres
la asignación está definida y, por tanto, una función puede devolver un dato de tipo básico, de
tipo string o de tipo estructura, pero no puede devolver un vector.
Aunque una función no tenga valor de retorno, es decir, aunque sea una función void es posible
utilizar la sentencia return en su cuerpo para terminar la ejecución de la función. En una función
void la sentencia return debe utilizarse sin expresión asociada, es decir:
return ;
Si una función void no utiliza ninguna sentencia return, la ejecución de la función termina cuan-
do se ejecuta la última instrucción de la función.
Las funciones void deben invocarse mediante una instrucción que incluya únicamente la llamada
a la función.
8
9 void pi (){
10 float error = 0.00001 , suma = 0 , xn , xm ;
11 int i =0;
12 do {
13 xn = termino ( i );
14 xm = termino ( i +1);
15 suma += xn ;
16 i ++;
17 } while ( abs ( xn - xm ) >= error );
18
19 cout << " Valor aproximado de pi es : " << 4* suma << endl ;
20 cout << " Numero de iteraciones : " << i << endl ;
21 return ;
22 }
23
24 int main (){
25 cout << " Aproximacion de pi \ n " << endl ;
26 pi ();
27 return 0;
28 }
El ámbito de una variable global abarca desde el lugar de su definición hasta el final del fichero
en que se ha definido, pudiendo ser utilizada en cualquier función situada en dicho ámbito. Una
variable local con el mismo nombre que una variable global oculta a la variable global.
El ámbito de una variable local abarca desde su lugar de definición en la función hasta el final
del bloque más interno en que ha sido definida. Los parámetros formales de una función son
variables locales de la función y, a efecto de ámbito, se encuentran definidas en el bloque más
CAPÍTULO 5. FUNCIONES 50
externo de la función, es decir, entre las llaves que delimitan el cuerpo de la función.
El uso de variables globales para implementar la comunicación entre funciones presenta algunos
inconvenientes:
1. Una función que se comunica con el resto mediante variables globales no es reutilizable,
salvo en un entorno en el que se utilicen las mismas variables globales. Se dice que la
función está fuertemente acoplada al resto del código.
2. El uso de variables globales puede producir los llamados efectos colaterales. Esto ocurre
cuando una variable global es ocultada por una variable local inadvertidamente.
Las variables globales se almacenan en una zona de memoria denominada memoria global. Una
variable global permanece almacenada en la memoria global durante todo el tiempo que dure la
ejecución de un program. Esto resulta necesario porque una variable global puede ser utilizada
por más de una función.
5.5.1. La Pila
Las variables locales de una función se almacenan en la pila. La pila es una zona de memoria
contigua donde se almacenan las variables locales de las funciones y alguna otra información,
como la dirección de memoria de retorno de una función. El tamaño de la pila varía dinámi-
camente durante la ejecución de un programa; cuando se invoca a una función la pila crece
hacia direcciones superiores de memoria para albergar a sus variables locales, se dice que las
variables se apilan; cuando una función termina la pila decrece y sus variables locales dejan de
ser accesibles, se dice que las variables se desapilan.
Una variable almacenada en la pila tiene un tiempo de existencia limitado al tiempo en que se
ejecuta el código asociado al ámbito de la variable.
10 }
11 return m ;
12 }
13
14 int main (){
15 double a , b ;
16 cout << " Ingrese dos números " << endl ;
17 cin >> a >> b ;
18
19 // Se imprime el máximo de los dos numeros
20 cout << " El máximo es : " << maximo (a , b ) << endl ;
21
22 // Se vuelve a invocar a maximo
23 cout << " El máximo de a y 10 es : " << maximo (a , 10) << endl ;
24 a = 8;
25 double z = 3 + maximo (a , a -1);
26 cout << " z vale : " << z << endl ;
27 return 0;
28 }
Ejecutamos el programa anterior considerando a = 6 y b = 8.
En principio cualquer función puede hacerse una llamada a sí misma, sin embargo, tiene que
estar especialmente diseñada para que funcione correctamente, ya que al llamarse a sí misma
provoca que ésta se vuelva a ejecutar, y dentro de sus instrucciones se vuelve a llamar, creando
un bucle que si no está controlado se vuelve infinito.
Por lo tanto, una función recursiva forma un bucle al ser llamada a si misma. Este bucle debe
ser controlado de alguna manera para poder salir de él y no caer en estructuras indeseadas como
CAPÍTULO 5. FUNCIONES 52
La recursividad facilita la escritura de código que trabaja con estructuras de datos o problemas
que tienen una naturaleza recursiva como la estructura de datos árbol. Además, produce un
código más legible para este tipo de problemas.
En C++ se pueden utilizar los parámetros formales de una función para que la misma devuelva
datos. En esta sección nos centraremos en estudiar como utilizar variables de tipo referencia.
5.7.1. Referencias
Una referencia es un nombre alternativo para un dato u objeto. La sintaxis T& significa refe-
rencia a un objeto del tipo T.
Una variable de tipo referencia debe iniciarse en su definición con un objeto del mismo tipo que
el tipo asociado a la referencia. Al objeto con que se inicia la referencia lo llamaremos el objeto
referenciado por la referencia.
Una referencia siempre tiene asociado el mismo objeto referencia, a saber, el objeto con que se ha
iniciado la referencia. Una vez iniciada una referencia, cuando un programa utiliza la referencia
CAPÍTULO 5. FUNCIONES 54
Notemos que los cuerpos de las funciones incremento1 e incremento2 son iguales, sin embargo,
los parámetros formales de la función son diferentes, para la primera función se hace un paso
por variable, mientras que la segunda función realiza un paso por referencia.
Para el siguiente programa nos encontramos interesados en realizar la división entre dos número
enteros y obtener dos resultados: el cociente y el residuo.
En el programa anterior a partir de una referencia es posible obtener 2 o más valores resultantes
de la ejecución de una función.
A continuación, retomamos nuestro trillado ejemplo del mínimo y máximo de dos números:
CAPÍTULO 5. FUNCIONES 56
El programa incluye una función, llamada MaxMin, cuyos dos últimos parámetros formales,
max y min, tienen semántica de paso por referencia. Cuando se invoca a la función MaxMin,
max y min se inician con los dos objetos pasados como parámetros reales. Cuando la función
MaxMin realiza alguna modificación o consulta sobre las variables max o min realmente está
modificando o consultando los objetos referenciados por estas dos variables. Esto permite que
tras la ejecución de la función MaxMin, la función main pueda consultar los valores de máximo
y mínimo calculados por la función MaxMin.
Cuando la función MaxMin asigna valores a las referencias max y min los valores asignados se
almacenan en las variables maximo y minimo respectivamente. Esto permite que tras ejecutar
la función MaxMin las variables maximo y minimo contengan los dos valores calculados por
MaxMin.
Una variable de tipo vector almacena la dirección de memoria a partir de la cual se almacenan
los elementos del vector. Por lo tanto, lo que recibe un parámetro formal de tipo vector es la
dirección de memoria donde se almacena un vector. Al recibir la dirección de memoria donde
se almacena el vector, la función tiene total acceso a los elementos originales del vector y, por
tanto, las modificaciones que realice en los elementos del vector serán visibles al terminar la
ejecución de la función.
58 cout << " Estatura media : " << media << endl ;
59 cout << " Hay " << mayores_media << " alumnos con estatura " ;
60 cout << " superior a la media " << endl ;
61 cout << " Hay " << menores_media << " alumnos con estatura " ;
62 cout << " inferior a la media " << endl << endl ;
63 }
64
65 int main (){
66 double estaturas [10] , media , mayor , menor ;
67 int cont_mas = 0 , cont_menos = 0;
68 leer ( estaturas );
69 max_min ( estaturas , mayor , menor );
70 media = estatura_media ( estaturas );
71 cu a n t o s _ m a y o r _ m e n o r _ m e d i a ( estaturas , media , cont_mas , cont_menos );
72 mos tr ar_resultado s ( estaturas , media , mayor , menor , cont_mas ,
73 cont_menos );
74 return 0;
75 }
En la función se debe declarar el parámetro como un array del tipo adecuado. En los
arrays unidimensionales no es necesario especificar el tamaño por lo tanto aparecerán los
corchetes vacíos.
En la llamada a la función a la que se envía el array, el nombre del array aparecerá solo,
sin corchetes ni índices
Los arrays en C++ se pasan siempre a las funciones por referencia. El nombre de un array
realmente es un puntero que contiene la dirección de memoria donde comienza el array, o lo
que es lo mismo, la dirección de memoria del primer elemento. Cuando se pasa un array a una
función, la función recibe la dirección de memoria donde se encuentra el primer elemento del
array. Por lo tanto, la función trabaja sobre el array original.
No es necesario utilizar el operador & en el paso de arrays a funciones para indicar que se hace
por referencia ya que siempre pasan por referencia.
5.12. Ejercicios
1. Realice un programa que permita al usuario ingresar 10 valores enteros y muestre en
pantalla los elementos impares ingresados.
3. Una matriz A ∈ Rn×n se dice que es simétrica si aij = aji , ∀i, j ∈ {1, . . . , n}. Desarrolle
una función que determine si una matriz es simétrica o no.
Función que dado un Sudoku y un número de fila del Sudoku devuelva un valor de
tipo lógico indicando si no se repiten dos dígitos en la fila.
Función que dado un Sudoku y un número de columna del Sudoku devuelva un valor
de tipo lógico indicando si no se repiten dos dígitos en la columna.
Función que dado un Sudoku y la primera fila y columna de una caja del Sudoku
devuelva un valor de tipo lógico indicando si no se repiten dos dígitos en la caja.