Introducción a la Programación en C++
Introducción a la Programación en C++
Tanto C como C++ son lenguajes de programación de propósito general. Todo puede programarse con
ellos, desde sistemas operativos y compiladores hasta aplicaciones de bases de datos y procesadores de
texto, pasando por juegos, aplicaciones a medida, etc.
Oirás y leerás mucho sobre este tema. Sobre todo diciendo que estos lenguajes son complicados y que
requieren páginas y páginas de código para hacer cosas que con otros lenguajes se hacen con pocas lí-
neas. Esto es una verdad a medias. Es cierto que un listado completo de un programa en C o C++ para
gestión de bases de datos (por poner un ejemplo) puede requerir varios miles de líneas de código, y que
su equivalente en Visual Basic sólo requiere unos pocos cientos. Pero detrás de cada línea de estos com-
piladores de alto nivel hay cientos de líneas de código en C, la mayor parte de estos compiladores están
respaldados por enormes bibliotecas escritas en C. Nada te impide a ti, como programador, usar biblio-
tecas, e incluso crear las tuyas propias.
Una de las propiedades de C y C++ es la reutilización del código en forma de bibliotecas de usuario.
Después de un tiempo trabajando, todos los programadores desarrollan sus propias bibliotecas para
aquellas cosas que hacen frecuentemente. Y además, raramente piensan en ello, se limitan a usarlas.
Además, los programas escritos en C o C++ tienen otras ventajas sobre el resto. Con la excepción del
ensamblador, generan los programas más compactos y rápidos. El código es transportable, es decir, un
programa ANSI en C o C++ podrá ejecutarse en cualquier máquina y bajo cualquier sistema operativo.
Y si es necesario, proporcionan un acceso a bajo nivel de hardware sólo igualado por el ensamblador.
Otra ventaja importante es que C tiene más de 30 años de vida, y C++ casi 20 y no parece que su uso
se debilite demasiado. No se trata de un lenguaje de moda, y probablemente a ambos les quede aún
mucha vida por delante. Sólo hay que pensar que sistemas operativos como Linux, Unix o incluso Win-
dows se escriben casi por completo en C.
Por último, existen varios compiladores de C y C++ gratuitos, o bajo la norma GNU, así como cientos de
bibliotecas de todo propósito y miles de programadores en todo el mundo, muchos de ellos dispuestos a
compartir su experiencia y conocimientos.
Es posible que usted nunca haya oído hablar de conceptos como compilación, ejecutables, etc. No se
trata de detallar aquí los mecanismos por los cuales un código escrito en un lenguaje de programación
se convierte en un programa que hace ciertas cosas en un ordenador. El tema es en sí mismo motivo de
libros. Sin embargo, sí que es interesante explicar cómo se obtiene un programa a partir de un código.
Para obtener un programa que se pueda ejecutar en un ordenador se necesita un código fuente, es de-
cir, un archivo de texto con las instrucciones. Este archivo suele tener la extensión cpp y es el que usted
tiene que escribir como programador. También son necesarios unos archivos de cabecera con la exten-
sión h; de éstos, algunos serán escritos por el programador, pero otros ya vienen con el compilador.
Con todos los archivos se realiza el proceso de compilación que da como resultado un archivo de exten-
sión obj.
El código que el programador escribe lo entienden las personas, pero no la máquina. El ordenador tiene
su propio lenguaje formado por unos y ceros, que es complicado para las personas. Entonces, qué se
Finalmente, antes de obtener el ejecutable es necesario un linkaje que enlaza el archivo obj con las li-
brerías que suministra el lenguaje. La mezcla del archivo obj con las librerías .lib conducen a un ejecuta-
ble exe. Este último archivo es el que se podrá ejecutar en la máquina.
Hoy en día, hay entornos de programación que realizan está labor en un conjunto integrado, posible-
mente usted trabaje con uno de ellos. En tal caso le remitimos al manual de instrucciones para compilar
y ejecutar un archivo. En general, de todas las funcionalidades que tienen esos entornos usted sólo va a
necesitar unas pocas; por lo tanto le aconsejamos que no pierda mucho el tiempo en aprender su mane-
jo hasta que realmente no necesite hacer cosas muy potentes.
Trabaje con un único archivo cpp y a lo sumo un archivo h, el resto lo pone todo el entorno, Construya y
ejecute las aplicaciones, no necesita nada más.
Consideraciones Generales
C es lenguaje de “funciones” por ejemplo la función “void main(void)”. Como función debe te-
ner uno o más argumentos. Puede ocurrir que ese argumento sea vacío.
En C todas las funciones se escriben en minúsculas, salvo algunas excepciones.
C hace distinción entre minúsculas y mayúsculas, de tal manera que el identificador Hola es dis -
tinto de hola, distinto de hOla, distinto de hoLa, etc.
Toda instrucción termina con un punto y coma (;)
C es un lenguaje de bloques. Dos o más instrucciones son un bloque que comienza con la apertu-
ra de una llave ({) y termina con el cierre de una llave (}).
Se abre una llave… se cierra una llave, análogamente se abre un paréntesis… se cierra un parén -
tesis, etc.
El Entorno Integrado de Desarrollo (EID) nos permite trabajar con “indentación”… se debe tra-
bajar en forma indentada
Es de muy buena costumbre llenar de comentarios el código fuente
Es responsabilidad del programador NO excederse en el rango máximo permitido para el tipo de
identificador declarado!!!!!! Por ejemplo, si declaro un int el valor máximo permitido es 32767.
Deben inicializarse todos y cada uno de los acumuladores, porque el compilador NO los inicializa.
Se deben declarar todas y cada una de los identificadores que se van a utilizar, así como su tipo.
Un programa sencillo
La mejor manera de empezar el estudio de C++ es examinar un programa. Comenzaremos con el pro-
grama más simple que puede escribirse en C++: 1PRIMERO.CPP
#include <iostream.h>
void main(void)
{
cout <<"Esta es una línea de texto.";
}
La palabra "main" es muy importante, y debe aparecer una vez y sólo una en cualquier programa en
C++. Este es el punto de partida desde el cual el programa se ejecuta.
Siguiendo a la palabra "main", hay un par de paréntesis en la forma (), que le indican al compilador que
está ante una función.
Los signos de llave, conocidos como símbolos de agrupamiento, agrupan las declaraciones relaciona-
das, se usan para definir los límites del programa principal.
El punto y coma de final de línea es usado como mandato finalizador, por tanto el compilador asigna a
este caracter la función de indicar que la línea ya está completa.
La declaración #include
Esta declaración indica al compilador que incluya el contenido del archivo especificado al principio del
programa. En este caso, el compilador incluirá el contenido del archivo iostream.h. Los archivos que tie-
nen extensión h y se incluyen al principio (o cabecera) de los programas se llaman archivos de cabe-
cera.
Cada uno de los archivos de cabecera comprende definiciones que el compilador proporciona para dife-
rentes operaciones. Por ejemplo, hay archivos de cabecera para las operaciones matemáticas, para ope-
La consola
El instrumento más rudimentario de interacción es la consola, es decir, el teclado para permitir la inte-
racción hombre-máquina y la pantalla para la relación inversa. En la librería <iostream.h> hay definidos
cuatro elementos de interacción.
cout Salida por pantalla.
cin Entrada por el teclado.
cerr Salida de error por pantalla.
Los operadores « y », son los llamados operadores de inserción y de extracción respectivamente, sirven
para dirigir el flujo de datos.
La salida se realiza a través del operador « y consiste en insertar los datos en el stream, en particular se
convierte en salida por la pantalla. Lo mismo ocurre con la entrada, el operador » saca del stream el tipo
de dato necesario.
El operador cout
El operador cout muestra por pantalla lo que se encuentra entre comillas. Se utiliza con el doble signo
de menor que “<<“, llamado operador de inserción.
A continuación veremos un programa pequeño, pero que ilustra un concepto muy importante: 2SEGUN-
DO.CPP
#include <iostream.h>
void main(void)
{
cout <<"Esta es una línea de texto.\n";
cout <<"Y esta es otra ";
cout <<"línea de texto.\n\n";
cout <<"Esta es la tercera línea.";
}
El programa consta de cuatro declaraciones. Se ejecutan las líneas por orden de encuentro, por lo tanto
se ejecutará la línea superior en primer lugar, después la segunda, tras ésta la tercera y así sucesiva -
mente. El programa se ejecuta de arriba a abajo.
Cerca del fin de la primera línea aparece el llamado "caracter de corte: \ ". Se usa para indicar que le
sigue un caracter de control especial. En este caso, ese caracter es "n", que indica que se ejecutará una
nueva línea. Esta indicación hace que el cursor baje una línea y se coloque en la primera posición iz-
quierda de la pantalla. Se refiere normalmente a un retorno de carro. En cualquier parte del texto, don-
de se desee, puede acabar la línea y empezar otra nueva. Se puede cortar una palabra y mostrarla en-
tre dos líneas. El compilador considera la expresión "\n" como un solo caracter (caracter de corte+letra
n). Entonces, el primer cout muestra una línea de texto, y realiza un retorno de carro. La segunda línea
muestra una línea de texto, sin retorno de carro, porque la tercera efectúa 2 retornos de carro, resultan-
do una línea en blanco. Finalmente la cuarta línea muestra otra línea de texto y acaba el programa.
IDENTIFICADORES
Un identificador es una combinación de caracteres numéricos, alfanuméricos o letras, o algún número, o
un carácter subrayado “_”, lo usa una variable, o una función, o una definición de datos, etc. En el len -
guaje C++ debe tenerse en cuenta que mayúsculas y minúsculas definen identificadores distintos. Así,
el identificador “INDICE”, es distinto de “índice”, y también de “Índice”.
Una vez declarada la variable se utiliza el operador de asignación (el signo igual) del C++ para asignar
un valor a una variable.
Cuando se declara una variable suele ser conveniente asignar el valor inicial de la misma. Para facilitar
las cosas, C++ permite asignar valores al mismo tiempo que se declaran las variables.
Después de asignar un valor a una variable, los programas pueden utilizar el valor de la misma haciendo
referencia simplemente a su nombre.
El siguiente programa, 3VARIABLE.CPP, asigna valores a dos variables y luego las exhibe en la panta-
lla utilizando el operador cout.
El operador de inserción (<<) comunica al sistema que lo sigue una variable o una constante.
#include <iostream.h>
void main(void)
{ /* Principio
del programa */
EJERCICIOS DE PROGRAMACIÓN:
1. Escribir un programa que visualice por pantalla su nombre completo.
2. Escribir otro que además muestre su dirección y número de teléfono, con una línea de espacio entre
los datos.
LIBRERIAS EN LENGUAJE C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
strxfrm
tolower toupper
#include <locale.h>
localeconv setlocale
#include <math.h>
tanh
#include <setjmp.h>
longjmp setjmp
#include <signal.h>
raise signal
#include <time.h>
strftime time
Otras librerias que no tienen funciones asociadas. Pero tienen macros constantes y/o estructuras.
#include <assert.h>
#include <errno.h>
#include <float.h>
#include <limits.h>
#include <stddef.h>
RESUMEN DE LIBRERIAS
limits.h Contienen varias macros que definen constantes para el tamaño de tipo enteros.
float.h Contienen varias macros que definen constantes para el tamaño de tipo flotante.
locale.h Contienen varias macros, funciones y tipos para unidades locales, como unidad monetaria,
tiempo, dígitos, etc.
setjmp.h Contienen declaraciones que proporcionan una forma de evitar la secuencia normal de llamada
y regreso de funciones.
signal.h Contiene un tipo, dos funciones y varias macros para manejar condiciones excepcionales que
aparecen durante la ejecución, tal como una señal de interrupción de una fuente externa o un error en
la ejecución.
stdarg.h Contiene un tipo y tres macros que proporcionan recursos para recorrer una lista de argumentos
de función de tamaño y tipo desconocido.
stddef.h Contiene varios tipos y macros que también están definidas en otras librerías, como size_t.
stdlib.h Contiene tipos, macros y funciones para la conversión numérica, generación de números aleato-
rios, búsquedas y ordenación, gestión de memoria y tareas similares.
time.h Contiene tipos, macros y funciones para la la manipulación de información sobre fechas y horas.
Tipos: char, int, float, long, long long, short, double, void.
c un carácter
% imprime el carácter %
p puntero
SECUENCIA DE ESCAPE
\a Alerta
\b Espacio atrás
\f Salto de página
\n Salto de línea
\t Tabulación horizontal
\v Tabulación vertical
\\ Barra invertida
Formateador Salida
%07i justificado a la derecha, 7 dígitos de largo, sin relleno
%.7i largo mínimo de 7 dígitos, justificado a la derecha, rellena con ceros
%8.2f tamaño total de 8 dígitos, con dos decimales
%.*f”',x,d) tamaño predeterminado,x numeros decimales
%*.*f”,x,y,d) tamaño igual a x, y numeros decimales
%s cadena terminada en null
%5s primeros cinco caracteres o delimitador
%.5s primeros cinco caracteres, sin tener en cuenta el delimitador
%20.5s primeros cinco caracteres, justificados a la derecha, con 20 caracteres de largo
%-20.5s primeros cinco caracteres, justificados a la izquierda, con 20 caracteres de largo
Operador Relación
== ... igual a ...
!= ... distinto de ...
> ... mayor que ...
< ... menor que ...
>= ... mayor o igual que ...
<= ... menor o igual que ...
&& y
|| o
EL BUCLE WHILE
El lenguaje C++ tiene varias estructuras de control para bucles y bifurcaciones condicionales. Empeza-
remos por el bucle WHILE. Este bucle continuará ejecutándose mientras (while significa mientras, en
inglés) sea cierta la condición impuesta. Cuando esta condición no se cumpla, el bucle se parará. El
nombre en sí ya es una buena descripción.
Veamos un ejemplo del funcionamiento de este bucle en el programa 4WHILE.CPP
void main(void)
{
int contador;
contador = 0;
while (contador < 6) {
cout <<"El valor del contador es " << contador << "\n";
contador = contador + 1;
}
}
Empezamos con un comentario y el nombre del programa. Tras esto procedemos a definir la variable
entera "contador" en el cuerpo del programa. La variable tiene como valor inicial 0. Y ahora, vamos al
bucle WHILE. La sintaxis es tal y como se describe ahora: la palabra reservada WHILE es seguida por
una expresión o por algo entre paréntesis, seguido a su vez por un mandato compuesto, encerrado en-
tre llaves. Tantas veces como sea cierta la condición, tantas veces se ejecutará este mandato. En este
caso, la variable contador irá incrementando su valor en 1 y, cuando alcance 6, el bucle dejará de ejecu-
tarse. El control del programa pasará a la primera instrucción tras el mandato o mandatos ejecutados
por el bucle.
1) Si la variable “contador” fuera mayor que 5, el bucle podría no ejecutarse jamás, (Ej: si empezara
con 6), ya que la comparación se realiza al iniciar el bucle.
2) Si la variable no se incrementa, el bucle no acabará de ejecutarse jamás.
3) Si el mandato dependiente del bucle es uno solo, no es necesario incluirlo entre llaves.
EL BUCLE DO-WHILE
Una variación del bucle WHILE se muestra en el programa 5DOWHILE.CPP
#include <iostream.h>
void main(void)
{
int i;
i = 0;
do {
cout <<"El valor de i es ahora " << i << "\n";
i = i + 1;
} while (i <= 5);
}
Programación C++ Ing. Helmut Heinz Dehner Página 12 de 70
Es casi idéntico al anterior, excepto en que el bucle comienza con la palabra reservada "DO", seguida
por un bloque de mandatos encerrados entre llaves, luego la palabra reservada WHILE y, finalmente la
expresión entre paréntesis. El bloque de comandos entre llaves se ejecutará mientras la condición en-
tre paréntesis se cumpla, Cuando la condición deje de ser cierta, el control pasará al primer mandato
tras el bloque de mandatos encerrados entre llaves.
Destacamos que:
1) Como la comprobación se realiza al final del bucle, el bloque de mandatos entre llaves se eje-
cutará al menos 1 vez.
2) Si “i” no se cambiara dentro del bucle, el programa se ejecutaría eternamente.
3) Igual que con el bucle WHILE, si el bloque de mandatos se reduce a uno, no son necesarias las lla-
ves.
Estos bucles pueden anidarse. Esto es, un bucle dentro de otro, y el número de anidamientos es ili-
mitado.
EL BUCLE FOR
El bucle for no es nada nuevo. Es una nueva manera de describir el bucle while. La estructura del bucle
for consiste en la palabra reservada for, seguida de determinado número de expresiones entre parénte-
sis. Estas expresiones son dos o tres campos separados por punto y coma.
#include <iostream.h>
void main(void)
{
int indice;
El segundo campo, en este caso conteniendo "indice < 6", es el test que se hace al principio de
cada vuelta del bucle. Esta expresión se puede evaluar verdadera o falsa.
La expresión contenida en el 3er. campo se ejecuta cada vez que se ejecuta el bucle, esto no ocu-
rre hasta que todos los mandatos contenidos en el bucle se ejecutan en su totalidad. Este campo, al
igual que el primero, puede contener varios operandos separados por ;.
Siguiendo a la expresión for (), algún mandato simple, o un bloque que será ejecutado en el cuerpo del
bucle.
Los tres campos utilizados dentro del paréntesis podrían explicarse como:
void main(void)
{
int dato;
if (dato == 2)
cout <<"Dato es ahora igual a " <<dato<< "\n";
if (dato < 5)
cout <<"Dato es ahora " << dato << ", el cual es menor de 5\n";
else
cout <<"Dato es ahora " << dato << ", el cual es mayor de 4\n";
El condicional empieza con la palabra reservada if, seguida de una expresión entre paréntesis. Si la ex-
presión se evalúa y resulta cierta, el mandato simple que sigue a if se ejecutará, pero si es falsa, el con-
trol del programa pasará a la siguiente instrucción. En lugar del comando simple, podemos poner un
bloque de instrucciones encerrado por llaves.
La expresión “dato == 2", está simplemente preguntando si el valor de "dato" es igual a 2, es decir que
“==“ significa comparación, en cambio si la expresión fuera “=“ la función sería de asignación.
IF-ELSE
Este segundo IF es similar al primero, con la adición de una nueva palabra reservada, “else", seguida
del mandato cout. Esto, simplemente significa que si la expresión evaluada entre paréntesis resulta cier-
ta, la primera expresión es ejecutada. Caso contrario, las instrucciones después de else serán ejecuta-
das. Entonces, una de las expresiones se ejecuta siempre, al contrario del primer ejemplo, donde la ex-
presión o cumple o se ignora.
BREAK y CONTINUE
Veamos el programa 8BREAKCON.CPP
#include <iostream.h>
void main(void)
{
int xx;
El siguiente bucle for contiene un comando continuo (continue), el cual no finaliza el bucle, pero
se desvía. Cuando xx alcance 8, en este caso, el programa saltará hasta el final del bucle y, continuará
ejecutando, ignorando el mandato cout, en este paso, cuando xx es 8, luego continuará normalmente el
bucle, en este caso, para xx igual a 9.
LA INSTRUCCIÓN SWITCH
Esta instrucción significa la elección de una posibilidad entre un abanico de varias. Empieza con la
palabra reservada "switch" seguida de una variable en paréntesis, la cual es la variable que determina
la opción adecuada por comparación. En el ejemplo, 9SWITCH.CPP, esta variable es "truck". Pueden
incluirse tantas posibilidades como sean necesarias, encerradas entre llaves, claro está. La palabra re -
servada "case" encabeza cada línea de opción, seguida por el valor de la variable. Si no se verifica
ninguna de las opciones de “case” se ejecutará la línea encabezada con default.
Este tipo de estructura también puede anidarse.
#include <iostream.h>
void main(void)
{
int dato;
switch (dato) {
case 3 : cout << "El valor es tres \n";
break;
case 4 : cout << "El valor es cuatro\n";
break;
case 5 :
case 6 :
case 7 :
case 8 : cout << "El valor esta entre 5 y 8\n";
break;
case 11 : cout << "El valor es once\n";
break;
EJERCICIOS DE PROGRAMACIÓN:
1. Escribir un programa que imprima 10 veces un nombre por pantalla. Hacer una versión para cada bu -
cle conocido. Definir cualquier variable cerca de su punto de uso.
2. Hacer un programa que cuente de 1 a 10, escriba cada número en la pantalla y que al lado del 3 y
del 7 escriba un comentario distinto para cada uno.
La función PRINTF()
Antes de analizar las asignaciones y comparaciones lógicas veremos una función similar al cout que se
utiliza en la programación en el lenguaje C. Tiene el propósito de visualizar algo en la pantalla, este algo
está dentro de unos paréntesis, rodeados a su vez por signos de comillas. Ej: printf (“Este texto
aparecerá por pantalla.\n”);
Como vemos, con la función printf se puede utilizar también el caracter de retorno de carro.
A continuación veremos el programa 10PRINTF.CPP en el que se utiliza esta función con diferentes ti-
pos de datos, modificando el formato de salida por pantalla.
#include <stdio.h>
void main(void)
{
int a; // tipo entero simple
long int b; // tipo entero expandido
short int c; // tipo entero comprimido
unsigned int d; // tipo entero sin signo
char e; // tipo caracter
float f; // tipo punto flotante
double g; // punto flotante doble precisión
a = 1023;
b = 2222;
c = 123;
d = 1234;
e = 'X';
f = 3.14159;
g = 3.1415926535898;
Como se observa en la primer línea, el archivo de cabecera para utilizar la función printf no es el mismo
que para el cout. En este caso la biblioteca es stdio.h, que controla las operaciones de entrada y salida.
Después de declarar varios tipos de variables y asignarles un determinado valor, nos encontramos, a
partir de la línea 20, con declaraciones printf que utilizan el caracter %.
Cada caracter de los anteriores es precedido por un signo de porcentaje, indicando el tipo de conversión
de salida, y entre estos dos caracteres, puede incluirse cualquiera de los siguientes:
-: Justificación izquierda en este campo.
(n): Especificador de mínimo de caracteres por campo.
.: Para separar n de m. (n.m)
m): Dígitos significativos de la fracción flotante.
l: Indica un "long".
Formateador Salida
%07i justificado a la derecha, 7 dígitos de largo, sin relleno
%.7i largo mínimo de 7 dígitos, justificado a la derecha, rellena con ceros
%8.2f tamaño total de 8 dígitos, con dos decimales
%.*f”',x,d) tamaño predeterminado, x números decimales
%*.*f”,x,y,d) tamaño igual a x, y números decimales
%s cadena terminada en null
%5s primeros cinco caracteres o delimitador
%.5s primeros cinco caracteres, sin tener en cuenta el delimitador
%20.5s primeros cinco caracteres, justificados a la derecha, con 20 caracteres de largo
%-20.5s primeros cinco caracteres, justificados a la izquierda, con 20 caracteres de largo
#include <stdio.h>
void main(void)
{
int a,b,c;
a = 12;
b = 3;
c = a + b;
printf("a= %d| b= %d| c= %d\n\n",a,b,c);
Programación C++ Ing. Helmut Heinz Dehner Página 17 de 70
c = a - b;
printf("a= %d| b= %d| c= %d\n\n",a,b,c);
c = a * b;
printf("a= %d| b= %d| c= %d\n\n",a,b,c);
c = a / b;
printf("a= %d| b= %d| c= %d\n\n",a,b,c);
(17)c = a % b; // módulo o residuo
printf("a= %d| b= %d| c= %d\n\n",a,b,c);
(19)c = 12*a + b/2 - a*b*2/(a*c + b*2);
printf("a= %d| b= %d| c= %d\n\n",a,b,c);
(21)c = c/4+13*(a + b)/3 - a*b + 2*a*a;
printf("a= %d| b= %d| c= %d\n\n",a,b,c);
a = a + 1;
printf("a= %d| b= %d| c= %d\n\n",a,b,c);
b = b * 5;
printf("a= %d| b= %d| c= %d\n\n",a,b,c);
Tres variables se definen para su uso en el programa, y las demás son para ilustrar acerca de otros tipos
de asignación. Las dos primeras líneas asignan valores numéricos a “a” y a “b”, y las 4 siguientes líneas
ilustran el uso de las 5 funciones aritméticas básicas. En la línea 17 se utiliza el operador modular
(%) que da el resto de la división de a por b. Esto sólo puede ser aplicado a variables tipo int o char,
y sus extensiones, tales como long, short, etc. Siguiendo, en las líneas 19 y 21 se ilustra la manera de
combinar variables en algunas expresiones complejas, utilizando paréntesis.
En las líneas 28 y 30 se usa la asignación múltiple, construcción muy útil sobre todo cuando hay que
inicializar variables en grupo.
El operador cin
Este operador se utiliza para leer datos desde el teclado. Se usa con el llamado operador de extracción
(>>).
Con el operador cin pueden asignarse a las variables valores ingresados por el usuario.
Veamos como ejemplo el programa 12OPER_CIN.CPP:
#include <iostream.h>
void main(void)
{
int a;
float b;
char c;
COMPARACIONES LÓGICAS
El programa 13COMPARAR.CPP contiene algunos ejemplos de comparaciones en C.
#include <iostream.h>
void main(void)
{
int x = 11,y = 11,z = 11;
char a = 40,b = 40,c = 40;
float r = 12.987,s = 12.987,t = 12.987;
x = y = z = 77;
if ((x == y) && (x == 77)) z = 33; // Esto asigna z = 33
if ((x > y) || (z > 12)) z = 22; // Esto asigna z = 22
if (x && y && z) z = 11; // Esto asigna z = 11
if ((x = 1) && (y = 2) && (z = 3)) r = 12.00;
// Esto asigna x = 1, y = 2, z = 3, r = 12.00
if ((x == 2) && (y = 3) && (z = 4)) r = 14.56; // Esto no cambia nada
Empezamos definiendo e inicializando nueve variables para usarlas en los mandatos comparadores.
El primer grupo de comparaciones representa el más simple, ya que sólo compara 2 variables. Cada va-
riable podría ser sustituida por una constante, y la comparación seguiría siendo válida, pero dos varia -
bles es el caso más frecuente. La primera comparación averigua si “x” e “y” son iguales, usando el doble
igual “==“ para esta comparación. La segunda comparación verifica si “x” es mayor de “z”.
La tercera introduce el operador NOT (!), el cual puede usarse para negar una comparación lógica ( !
(x>z) : que x no sea mayor que z). La cuarta comprueba que “b” sea menor o igual que “c”, y la última
Las comparaciones del segundo grupo son más complicadas. Para comprender esto debemos entender
tan solo lo que significan verdadero y falso en lenguaje C. Falso está definido como valor 0, y verdade-
ro es definido como no cero. Cualquier variable entera o tipo char puede usarse para el resultado de
tipo verdadero/falso, o el resultado puede ser transformado en un valor entero o char.
Observemos primero la comparativa del segundo grupo de comparadores. La expresión “r!=s” será eva-
luada como cierta, teniendo en cuenta que “r” fue probablemente inicializada antes a 0.0, por tanto el
resultado será un no cero, tal vez un 1. Tengamos presente que cuando se evalúen dos variables float,
el resultado será siempre de tipo integer. Dado que no se le ha dado una variable para almacenar el re-
sultado de la comparación, lo hará produciendo directamente un entero. Finalmente, el resultado, 1 en
este caso, será asignado a “x”. Si hubiésemos usado el doble igual, el valor fantasma llamado 1, sería
comparado internamente con “x”, pero como hemos empleado el igual simple, el valor es asignado a
“x”, aunque el mandato esté entre paréntesis. Finalmente, dado que el resultado de la asignación entre
paréntesis es no cero, la expresión evaluada es cierta, y el valor 1000 es asignado a “z”. Por tanto, he-
mos conseguido 2 cosas: hemos asignado un nuevo valor a “x”, probablemente 1, y hemos destinado
1000 a “z”. Lo más importante a recordar es que valores verdadero/falso y muchas cosas más pueden
ser asignadas a este mandato condicional. El valor asignado a “x” es 1, pero distintos compiladores po-
drían asignar otros valores.
El ejemplo que proponemos servirá para aclarar conceptos. En él , “x” es asignado al valor de “y”, y
dado que el valor es 11, es no cero, lo cual es, por tanto, verdad. De este modo, a “z” se le asigna el
valor 222.
El tercer ejemplo del segundo grupo compara “x” y 0. Si el resultado es verdad, significa que “x” es no
cero, por tanto a “z” se le asigna el valor 333. El tercer ejemplo ilustra el mismo caso, ya que el resulta-
do de “x” es no cero. La comparación a cero no es actualmente necesaria, ya que el resultado de la mis-
ma es verdad. El tercer y cuarto ejemplo son idénticos.
EVALUACIÓN LÓGICA
Cuando una expresión compuesta se evalúa, la evaluación se realiza de izquierda a derecha, y tan pron-
to como se cumple el resultado de la misma, se para. Nos referimos a “evaluación lógica” cuando em-
pleamos un AND y, uno de los términos evaluados da falso, la evaluación es discontinua, aunque los de -
más términos sean verdad, la condición en su totalidad resulta falso. Tratándose del OR, sólo con que
uno de los términos evaluados sea cierto, la condición ya se cumple ahí mismo, caso contrario del AND.
En caso de términos adicionales anidados, las reglas para su evaluación se describen en la sgte. página.
Yendo al siguiente ejemplo del tercer grupo, encontramos 3 variables simples, usadas en la parte condi -
cional de la comparación. Como todas las variables tienen valor no cero, todas son verdad, hay por tan-
to el “AND” de esas 3 variables, “r”, “s” y “t” son de tipo float, por lo cual no podrían ser usadas para
este propósito, pero pueden ser comparadas con cero, y el mismo tipo de expresión podría aplicárseles.
Continuando con el cuarto ejemplo del tercer grupo, encontramos 3 asignaciones en la parte compara-
dora del if. A las tres variables se les asignan nuevos valores, los cuales son no cero, por lo tanto produ -
cen un resultado verdad.
Programación C++ Ing. Helmut Heinz Dehner Página 20 de 70
El último ejemplo del tercer grupo contiene una pequeña trampa, pero como ya hemos hablado acerca
de esto, parte de la comparación evalúa falso. El resto de la comparación no es evaluada, porque es un
AND, que al dar falso en la primera comparación, ya la resuelve. Si el programa dependía del valor de
“y”, que había sido inicializada a 3, en la siguiente parte de la comparación cesará porque parará al en-
contrar el falso en el primer término. Por tanto, “z” no tomará valor 4, y la variable “r” no cambiará.
# include <iostream.h>
void main(void)
{
int x = 0,y = 2,z = 1025;
float a = 0.0,b = 3.14159,c = -37.234;
// incrementando
x = x + 1; // Incrementa x
x++; // Incrementa x
++x; // Incrementa x
z = y++; // z = 2, y = 3
z = ++y; // z = 4, y = 4
// decrementando
y = y - 1; // Decrementa y
y--; // Decrementa y
--y; // Decrementa y
y = 3;
z = y--; // z = 3, y = 2
z = --y; // z = 1, y = 1
// operador aritmético
a = a + 12; // Añade 12 a a
a += 12; // Añade 12 más a a
a *= 3.2; // Multiplica a por 3.2
a -= b; // Resta b a a
a /= 10.0; // Divide a entre 10.0
// expresión condicional
a = (b >= 3.0 ? 2.0 : 10.5 ); // Esta expresión
En este programa algunas variables son definidas e inicializadas en el mismo mandato, para su uso pos-
terior.
El primer mandato ejecutable, simplemente suma 1 al valor de “x”. Los dos siguientes mandatos tam-
bién añaden 1 al valor de “x”, pero utilizando el operador de incremento de C++, un doble signo
más (++) antes o después de una variable, incrementa su valor en 1.
Si el signo está antes de la variable, es incrementada antes de su uso: z = ++y, incrementa “y” para
después asignar su valor a “z”.
Si el signo está después de la variable, ésta es usada e incrementada posteriormente: z = y++, asigna
a “z” el valor de “y”, luego incrementa esta última variable.
Otros operadores se usan para modificar una variable en algún valor constante. El primer mandato del
grupo del operador aritmético sencillamente suma 12 al valor de “a”. El segundo hace lo mismo, pero
utilizando la expresión “+=“. Algunas de las funciones aritméticas básicas, +, - ,*,/, pueden tratarse de
esta manera, poniendo la función deseada delante del signo igual, y eliminando la segunda referencia al
nombre de la variable. Nótese que la expresión a la derecha del operador aritmético puede ser expresión
válida.
Al igual que el incremento/decremento, el operador aritmético es una de las herramientas habituales de
un buen programador.
LA EXPRESIÓN CONDICIONAL
La expresión condicional es, al igual que los dos anteriores, un críptico. Consiste en 3 expresiones entre
paréntesis, separadas por un signo de interrogación y dos puntos. La expresión prioritaria en el interro-
gante es evaluada para determinar si es verdad o falso. Si es verdad, la expresión entre interrogantes y
dos puntos es evaluada y, si es “no verdad”, la expresión que sigue a los dos puntos se evalúa. El resul-
tado de la evaluación se usa en la asignación. El resultado final es idéntico que un if con else.
if else
a = (b >= 3.0 ? 2.0 : 10.5 ) Si b >=3.0 “a” será igual a 2.0 sino, “a” se igualará a 10.5
Esto viene ilustrado en el segundo ejemplo de este grupo. La expresión condicional tiene la ventaja aña -
dida de un código más compacto, el cual compilará la máquina en pocas instrucciones en el programa.
Las dos líneas finales del programa ejemplo ilustran una manera muy compacta de asignar la mayor de
2 variables, “a” o “b” a “c” y, de asignar la menor de esas variables a “c”.
#include <iostream.h>
void main(void)
{
(5) const int PRINCIPIO = 3; // El valor de PRINCIPIO no podrá cambiarse
const int FIN = 9; // El valor de FIN no podrá cambiarse
volatile int CENTRO = 6; // El valor de CENTRO podrá ser cambiado
Programación C++ Ing. Helmut Heinz Dehner Página 22 de 70
// por algo externo a este programa.
int indice; // Una variable normal de C
En la línea 5 la constante es de tipo int (entero), se llama PRINCIPIO, y se le asigna el valor 3. El com-
pilador no permitirá que accidentalmente, o aún queriéndolo, se cambie el valor de PRINCIPIO porque
se ha declarado como constante. Si existiera una variable llamada PRINCIPIOS, el sistema no permitiría
que accidentalmente se cambiara el valor de PRINCIPIO. El compilador daría un mensaje de error, ya
que no está permitido cambiar el valor de una constante.
La palabra volatile indica que podrá cambiarse el valor de la variable así declarada. Aunque el valor de
una variable volátil puede ser cambiado por el programador, puede haber otro mecanismo para que el
valor pueda cambiarse, tal como por un procedimiento que ocasione su incremento. El compilador nece-
sita saber que este valor puede ser cambiado por alguna fuerza externa al avanzar el programa.
EL OPERADOR DE ALCANCE
El programa llamado 16OP_ALCAN.CPP ilustra otra construcción que es nueva en C++.
Esto permite acceso al índice declarado como variable global, (declarada antes del main) aunque hay
una variable local del mismo nombre dentro de la función principal.
El uso del doble dos puntos (::) antes del nombre de la variable, en las líneas 10, 12 y 15, indica que
estamos interesados en usar el índice global, definido en la línea 3, y no en el índice local definido en la
línea 7.
#include <iostream.h>
void main(void)
{
(7) float indice = 3.1415;
cout << "El valor del índice local es " << indice << "\n";
(10) cout << "El valor del índice global es " << ::indice << "\n";
cout << "El valor del índice local es " << indice << "\n";
(15) cout << "El valor del índice global es " << ::indice << "\n";
El uso de esta técnica permite acceso a la variable global para cualquier uso. Podría usarse en cálculos,
como un parámetro de función, o para cualquier otro propósito.
En la práctica realmente buena de un programador no se debe abusar de esto, porque podría hacer que
el código sea difícil de leer. Sería mejor usar un nombre diferente para cada variable, en vez de repetir
uno solo, pero esta construcción está disponible si se la necesita alguna vez.
DEFINICIÓN DE VARIABLES
Veamos a continuación el archivo 17VARDEF.CPP
#include <iostream.h>
void main(void)
{
(7) int elemento;
(8) int &otro_elemento = elemento; // Un sinónimo para elemento
(10)elemento = indice + 14; //índice ha sido inicializado a cero y elemento toma su valor modificado
cout << "El elemento tiene el valor " << elemento << "\n";
elemento = 17;
cout << "El otro elemento tiene el valor " << otro_elemento << "\n";
cout << "Otro elemento tiene el valor " << mas_elementos << "\n";
VARIABLE DE REFERENCIA
En la línea 8 se define a la variable “otro_elemento” como una variable de referencia, utilizando el sím-
bolo & (amperson).
La variable de referencia llega a ser un sinónimo para la variable “elemento”. Cambiando el valor de
“elemento” cambiará el valor de “otro_elemento” porque ambas son como una misma variable.
El sinónimo puede usarse para acceder al valor del variable con cualquier propósito. Se debe indicar que
una variable de referencia debe ser inicializada para hacer referencia a alguna otra va-
riable, de no ser así el compilador responderá con un error. Después de la inicialización, la variable no
puede cambiarse para hacer referencia a una variable diferente.
La variable de referencia no debería usarse muy frecuentemente, ya que puede conducir a confusiones
en el programa, pero puede utilizarse cuando el código es claro y fácil de comprender.
DECLARACIONES EJECUTABLES
En la línea 15 hay una declaración extraña, pero legal en C++. Es legal poner una declaración ejecuta-
ble en cualquier lugar del programa, incluso en una definición de variable.
En este caso, definimos la variable “mas_elementos” y la inicializamos con el valor 13.
Es muy importante que el variable se declare cerca de su punto de uso. Esto hace más fácil de ver qué
variable se usa para una determinada orden. Aunque tiene un alcance mucho más restringido.
Definición y declaración
Las palabras de definición y declaración se refieren a dos cosas diferentes en C++.
Los streams predefinidos proveen varias funciones miembro para el manejo de los datos. Algunas de es-
tas funciones son las siguientes:
//Ejemplo
void main(void)
{
float coef[] = { 5198, 3.21, 46.32, 506.5, 2002.38 };
char *prov[] = { "Córdoba", "Misiones", "Salta", "Chaco", "Corrientes" };
EJERCICIOS DE PROGRAMACIÓN
1. Escribir un programa que cuente de 1 a 12 Nº ingresados, que escriba el número en una columna, y
su cuadrado en otra contigua. Cuidar el formato de salida.
2. Escribir un programa que cuente de 1 a 12 Nº ingresados, escriba el número (n), y al lado el resulta -
do de dividir 1/n. Cálculo float de 5 dígitos (5 decimales).
3. Escribir un programa que cuente de 1 a 10 Nº ingresados, pero que sólo imprima los números com-
prendidos entre 32 y 39, uno en cada línea.
5. Escribir un programa con unos valores constantes y con variables volátiles. Ver qué tipo de mensaje
de error da el compilador al intentar cambiar el valor de las constantes.
DEFINES Y MACROS
void main(void)
{
int index,mn,mx;
int count = 5;
Observamos que las 4 primeras líneas de programa empiezan con la palabra "#define". Es la
manera de definir todos los "macros" y las "defines". Antes de empezar la compilación, el compilador
efectúa un paso de preprocesador para resolver todas las "defines". En el caso presente encontrará cada
sitio donde la combinación "START" aparezca y, simplemente la sustituirá por un 0, ya que esto es una
definición. El compilador nunca verá la palabra "START" en toda la compilación. Sólo encontrará ceros.
En este caso se utilizan las palabras "START", "ENDING", etc. Pero pueden utilizarse las que se
quiera, como "INICIO", "FIN", etc.
En el caso de un programa pequeño, como este, no tiene importancia lo que se use, pero imagí -
nese un programa de 2000 líneas y 27 referencias a START. Sería totalmente distinto. Si necesitara
cambiar todos los STARTS del programa por un nuevo número, no habría dificultad en hacerlo con un
"#define", pero más complicado sería cambiar todas las referencias manualmente, y realmente desas-
troso si se deja un par de referencias.
De la misma manera, el preprocesador encontrará todas las apariciones de la palabra "ENDING",
y las cambiará por 9, y el compilador operará en esa línea sin saber que hubo un "ENDING".
Es una buena costumbre en programación el usar mayúsculas para constantes simbólicas, como
"START" y "ENDING", y usar minúsculas para las variables. Per puede usarse el método que se prefiera,
es a gusto de cada uno.
¿ESTO ES ÚTIL?
Cuando en adelante tratemos sobre entrada/salida, necesitaremos alguna manera de conocer el
fin de fichero, en un fichero de entrada. Dado que diferentes compiladores usan distintos valores numé-
ricos para esto, a pesar de que lo más usual es usar 0 o -1, escribiremos un programa con "define" para
definir el EOF(fin de fichero) para nuestro compilador.
Si tras un tiempo cambiamos de intérprete C, será cuestión de modificar la define de acuerdo con
el nuevo compilador. Fin de fichero es otro de los indicadores no universales.
Esto tendrá sentido en temas posteriores.
UN MACRO INCORRECTO
El siguiente es un ejemplo mejor de macro:
20MACRO.C
void main(void)
{
int i,offset;
offset = 5;
for (i = START;i <= STOP;i++) {
printf("El cuadrado de %3d es %4d, y su cubo es %6d\n",
i+offset,SQUR(i+offset),CUBE(i+offset));
printf("El incorrecto de %3d es %6d\n",i+offset,WRONG(i+offset));
}
}
La primera línea define un macro de nombre "WRONG", que sirve para obtener el cubo de "A", y
de hecho lo hace en algunos casos, aunque fracasando estrepitosamente en otros. El segundo macro,
llamado "CUBE" obtiene el cubo en todos los casos.
Consideremos el programa en si, donde el CUBE de i+offset es calculado. Si i es 1, lo cual es la
primera vez, buscaremos el cubo de 1+5+6, el cual es 216. Cuando usamos "CUBE" agrupamos valores
como estos: (1+5)*(1+5)*(1+5) = 6*6*6 =216. Como siempre, si usamos WRONG, los agruparemos
así: 1+5*1+5*1+5 = 1+5+5+5 = 16, lo cual es una respuesta incorrecta. Los paréntesis son básicos
para operar con variables agrupadas. Debe ver bien clara la diferencia entre "CUBE" y "WRONG". Los
valores correctos e incorrectos de cubo y cuadrado aparecen por pantalla para su inspección.
El resto del programa es simple, y no necesita comentarios.
EJERCICIOS DE PROGRAMACIÓN:
1-. Escribir un programa que cuente de 7 a -5 hacia atrás. Usar #define con mandatos para establecer
los límites. Por supuesto, se necesitará una variable decrementadora para la tercera parte del bucle
"for".
# define INICIO 7
# define FIN -5
for(n=INICIO;n>=FIN;n--){
printf("\n %d ",n); }
}
Valores
< 1000
1000 – 2000
2001 – 3000
> 3000
6) Cuatro enteros entre 0 y 100 representan las puntuaciones de un estudiante de un curso de informá-
tica. Escribir un programa para encontrar la media de estas puntuaciones y visualizar una tabla de
notas de acuerdo al siguiente cuadro:
Media Puntuación
90 – 100 A
80 – 89 B
70 –79 C
60 – 69 D
0 – 59 E
7) La fuerza de atracción entre dos masas, m1 y m2, separadas por una distancia d, está dada por la
fórmula:
Escribir un programa que lea la masa de dos cuerpos y la distancia entre ellos y a continuación ob-
tenga la fuerza gravitacional entre ella.
8) La famosa ecuación de Einstein para conversión de una masa m en energía viene dada por la fórmu-
la:
Escribir un programa que lea una masa en gramos y obtenga la cantidad de energía producida cuan-
do la masa se convierte en energía.
9) La relación entre los lados (a,b) de un triángulo rectángulo y la hipotenusa (h) viene dada por la fór-
mula:
a2 + b2 = h2
Escribir un programa que lea la longitud de los lados y calcule la hipotenusa.
10) El área de un triángulo cuyos lados son a, b y c se puede calcular por la fórmula:
Escribir un programa que lea las longitudes de los tres lados de un triángulo y calcule el área del
triángulo.
11) Determinar la media de una lista indefinida de números positivos, terminados con un número ne -
gativo.
12) Dado el número de un mes y si el año es o no bisiesto, deducir el número de días del mes. Un
año es bisiesto si es múltiplo de 4(cuatro), salvo que sea principio de siglo, en cuyo caso NO es bi-
siesto, con la excepción de los que son múltiplos de 400(cuatrocientos).
13) Sumar los números enteros de 1 a 100 mediante:
a) estructura while;
b) estructura do while;
c) estructura for.
14) Determinar la media de una lista de números positivos terminada con un número no positivo des-
pués del ú1timo número válido.
15) Imprimir todos los números primos entre 2 y 1.000 inclusive.
16) Se desea leer las calificaciones de una clase de informática y contar el número total de aprobados
(7 o mayor que 7).
17) Leer las notas de una clase de Informática y deducir todas aquellas que sean NOTABLES ( >= 7 y
< 9).
18) Leer 100 números. Determinar la media de los números positivos y la media de los números ne-
gativos.
19) Un comercio dispone de dos tipos de artículos en fichas correspondientes a diversas sucursales
con los siguientes campos (que se ingresan por teclado):
i) La última ficha del archivo de artículos tiene un código de articulo, una letra X. Se pide:
21) Calcular:
Fibonacci (1) = 1
Fibonacci (2) = 1
Fibonacci (3) = 2 = Fibonacci(2) + Fibonacci(l)
Fibonacci (4) = 3 = Fibonacci(2) + Fibonacci(3)
1 2 3 4 ... 15
** ** ** ** ** **
1* 1 2 3 4 ... 15
2* 2 4 6 8 ... 30
3* 3 6 9 12 ... 45
4* 4 8 12 16 ... 60
FUNCIONES EN C++
Luego, en el programa principal, se llamará a la función escribiendo su nombre seguido por paréntesis:
nombre_función(); Si la función necesita parámetros , éstos estarán dentro del paréntesis, separados
por comas.
#include "stdafx.h"
#include <iostream>
void main(void)
{
cout << "Ahora se llamar"<<char(160)<<" a la funci"<<char(162)<<"n \n";
mayor_y_menor(5, 2, 3);
mayor_y_menor(500, 0, -500);
mayor_y_menor(101, 101, 101);
cout << "\n\nYa se retorn" << char(162) << " al programa principal.\n";
system("pause");
}
Como vemos en la línea 3, la función “mayor_y_menor” es de tipo void (nulo), esto significa que la
función no devolverá un valor al programa. Pero, como lo indican las declaraciones dentro del parénte-
sis, la función espera que el programa sí le pase información, en este caso, esperará tres valores de tipo
int.
En las líneas 20 a 22 vemos los llamados a la función, cada uno especifica los valores que envía a la
misma, todos enteros. Si se tratara de pasar a la función un valor de tipo diferente al especificado, el
compilador generará un error.
En el programa anterior vemos que los tres parámetros son de tipo int, pero no es necesario que todos
los parámetros de una función sean del mismo tipo, pudiendo ser uno de tipo int, otro char, o float, etc.
Veamos cómo la función puede devolver un resultado al programa en el archivo llamado 22FUN-
CION2.CPP:
#include "stdafx.h"
#include <iostream>
return (resultado);
}
void main(void)
{
int x, y;
cout << "El programa le pedir"<<char(160)<<" que ingrese dos n"<<char(163)<<"meros enteros. ";
cout << "\n\nIngrese el primer n" << char(163) << "mero: ";
cin >> x;
cout << "\nIngrese el segundo n" << char(163) << "mero: ";
cin >> y;
cout << "\n\nLa suma de los n" << char(163) << "meros es : " << sumar_valores(x, y);
cout << "\nEl promedio es: " << promedio(x, y)<<endl;
system("pause");
}
En este programa se han declarado dos funciones, la primera devolverá al programa un valor de tipo int
y la segunda uno del tipo float. (Líneas 3 y 11).
Estas funciones utilizan la declaración return (retornar, volver) para devolver o producir un valor (Lí-
neas 7 y 13). Cuando el programa encuentra esta declaración, devuelve o produce el valor especificado
y termina la ejecución de la función, volviendo el control al programa.
Los llamados a las funciones se producen en las líneas 27 y 28, utilizando como parámetros los valores
que el mismo usuario ingresa (“x” e “y”), es decir que los parámetros pueden ser tanto constantes como
variables.
En la declaración de la primer función se utilizaron más líneas que las necesarias, si deseamos simplifi-
car el código del programa, las mismas podrían escribirse de la siguiente manera:
int sumar_valores(int a, int b)
{
return (a+b);
}
De esta manera se ha declarado la segunda función, sin necesidad de declarar una variable extra.
LOS PROTOTIPOS
Examinemos el archivo 23PROTIPO1.CPP
#include "stdafx.h"
#include <iostream>
void main(void)
{
int brazo = 2;
float pie = 1000.0;
char ojo = 66;
#include "stdafx.h"
#include <iostream>
#include <iomanip>
void main(void)
{
int i;
for (i = 32; i <= 127; i++)
relleno(i);
cout << endl;
system("pause");
}
Un prototipo es un modelo limitado de una entidad más completa que vendrá luego. En este caso, la
función “relleno” es la entidad completa que vendrá luego y el prototipo se ilustra en la línea 3. El pro-
totipo proporciona información sobre el tipo devuelto o producido por la función, así como sobre sus pa-
rámetros. Se utiliza para verificar los llamados a la función, ya que controla el número y el tipo de los
parámetros, comprobando si son los apropiados. En nuestro ejemplo, cada llamado a la función llamada
“relleno()” debe tener exactamente tres parámetros o el compilador dará un mensaje de error.
Además del número correcto de parámetros, los tipos deben ser compatibles o el compilador emitirá un
mensaje de error. El aviso sobre el que trabaja el compilador se ve en las líneas 11 y 12, la comproba-
ción de tipo puede hacerse en base al prototipo de la línea 3 aunque la función misma no está definida
aún.
Si el prototipo no es dado, el número de parámetros no se verificará, ni los tipos de los parámetros. Aún
cuando se tiene el número equivocado de parámetros, se conseguirá una compilación y vinculación apa -
rentemente buenas, pero el programa puede hacer algunas cosas extrañas cuando se ejecute. jaja
Aunque deseamos usar el tipo char para “ojos” en la función, queremos usarlo más bien como un núme-
ro y no como un caracter.
El entero en la línea 19 requiere que se exija la impresión del valor numérico como un caracter ASCII. El
próximo ejemplo de programa es similar pero sin el int.
También debería producirse un mensaje de error si se cambia uno de los parámetros en la línea 12 es -
cribiendo un signo amperson frente a uno de los nombres de las variables. Finalmente, cambiando la
primera palabra en la línea 3 entre void e int se puede ver otro mensaje de error. En la línea 15 se re -
querirá que la función concuerde con un prototipo, pero el compilador no lo encontrará.
#include "stdafx.h"
#include <iostream>
void main(void)
{
int brazo = 2;
float pie = 1000.0;
char ojo = 65;
#include "stdafx.h"
#include <iostream>
#include <iomanip>
void relleno(int);
void main(void)
{
int j,i;
for (j = 32,i=1; j < 255; j++,i++)
{
relleno(j);
if (!(i % 9)) i = 0, cout << endl;
}
void relleno(int n)
{
cout << setw(4)<< n << " = " << char(n)<<" | ";
}
#include "stdafx.h"
#include <iostream>
void main(void)
{
int cont = 7, ind = 12;
violin(cont, ind);
Un ejemplo práctico:
#include "stdafx.h"
#include <iostream>
void main(void)
{
menu();
//system("pause");
}
void menu(void)
{
int opc;
float p, q;
for (;;)
{
cout << "\n\n1 - Cartesiana a Polar\n"
<< "2 - Polar a Cartesiana\n\n"
<< "0 - Salir\n\n"
<< "Ingrese opci" << char(162) << "n: ";
cin >> opc;
switch (opc)
{
case 0: break;
case 1: cout << "Ingrese x: ";
cin >> p;
cout << "Ingrese y: ";
cin >> q;
car_pol(p, q);
cout << "Las coordenadas polares R = " << p << "\tA = " << q << endl;
break;
case 2: cout << "Ingrese R: ";
cin >> p;
cout << "Ingrese A: ";
cin >> q;
pol_car(p, q);
cout << "Las coordenadas cartesianas X = " << p << "\tY = " << q << endl;
break;
default:
cout << "\n\nNo es correcta\n\n";
break;
}
if (!opc) break;
}
}
void car_pol(float &x, float &y)
{
float aux = sqrt(pow(x, 2) + pow(y, 2));
y = atan(x / y);
Otra variante:
#include "stdafx.h"
#include <iostream>
#include <iomanip>
void main(void)
{
int opc;
float p, q;
do
{
system("cls");
cout << "1 - Cartesiana a Polar\n"
<< "2 - Polar a Cartesiana\n\n"
<< "0 - Finalizar\n\n"
<< "elija alternativa: ";
cin >> opc;
switch (opc)
{
case 0: break;
case 1: cout << "Ingrese el valor de X: ";
cin >> p;
cout << "Ingrese el valor de Y: ";
cin >> q;
car_pol(p, q); //en p retorna el valor del ángulo y en q retorna el valor de r1
cout << "\n\nLas coordenadas polares correspondientes son " << char(237) << " = "
<< setprecision(15) << p << "\t r = " << setprecision(15) << q << endl;
break;
case 2: cout << "Ingrese el valor del " << char(160) << "ngulo " << char(237) << ": ";
cin >> q;
cout << "Ingrese el valor del vector (R1): ";
cin >> p;
pol_car(p, q);// en p retorna el valor de X y en q retorna el valor de Y
cout << "\n\nLas coordenadas correspondientes son X = "
<< setprecision(15) << p << "\t Y = " << setprecision(15) << q << endl;
break;
default:
cout << "\n\nAlternativa NO disponible\n";
break;
}
if (opc) system("pause");
} while (opc);
}
void car_pol(float &ro, float &r1) //ro --> x; r1 --> y
{
float a = sqrt(pow(ro, 2) + pow(r1, 2));//este sería r1
ro = atan(ro / r1);
Por predefinición, cuando los programas introducen un parámetro a una función, C++ hace una copia
del valor de este parámetro y lo pone dentro de un lugar de memoria temporal llamado pila. Entonces la
función utiliza una copia del valor. Cuando se termina de ejecutar la función, C++ descarta el contenido
de la pila y cualquier cambio que la función haya hecho a la copia.
Para cambiar el valor de un parámetro, la función debe saber la dirección de memoria del parámetro. El
operador de dirección & se utiliza en los programas para indicarle a la función cuál es la dirección del
parámetro para que pueda realizar los cambios deseados.
Este procedimiento es un pase por referencia, permite el pasaje de una variable a una función y retor-
nar los cambios hechos en la función al programa principal.
Observemos el prototipo en la línea 4, donde la segunda variable tiene un signo & delante del nombre
de la variable. Este signo indica al compilador que esa variable actuará como un puntero (indicador) a la
variable real del programa principal que se usará en la función.
En la función misma, en las líneas 21 a 24, la variable “in2” se usa como cualquier otra, pero pasándola
desde el programa principal a la función, no usa una copia de ella. En efecto, el nombre “in2” es un si-
nónimo para la variable “ind” en el programa principal, hace referencia a ella. En cambio, la otra varia -
ble llamada “in1” se trata como cualquier otra variable normal en C.
Cuando el programa se compila y ejecuta, se observa que la variable “in1” cambia en la función pero
vuelve a su valor original cuando se retorna al programa principal (sigue valiendo 7). Sin embargo, la
segunda variable “in2”, cambia en la función y el nuevo valor se refleja en la variable del programa prin-
cipal (su valor cambia de 12 a 112), lo que se puede ver cuando los valores se imprimen por pantalla
(línea 16).
Si se prefiere omitir los nombres de variables en los prototipos, se escribiría el prototipo como se indica
a continuación: void violín (int, int&);
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
void main(void)
{
int x = 10, y = 12, z = 15;
cout << " Algunos datos de la caja son " << volumen(x, y, z) << "\n";
cout << " Algunos datos de la caja son " << volumen(x, y) << "\n";
cout << " Algunos datos de la caja son " << volumen(x) << "\n";
}
Programación C++ Ing. Helmut Heinz Dehner Página 39 de 70
int volumen(int largo, int ancho, int alto)
{
printf("%4d %4d %4d ", largo, ancho, alto);
return largo * ancho * alto;
}
Este programa realmente se ve extraño ya que contiene algunos valores por defecto para los paráme-
tros en el prototipo, pero faltan valores muy útiles como veremos luego.
Este prototipo dice que el primer parámetro llamado “largo” debe darse para cada llamado de esta fun-
ción porque no fue proporcionado ningún valor por defecto.
El segundo parámetro llamado “ancho”, sin embargo, no requiere que se especifique para cada llamado,
ya que si no es especificado, se usará el valor 2 para la variable “ancho” dentro de la función. Asimismo,
el tercer parámetro es optativo, y si no es especificado, el valor 3 se usará para la “altura” dentro de la
función.
En la línea 10 de este programa se especifican los tres parámetros, así que no hay nada de particular en
este llamado a la función.
Sin embargo, en la línea 11, se especifican solamente dos valores, por lo tanto se usará el valor por de-
fecto para el tercer parámetro y el sistema trabajará como si se hubiera llamado a la función con volu-
men(x, y, 3), ya que el valor por defecto para el tercer parámetro es 3. En la línea 12, se especifica úni-
camente un parámetro, que se usará para el primer parámetro formal, y faltarán los otros dos. El siste-
ma considerará el llamado como volumen (x, 2, 3).
Notaremos que la salida por pantalla de estas tres de líneas se revierte. Esto se explicará luego.
Hay unas reglas que deben ser obvias pero serán revisadas de cualquier manera. Una vez que a un pa-
rámetro se le da un valor por defecto o de autoselección en la lista de parámetros formales, todos los
restantes deben tener también valores de autoselección. No es posible dejar hoyos en medio de la lista,
únicamente los valores anteriores pueden faltar. Por supuesto, los valores especificados deben ser de los
tipos correctos o se emitirá un error de compilación. Los valores por defecto pueden darse en el prototi-
po o en la cabecera de función, pero no en ambos.
Si ellos se dan en ambos lugares, el compilador debe usar solamente el valor por defecto, pero debe ve -
rificar cuidadosamente que ambos valores sean idénticos. Esto podría complicar un programa ya muy
complicado, por lo que se recomienda que los valores por defecto se declaren en el prototipo y no en la
función.
#include <iostream.h>
#include <stdarg.h>
void main(void)
{
int ind = 5;
int uno = 1, dos = 2;
mostrar_var(uno, ind);
mostrar_var(3, ind, ind + dos, ind + uno);
mostrar_var(dos, 7, 3);
}
void mostrar_var(int numero, ...)
{
va_list param_pt;
En ciertas ocasiones, podemos desear escribir una función que usa un número variable de parámetros.
La función printf () es un ejemplo de esto. EL ANSI - C tiene una serie de tres macros disponibles en el
archivo "stdarg.h" para permitir el uso de un número variable de argumentos. Estas macros están dispo-
nibles también para el uso con C++, pero necesitamos eliminar de alguna manera la comprobación de
tipos que hace C++ con todas las funciones. Los tres puntos ilustrados en la línea 5 harán esto para no-
sotros. Este prototipo dice que se requiere un único argumento de tipo int como el primer parámetro,
entonces el compilador no hará ninguna comprobación adicional de tipos.
Es evidente que el programa principal consiste en tres de llamados a la función, cada uno con un núme -
ro diferente de parámetros, y el sistema no hace diferencias en los tipos utilizados. Mientras el primer
parámetro sea de tipo int, el sistema compilará y ejecutará el programa sin problemas. Por supuesto el
compilador no comprueba los tipos que estén más allá del primer parámetro. El programador debe ase-
gurarse de que usa los tipos de parámetros adecuados.
En este programa, simplemente se muestran los números por pantalla para ilustrar que son manejados
adecuadamente.
Por supuesto, debemos tener en cuenta que el usar un número variable de argumentos en
un llamado de función puede conducir a obscurecer el código y debe usarse muy poco en un programa,
pero esta posibilidad existe y puede usarse si es necesario.
SOBRECARGA DE FUNCIONES
En C++, dos o más funciones pueden compartir el mismo nombre, siempre y cuando sus declaraciones
de parámetros sean diferentes.
El proceso por el cual varias funciones pueden compartir el mismo nombre se denomina sobrecarga
(overload) de funciones. De estas funciones se dice que están sobrecargadas.
El programa 28SOB_FUNC.CPP es un ejemplo de funciones sobrecargadas, que es una de las claves de
la programación orientada a objetos.
#include "stdafx.h"
#include <iostream>
cout << "El cuadrado de "<< ind<<" es " << relleno(ind) << "\n";
cout << "El cuadrado de "<< 2*ind<<" es " << relleno(2 * ind) << "\n";
cout << "El triple de la longitud es " << relleno(longitud) << "\n";
cout << "El triple de la altura es " << relleno(altura) << "\n";
cout << "El promedio es " << relleno(longitud, altura) << "\n";
system("pause");
}
int relleno(const int valor) // Cuadrado de un número
{
return valor * valor;
}
En este programa ejemplo hay tres funciones, además de la función principal, y las tres tienen el mismo
nombre. La primer pregunta es probablemente "¿Qué función se ejecutará cuando se llame a relleno
() ?" .
La respuesta es que se ejecutará la función que tenga el número correcto de parámetros formales y que
sean del tipo especificado.
Si se llama a la función relleno () con una variable o valor entero como su parámetro real, la función co -
menzará en la línea 22. Si el único parámetro real es de tipo float, la función que comenzará en la línea
27, y si se especifican dos float, la función comenzará en la línea 33.
Es importante destacar que el tipo de regreso no es usado para determinar qué función se llamará. So -
lamente los parámetros formales se usan para determinarlo.
La palabra clave overload usada en la línea 3 sólo es requerida en la versión 1.2 de C++. La versión 2.0
y posteriores de C++ no la requieren, pero permiten usarla opcionalmente a fin de que el código sea
compatible con otros compiladores.
El uso del operador const en algunas de las cabeceras y prototipos de función impide que el programa -
dor cambie accidentalmente el parámetro formal dentro de la función. En funciones tan cortas como és -
tas no hay problema. En una función más importante que se modifica ocasionalmente, se podría olvidar
fácilmente la intención original del uso de un valor e intentar cambiarlo durante la depuración del pro -
grama.
RECURSIVIDAD
En C, las funciones pueden llamarse a sí mismas. Si una expresión en el cuerpo de una función llama a
la propia función, se dice que ésta es recursiva. La recursividad es el proceso de definir algo en términos
de sí mismo y a veces se llama definición circular.
Los ejemplos de recursividad abundan.
No todas la funciones pueden llamarse a sí mismas, sino que deben estar diseñadas especialmente para
que sean recursivas, de otro modo podrían conducir a bucles infinitos, o a que el programa termine
inadecuadamente.
C++ permite la recursividad. Cada vez que se llama a una función, se crea un juego de variables
locales, de este modo, si la función hace una llamada a si misma, se guardan sus variables y
parámetros, usando la pila, y la nueva instancia de la función trabajará con su propia copia de las
variables locales. Cuando esta segunda instancia de la función retorna, recupera las variables y los
parámetros de la pila y continua la ejecución en el punto en que había sido llamada.
Por ejemplo:
Podríamos crear una función recursiva para calcular el factorial de un número entero.
El factorial se simboliza como n!, se lee como "n factorial", y la definición es:
De modo que una función bien hecha para cálculo de factoriales debería incluir un control para esos
casos:
Ejemplo 1
#include "stdafx.h"
#include <iostream>
#include <iomanip>
void main(void)
{
unsigned long int i;
cout << "Ingrese el n"<<char(163)<<"mero a calcular el factorial: ";
cin >> i;
cout << "\nEl factorial de " << i << " = " << setiosflags(ios::scientific)<<setprecision(12)
<< factorial(i)<<endl;
system("pause");
}
Veamos paso a paso, lo que pasa cuando se ejecuta esta función, por ejemplo: factorial(4):
1ª Instancia
n=4
n>1
salida 4 * factorial(3) (Guarda el valor de n = 4)
2a Instancia
n>1
salida 3*factorial(2) (Guarda el valor de n = 3)
3a Instancia
n>1
salida 2*factorial(1) (Guarda el valor de n = 2)
4a Instancia
n == 1 retorna 1
3a Instancia
(recupera n=2 de la pila) retorna 1*2=2
2a instancia
(recupera n=3 de la pila) retorna 2*3=6
1a instancia
(recupera n=4 de la pila) retorna 6*4=24
Valor de retorno 24
Aunque la función factorial es un buen ejemplo para demostrar cómo funciona una función recursiva, la
recursividad no es un buen modo de resolver esta función, que sería más sencilla y rápida con un simple
bucle for.
La principal ventaja de las funciones recursivas es que se pueden usar para crear versiones de algoritmo
más claras y más sencillas. Por ejemplo, la ordenación rápida (quicksort) es difícil implementar en forma
iterativa. Además, algunos problemas, especialmente los problemas relacionados con la inteligencia
artificial parece que tienden ellos mismos hacia soluciones recursivas. Por último, algunas personas
parecen pensar más fácilmente de forma recursiva que de forma iterativa.
Cuando se escriben funciones recursivas, se debe tener una sentencia if en algún sitio que fuerce a la
función a volver sin que se ejecute la llamada recursiva. Si no se hace así, la función nunca devolverá el
control una vez que se le ha llamado. Es un error muy común el escribir funciones recursivas sin un if.
Ejemplo 2
#include "stdafx.h"
#include <iostream>
Ejemplo 3
/*visualizar las permutaciones de n elementos.*/
#include <iostream>
//using namespace std;
/* Prototipo de función */
void Permutaciones(char *, int l=0);
void main(void)
{
char palabra[] = "ABC";
Permutaciones(palabra);
cin.get();
}
EJERCICIOS DE PROGRAMACIÓN
1. Cambiar el tipo de “alas” a float en el prototipo de PROTIPO1.CPP para que disienta con la defini-
ción de función para ver si ocurre un error de compilación.
2. Cambiar la definición de función en PROTIPO1.CPP para acordar con el prototipo cambiado. Compi-
lar y ejecutar el programa sin cambiar los llamados en líneas 11 y 12. Explicar los resultados.
3. En PARAMET.CPP, quitar el valor por defecto para “alto” en el prototipo para ver qué tipo de error
de compilación se produce.
4. En SOB_FUNC.CPP, cambiar los nombres de las tres de funciones para que cada una tenga un nom-
bre único. Comparar el tamaño del archivo ejecutable resultante con el que dio el programa original.
dd/mm/aa
19/9/97
3/9/05
8. Realizar dos funciones que realicen la conversión de coordenadas polares (r, ) a coordenadas
cartesianas (x, y) math.h
9. Escribir una función Salario que calcule los salarios de un trabajador para un número dado de ho-
ras trabajadas y un salario hora. Las horas que superen las 40 horas semanales se pagarán como
extras con un salario hora 1,5 veces el salario ordinario.
10. Escribir una función booleana Dígito que determine si un carácter es uno de los dígitos 0 al 9.
11. Escribir una función booleana Vocal que determine si un carácter es una vocal.
Programación C++ Ing. Helmut Heinz Dehner Página 46 de 70
12. Escribir una función que tenga un argumento de tipo entero y que devuelva la letra P si el núme-
ro es positivo, y la letra N si es cero o negativo.
13. Escribir una función lógica de dos argumentos enteros, que devuelva true si uno divide al otro y
false en caso contrario.
14. Escribir una función que convierta una temperatura dada en grados Celsius a grados Fahrenheit.
La fórmula de conversión es:
15. Escribir una función Redondeo que acepte un valor real Cantidad y un valor entero Decimales y
devuelva el valor de Cantidad redondeado al número especificado de Decimales. Por ejemplo, Re-
dondeo (20.563,2) devuelve el valor 20.56, y Redondeo (20.563,1) devuelve 20.6.
16. Escribir un programa que permita al usuario elegir el cálculo del área de cualquiera de las figuras
geométricas: círculo, cuadrado, rectángulo o triángulo, mediante funciones sobrecargadas.
ARREGLOS Y CADENAS
Como ya sabemos, los programas almacenan información en las variables. Hasta ahora, las variables
utilizadas sólo guardaban un valor. Sin embargo, en muchos casos los programas necesitarán guardar
muchos valores al mismo tiempo, tales como 50 calificaciones, 100 nombres de archivo o 1000 títulos
de libros. Cuando los programas necesitan almacenar muchos valores definen un arreglo. Es decir que
un arreglo es una variable capaz de guardar uno o más valores.
#include "stdafx.h"
#include <iostream>
void main(void)
{
int valores[5]; // Declaración del arreglo
valores[0] = 100;
valores[1] = 200;
valores[2] = 300;
valores[3] = 400;
valores[4] = 500;
En primer lugar se define un arreglo de tipo int llamado “valores”. Los corchetes "[]" definen una matriz
con subíndice, y en el caso del ejemplo, el 5 entre corchetes define 5 campos de datos, tipo int, todo
Programación C++ Ing. Helmut Heinz Dehner Página 47 de 70
ello definido como variable “valores”. En C, los subíndices empiezan desde 0, y se incrementan de
uno en 1 hasta el máximo valor, en este caso, 4. Tenemos, por tanto, 5 variables tipo int, denominadas:
“valores[0]”, “valores[1]”, hasta “valores[4]”.
Recordemos siempre que al partir de 0, los subíndices tienen como máximo valor una posición menos
que en su definición.
Cuando los programas utilizan arreglos, el procedimiento más común es utilizar una variable índice para
indicar a los elementos del arreglo. En el siguiente programa, 31ARREGLO2.CPP, se utiliza el índice
dentro de un bucle for, que inicia al índice “i” en 0. El bucle termina cuando “i” es mayor que 4 (el últi -
mo elemento del arreglo):
#include "stdafx.h"
#include <iostream>
void main(void)
{
int valores[5]; // Declaración del arreglo
int i;
valores[0] = 100;
valores[1] = 200;
valores[2] = 300;
valores[3] = 400;
valores[4] = 500;
#include "stdafx.h"
#include <iostream>
void main(void)
{
int nros_chicos[] = { 1, 2, 3, 4, 5 };
int nros_grandes[] = { 1000, 2000, 3000 };
mostrar_arreglo(nros_chicos, 5);
mostrar_arreglo(nros_grandes, 3);
cout << endl;
system("pause");
}
El programa anterior simplemente pasa el arreglo a la función por medio del nombre. El siguiente pro-
grama, 33TRAERARR.CPP, utiliza la función “traer_valores” para asignar tres valores al arreglo “nume-
ros”:
#include "stdafx.h"
#include <iostream>
void main(void)
{
int numeros[3];
int i;
traer_valores(numeros, 3);
cout << "Los valores del arreglo son : ";
ARREGLOS MULTIDIMENSIONALES
Veamos el programa 34MULTIARR.CPP como un ejemplo del trabajo con arreglos multidimensionales
(matrices):
#include "stdafx.h"
#include <iostream>
void main(void)
La variable “arr1” es un arreglo de 8x8, que contiene 8 veces 8, o 64 elementos en total. El primer ele-
mento es “arr1[0][0]”, y el último “arr1[7][7]”. Otro arreglo, “arr2” es también de este tipo, pero no es
cuadrado, para que se vea que un arreglo multidimensionado no debe ser necesariamente cuadrado.
Ambos arreglos están rellenos con datos, que representan una tabla de multiplicar, y, una tabla de su -
mar, el otro.
Para ilustrar que elementos individuales pueden ser modificados, a uno de los elementos de “arr1” se le
asigna uno de los elementos de “arr2”, tras ser multiplicado por 22 (línea 18). En la siguiente línea, se
le asigna a “arr1[2][2]” el valor arbitrario 5, y se lo usa para el subíndice del siguiente mandato de asig -
nación. El tercer mandato de asignación es en realidad “arr1[5][5] = 177”, porque cada uno de los su -
bíndices contiene el valor 5. Esto sirve a título de ilustración de que cualquier expresión valida puede
usarse como subíndice, sólo debe cumplir 2 reglas, una es que debe ser un entero (aunque un "char"
numérico también valdría), y la otra es que debe estar en el límite del subíndice del arreglo, y no sobre-
pasarlo.
El contenido total de la matriz “arr1” se imprime por pantalla, en forma de cuadrado, con lo cual pode -
mos comprobar por los valores si el programa hace lo que imaginábamos.
¿Es posible recorrer una matriz con un solo bucle y el tamaño de la misma?
#include "stdafx.h"
#include <iostream>
#include <time.h> //Se utiliza para poder generar verdaderos números al azar
#include <iomanip>
#define N 10
#define M 4
void main(void)
{
int mat[N][M];
int i;
#include "stdafx.h"
#include <iostream>
void main(void)
{
char alfabeto[27]; // 26 letras más NULL
char letra;
int i;
Cadenas y funciones
Como en el caso de cualquier arreglo, para trabajar con una cadena en una función, simplemente debe-
mos especificar el tipo de arreglo (char). No se tiene que especificar el tamaño de la cadena. Por ejem-
plo, en el programa 36SHOW_CAD.CPP, se utiliza la función “mostrar_cadena” para mostrar por pan-
talla una cadena de caracteres:
#include "stdafx.h"
#include <iostream>
void main(void)
{
Como ya sabemos, C++ utiliza el caracter NULL para indicar el final de una cadena. A continuación ve -
remos el programa 37LONG_CAD.CPP, que contiene una función que busca el caracter NULL para de-
terminar el número de caracteres que contiene una cadena.
Cuando examinemos más programas C++ encontraremos que muchas funciones buscan en esta forma
el caracter NULL dentro de una cadena de caracteres.
#include "stdafx.h"
#include <iostream>
void main(void)
{
cout << "La cadena '" << titulo << "' contiene " <<
long_cadena(titulo) << " caracteres.\n";
cout << "La cadena '" << capitulo << "' contiene " <<
long_cadena(capitulo) << " caracteres.\n";
cout << "La cadena " << titulo << " contiene " << strlen(titulo) <<" caracteres.\n"
<< "La cadena " << capitulo << " contiene " << strlen(capitulo) << " caracteres.\n";
system("pause");
}
La biblioteca string.h
El archivo string.h contiene muchas funciones para manipular cadenas. Por ejemplo, la función strupr
convierte una cadena de caracteres a mayúsculas. De igual forma, la función strlwr convierte la cadena
a minúsculas. Mientras que strlen regresa el número de caracteres que hay en una cadena. El progra-
ma 38STRING.CPP ilustra el empleo de las dos primeras:
#include "stdafx.h"
#include <iostream>
void main(void)
{
char titulo[] = "Aprenda C++";
char capitulo[] = "Arreglos y Cadenas";
SUBRUTINAS DE CADENAS
Veamos otras funciones de la biblioteca string.h en el programa 39CADENAS.CPP:
#include "stdafx.h"
#include <iostream>
void main(void)
{
char nombre1[12], nombre2[12], cadena[25];
char titulo[20];
Programación C++ Ing. Helmut Heinz Dehner Página 53 de 70
strcpy(nombre1, "Margarita"); //NO ES LICITO PONER nombre1 = "Margarita"
strcpy(nombre2, "Pedro");
strcpy(titulo, "Trabajando con cadenas");
printf("%s\n\n", titulo);
printf("Nombre 1 es %s\n", nombre1);
printf("Nombre 2 es %s\n", nombre2);
strcpy(cadena, nombre1);
strcat(cadena, " y ");
strcat(cadena, nombre2);
printf("Ambos nombres son %s\ny la longitud de la cadena = %i\n", cadena, strlen(cadena));
system("pause");
}
Primero se definen 4 cadenas. Después, en la línea 10, se utiliza una función de nombre “strcpy”, fun-
ción de copia de cadenas. Copia una cadena a otra mientras no aparezca NULL en la cadena origen. Tras
la ejecución de este mandato, “nombre1” contendrá “Margarita” pero sin las dobles comillas, que son
sólo para el compilador (así sabe que estamos definiendo una cadena). De la misma forma, en la si-
guiente línea “Pedro” se copia en “nombre2”, y luego se copia “titulo”. Nótese que no es necesario para
la definición de cadena el que las dos cadenas (origen - destino) sean de la misma longitud, tan solo con
que destino sea igual a origen+NULL, ya vale.
En la línea 18 vemos la función “strcmp”, o función de comparación de cadenas. Devolverá 1 si la pri-
mera cadena es más larga que la segunda, 0 si las 2 tienen la misma longitud y los mismos caracteres,
y -1 si la primera cadena es menor que la segunda. Una de las cadenas, dependiendo del resultado se
copia en la variable “cadena”, y se imprime el nombre más largo alfabéticamente. No debería sorpren -
dernos que “Pedro” gane, ya que es alfabéticamente mayor, no importa su longitud. También hay que
señalar que el resultado varía influido por mayúsculas o minúsculas.
El mandato en la línea 26 tiene otra utilidad, "strcat" o función concatenadora de cadenas (“Suma” de
caracteres). Esta función simplemente añade los caracteres de una cadena al final de otra, tomando cui-
dado de eliminar el NULL intermedio. En este caso, “nombre1” es copiado en “cadena” en la línea ante -
rior, luego se concatenan los 2 blancos, y finalmente la combinación se concatena con “nombre2”. El re-
sultado se imprime, con los dos nombres en “cadena”.
/*
Hacer un programa para que el usuario introduzca dos nombres, sin espacios, y los ordene alfa-
béticamente
*/
#include "stdafx.h"
#include <iostream>
void main(void)
{
char nombre1[30], nombre2[30];
cout << "Ingrese el 1er nombre: ";
cin >> nombre1;
cout << "Ingrese el 2do nombre: ";
cin >> nombre2;
if (!strcmp(nombre1, nombre2)) cout << "\nLos nombres son iguales\n";
Programación C++ Ing. Helmut Heinz Dehner Página 54 de 70
else
if (strcmp(nombre1,nombre2)>0)
cout << nombre2 << " esta antes que " << nombre1 << endl;
else
cout << nombre1 << " esta antes que " << nombre2 << endl;
system("pause");
}
EJERCICIOS DE PROGRAMACIÓN
1. Hacer un programa con 3 cadenas cortas, alrededor de 6 caracteres cada una, y usar “strcpy” para
copiarlas en “uno”, “dos” y “tres”. Concatenar las 3 cadenas en una, e imprimir el resultado 10 ve -
ces.
2-. Definir 2 arreglos de tipo entero, cada uno con 10 elementos, de nombres “arr1” y “arr2”. Usando
un bucle, rellenar con valores informales, y añadir elemento a elemento en otro arreglo, “arreglo”.
Finalmente, imprimir el resultado en una tabla con número de índice. Ejemplo:
1. 2 + 10 = 12
2. 4 + 20 = 24
3. 6 + 30 = 36
etc.
2. Escribir un programa que visualice un cuadrado mágico de orden impar n, comprendido entre 3 y
11; el usuario elige el valor de n. Un cuadrado mágico se compone de números naturales comprendi-
dos entre 1 y n2. La suma de los números que figuran en cada línea, cada columna y cada diagonal
son idénticos. Un ejemplo es:
8 1 6
3 5 7
4 9 2
Un método de construcción del cuadrado consiste en situar el número 1 en el centro de la 1º línea, el
número siguiente en la casilla situada encima y a la derecha, y así sucesivamente. Es preciso consi-
derar que el cuadrado se cierra sobre sí mismo: la línea encima de la 1º es de hecho la última y la
columna a la derecha de la última es la primera. Sin embargo, cuando la posición del número caiga
en una casilla ocupada, se elige la casilla situada por debajo del número que acaba de ser situado.
3. Escribir un programa que efectúe la multiplicación de dos matrices A, B:
A m * p elementos
B p * n elementos
4. Escribir el algoritmo que permita obtener el número de elementos positivos de una tabla.
5. Rellenar una matriz identidad de 4 por 4.
6. Leer una matriz de N por N elementos y calcular la suma de cada una de sus filas y columnas, dejan-
ESTRUCTURAS Y UNIONES
Enumeración de tipos
Examinemos el archivo 40ENUM.CPP como un ejemplo del uso de tipos de variables enumeradas.
#include "stdafx.h"
#include <iostream>
int main()
{
enum TipoFigura { Cuadro, Triangulo, Circulo };
TipoFigura Figura; //Definimos Figura de tipo enumerado TipoFigura
Figura = Circulo;
switch (Figura) {
case Cuadro: cout << "Actividades para Cuadros"; break;
case Triangulo: cout << "Actividades para Triángulo"; break;
case Circulo: cout << "Actividades para C"<<char(161)<<"rculo"; break;
default: cout << "Función no implementada"; break;
}
//Revisamos el valor predeterminado que asigna el compilador a los enumeradores
cout << endl << endl << "Valor de Cuadro: " << Cuadro << endl;
cout << "Valor de Triangulo: " << Triangulo << endl;
cout << "Valor de Circulo: " << Circulo << endl;
system("pause");
}
#define NUM_OPCIONES 5
void main(void)
{
enum { Nuevo, Abrir, Guardar, Cerrar, Salir };
char menu[][10] = { "Nuevo", "Abrir", "Guardar", "Cerrar", "Salir" };
char opcion;
int i, caso;
do
{
/* Visualizar menú y leer la opción */
printf("\nSeleccione una opci%cn:\n\n",char(162));
El uso paralelo de una enumeración y una lista de cadenas facilita notablemente la construcción del pro-
grama; además, se entiende claramente el sentido de las acciones desencadenadas por el programa
principal. Obsérvese que hemos recurrido a leer un carácter, aun cuando la opción es numérica. Una vez
leído el valor de opción, se traduce a un número restándole el valor de '0', de tal modo que el carácter
'0' se convierte en el número 0, el carácter '1' se convierte en el número 1, y así sucesivamente. De
este modo, no es preciso comparar opcion con '4' sino caso con Salir ... y el método debe funcionar
siempre, sin cambios. Obsérvese también que se capturan los posibles errores del usuario: si el valor de
caso no aparece en la lista de sentencias case, se ejecuta el default correspondiente. Esto tendrá impor-
tancia en aquellos programas en que la activación de una opción desencadene la lectura de datos a par -
tir del teclado.
#include "stdafx.h"
#include <iostream>
struct fecha{
int d;
int m;
int a;
};
void main(void)
{
struct mi_estructura
{
boy.initial = 'R';
boy.age = 21;
boy.grade = 75;
/*boy.d_n.d = 15;
boy.d_n.m = 1;
boy.d_n.a = 2000;*/
cout << "Ingrese fecha de nacimiento dd mm aa: ";
cin >> boy.d_n.d >> boy.d_n.m >> boy.d_n.a;
Las estructuras pueden ser de carácter global, de manera que se utilizan en todo el programa. En
el ejemplo de arriba, fecha está definida como global, pero además, lo que se define es un tipo de dato
que se declara o utiliza en el main dentro de otra estructura. Si la estructura está declarada dentro de la
función, tiene validez solo para la función que lo define.
El programa empieza con la definición de una estructura. La palabra clave "struct" es precedida por al-
gunas variables simples entre llaves, las cuales son componentes de la estructura. Las variables lista-
das, de nombre "boy" y "girl" se definen por el tipo mi_estrucutra. De acuerdo con la definición dada an -
teriormente, "boy" es ahora una variable compuesta de 4 elementos, "initial", "age" , "grade" y fecha de
nacimiento. Cada uno de los campos está asociado a "boy" y, cada uno puede almacenar una variable
de su respectivo tipo. La variable "girl" es también una variable con 4 campos asociados con los mismos
nombres que para "boy", pero son variables distintas. Hemos definido por tanto, 8 variables.
ESTRUCTURA DE ARRAYS
42STRUCT2.C
#include "stdafx.h"
#include <iostream>
void main(void)
{
struct {
char initial;
int age;
int grade;
} kids[12];
int index;
Contiene la misma definición de estructura que el anterior, excepto en que en este definimos un
array de 12 variables denominadas "kids" con 3 campos. Este programa contiene, por tanto, 12 veces 3,
o sea, 36 variables simples, cada una de las cuales puede almacenar un dato de acuerdo con su tipo.
También definimos una variable simple denominada "index", para su uso en un bucle.
Para asignar un valor a cada componente, empleamos un bucle "for", y a cada paso del bucle se
efectúa una asignación a cada uno de los 3 componentes. Un paso de bucle asigna todos los valores a
un "kid". Esto no sería muy útil en una situación real, para asignar datos, pero el bucle podría leer de un
fichero y almacenar esos valores en las variables adecuadas. Puede considerarse esto como el principio
de una base de datos, ya que así es.
void main(void)
{
struct person {
char name[25];
int age;
char status; /* M = casado, S = soltero */
};
struct alldat {
int grade;
person descrip;
char lunch[25];
} student[53];
sub.descrip.age = 87;
sub.descrip.status = 'M';
strcpy(sub.descrip.name, "Old Lady Brown");
sub.grade = 73;
strcpy(sub.lunch, "Yogurt and toast");
student[1].descrip.age = 15;
student[1].descrip.status = 'S';
strcpy(student[1].descrip.name, "Billy Boston");
strcpy(student[1].lunch, "Peanut Butter");
student[1].grade = 77;
student[7].descrip.age = 14;
student[12].grade = 87;
cout << "Estudiante = " << student[1].descrip.name << " edad = " << student[1].descrip.age <<
" come = " << student[1].lunch << endl;
system("pause");
}
La primera estructura contiene 3 elementos, pero no está seguida por ningún nombre de variable. No
hemos definido, por tanto variables sólo para la estructura, pero le hemos dado nombre, "person", al
principio de la estructura. Este nombre puede ser utilizado para referirse a la estructura, pero no para
ninguna variable de esta. Hemos creado un nuevo tipo de variable, que podemos manejar tan fácilmen-
La siguiente definición de estructura contiene 3 campos, con el campo central del tipo de la es -
tructura anterior, es decir "person". Esta variable se llama "descript". Por tanto, la nueva estructura
contiene 2 variables simples, "grade" y una cadena denominada "lunch[25]", y la estructura "descript".
Ya que "descript" contiene 3 variables, la nueva estructura contiene realmente 5 variables. A esta es -
tructura se le da otro nombre, "alldat" que además constituye un nuevo tipo de variable. Finalmente de-
finimos un array de 53 variables cada una con la estructura definida por "alldat" y cada una de nombre
"student". Hemos definido un total de 53 veces 5 variables, cada una de las cuales es capaz de almace-
nar un valor.
Ya que hemos creado un nuevo tipo de variable, usémoslo para definir 2 variables más. Las va -
riables "teacher" y "sub" se definen en el siguiente mandato como variables de tipo "alldat", por lo cual
cada variable contiene 5 campos que pueden almacenar datos.
En las 5 siguientes líneas de programa, asignaremos valores a cada uno de los campos de "tea -
cher". El primer campo es "grade" y se expresa igual que las otras estructuras ya estudiadas, porque no
es parte de una estructura anidadas. Para definir este campo, empezamos con la variable "teacher" a la
que añadimos el nombre de grupo "descript", y entonces debemos describir que fichero de la estructura
anidada deseamos, por lo que asignamos "age". "Teacher" viene dado de la misma forma que "Age",
pero a los 2 últimos campos se les ha asignado cadenas, usando "strcpy", función normalmente utilizada
para estos menesteres.
Los nombres de las variables en la función "strcpy" son todavía nombres de variables, aunque es-
tén compuestas de varias partes.
A la variable "sub" le son asignados valores sin sentido de muchas formas, pero en diferente or -
den, ya que no se precisa un orden determinado para hacer estas asignaciones. Finalmente, a un grupo
de variables "student", se les asignan valores, con propósitos ilustrativos y, el programa finaliza. Nin-
guno de los valores se muestra en la pantalla dado que ya lo hicimos con varios en los últimos ejemplos.
44UNION1.C
#include "stdafx.h"
#include <iostream>
void main(void)
{
union {
int value; /*primera parte de la unión*/
long index;
En este ejemplo, tenemos 2 elementos para la unión, la primera parte es un entero, "value" el
cual está almacenado como una variable de 2 bits en algún lugar de la memoria del ordenador. El se-
gundo elemento está constituido por 2 variables tipo caracter, "first" y "second". Estas variables se al-
macenan en la misma localización que "value", porque esto es lo que hace una unión. Permite almace-
nar datos de diferentes tipo en un mismo espacio físico. En este caso, podría ponerse un entero en "va-
lue", y recobrarlo luego en dos mitades, ubicadas en "first" y "second". Esta técnica se utiliza habitual-
mente para empaquetar bytes de datos cuando, por ejemplo, se están combinando datos para ser utili -
zados en los registros del microprocesador.
El acceso a los elementos de la unión es muy parecido a hacerlo en una estructura.
Una nota adicional acerca del programa: cuando se ejecuta en la mayoría de compiladores, los
datos aparecerán por pantalla con dos "f" de guía, debido a la salida en formato hexadecimal de las va -
riables "int" y "char", y añadiendo el signo a la izquierda. Convirtiendo los datos de tipo "char" en "int"
antes de sacarlos por pantalla se podrían evitar las "f". Esto supone la definición de nuevos tipos de va-
riables enteras y la asignación de variables "char" a ellas.
45UNION2.C
#include "stdafx.h"
#include <iostream>
#define AUTO 1
#define BOAT 2
#define PLANE 3
#define SHIP 4
void main(void)
{
struct automobile { /* estructura de un automóvil */
int tires;
int fenders;
int doors;
};
struct {
char vehicle; /* ¨que tipo de vehículo? */
int weight; /* vehículo pesado */
union { /* tipo de dato dependiente */
struct automobile car; /* parte 1 de la union */
BOATDEF boat; /* parte 2 de la union */
struct {
char engines;
int wingspan;
} airplane; /* parte 3 de la union */
BOATDEF ship; /* parte 4 de la union */
} vehicle_type;
int value; /* valor del vehículo (en dólares) */
char owner[32]; /* nombre de los dueños */
} ford, sun_fish, piper_cub; /* 3 variables estructura */
ford.vehicle = AUTO;
ford.weight = 2742; /* con el depósito lleno*/
ford.vehicle_type.car.tires = 5; /* incluyendo repuesto */
ford.vehicle_type.car.doors = 2;
piper_cub.vehicle = PLANE;
piper_cub.vehicle_type.airplane.wingspan = 27;
Primero definimos algunas constantes con el "#define", y comenzamos el programa en si. Definimos una
estructura denominada "automobile", la cual contiene varios campos, con los que no debería existir con-
fusión. No definimos variables, por ahora.
P1 (x1,y1) P2 (x2,y2)
Y
2
Y2 – Y1
Y
X2 –
1
X X1 X
1 2
4) Un número complejo tiene la forma a + bi, donde a y b son números reales e i2 = -1. Las operacio-
nes básicas con números complejos son:
¡
Escribir un programa que lea dos números complejos y el símbolo correspondiente a la operación y
ejecute la operación indicada. Utilizar una estructura para representar números complejos y procedi-
5) Se dispone de un tipo de dato estructurado Tiempo que consta de tres campos: Horas, Minutos y Se-
gundos. Se desea diseñar un Procedimiento / Función que reciba como entrada la hora inicial desde
el comienzo de un experimento y el tiempo transcurrido en segundos y que devuelva como salida la
hora actual. Se debe suponer un reloj de 24 Horas.
6) Se declara un dato estructurado Complejo –dos campos– que representa a los números complejos
(a, bi) que tiene una parte real (a) y una parte imaginaria (bi). Se desea diseñar una serie de proce-
dimientos / funciones que realicen las siguientes tareas:
a) Inicializar a cero el número complejo (a, b) = (0,0).
b) Leer números complejos.
c) Escribir números complejos.
d) Sumar números complejos (a, bi) + (c, di) ) = (a + b), (c + d)i.
e) Restar números complejos (a, bi) - (c, di) ) = (a - b), (c - d)i.
f) Multiplicar complejos (a + bi) * (c + di) ) = (ac - bd), (ad + bc)i.
g) Parte real de un complejo, a.
h) Parte imaginaria de un complejo, bi.
i) Conjugado de un complejo a – bi.
j) Valor absoluto de un complejo.
Índice
PROGRAMACIÓN EN C++----------------------------------------------------------------------------2
Consideraciones Generales-------------------------------------------------------------------------------------3
Un programa sencillo-----------------------------------------------------------------------------------------------4
La declaración #include------------------------------------------------------------------------------------------5
La consola-----------------------------------------------------------------------------------------------------------------5
El operador cout-------------------------------------------------------------------------------------------------------5
IDENTIFICADORES--------------------------------------------------------------------------------------------------6
Declaración de variables-----------------------------------------------------------------------------------------6
EJERCICIOS DE PROGRAMACIÓN:--------------------------------------------------------------------------7
RESUMEN DE LIBRERIAS---------------------------------------------------------------------------------------------8
CADENAS DE FORMATO-----------------------------------------------------------------------------------------------9
Programación C++ Ing. Helmut Heinz Dehner Página 66 de 70
SECUENCIA DE ESCAPE----------------------------------------------------------------------------------------------10
EL BUCLE WHILE-----------------------------------------------------------------------------------------------------11
EL BUCLE DO-WHILE----------------------------------------------------------------------------------------------11
EL BUCLE FOR---------------------------------------------------------------------------------------------------------12
EL CONDICIONAL IF-----------------------------------------------------------------------------------------------13
IF-ELSE--------------------------------------------------------------------------------------------------------------------13
BREAK y CONTINUE------------------------------------------------------------------------------------------------13
LA INSTRUCCIÓN SWITCH-------------------------------------------------------------------------------------14
EJERCICIOS DE PROGRAMACIÓN:------------------------------------------------------------------------14
La función PRINTF()----------------------------------------------------------------------------------------------15
El operador cin--------------------------------------------------------------------------------------------------------17
COMPARACIONES LÓGICAS-----------------------------------------------------------------------------------18
EVALUACIÓN LÓGICA---------------------------------------------------------------------------------------------19
LA EXPRESIÓN CONDICIONAL------------------------------------------------------------------------------21
EL OPERADOR DE ALCANCE-----------------------------------------------------------------------------------22
DEFINICIÓN DE VARIABLES----------------------------------------------------------------------------------23
VARIABLE DE REFERENCIA------------------------------------------------------------------------------------23
DECLARACIONES EJECUTABLES----------------------------------------------------------------------------24
Definición y declaración-----------------------------------------------------------------------------------------24
}-------------------------------------------------------------------------------------------------------------------------------26
EJERCICIOS DE PROGRAMACIÓN--------------------------------------------------------------------------26
DEFINES Y MACROS-----------------------------------------------------------------------------------26
¿ESTO ES ÚTIL?------------------------------------------------------------------------------------------------------27
¿QUÉ ES UN MACRO?----------------------------------------------------------------------------------------------27
UN MACRO INCORRECTO---------------------------------------------------------------------------------------27
EJERCICIOS DE PROGRAMACIÓN:------------------------------------------------------------28
FUNCIONES EN C++-----------------------------------------------------------------------------------30
LOS PROTOTIPOS---------------------------------------------------------------------------------------------------32
SOBRECARGA DE FUNCIONES-------------------------------------------------------------------------------41
RECURSIVIDAD-------------------------------------------------------------------------------------------------------42
Ejemplo 1-----------------------------------------------------------------------------------------------------------------42
Ejemplo 2-----------------------------------------------------------------------------------------------------------------44
Ejemplo 3-----------------------------------------------------------------------------------------------------------------44
EJERCICIOS DE PROGRAMACIÓN--------------------------------------------------------------------------45
Programación C++ Ing. Helmut Heinz Dehner Página 68 de 70
TRABAJO PRÁCTICO DE FUNCIONES--------------------------------------------------------45
ARREGLOS Y CADENAS------------------------------------------------------------------------------46
}-------------------------------------------------------------------------------------------------------------------------------49
ARREGLOS MULTIDIMENSIONALES----------------------------------------------------------------------49
¿Es posible recorrer una matriz con un solo bucle y el tamaño de la misma?-----------------------------------50
Cadenas y funciones----------------------------------------------------------------------------------------------51
La biblioteca string.h---------------------------------------------------------------------------------------------52
SUBRUTINAS DE CADENAS------------------------------------------------------------------------------------53
EJERCICIOS DE PROGRAMACIÓN--------------------------------------------------------------------------54
ESTRUCTURAS Y UNIONES------------------------------------------------------------------------56
Enumeración de tipos--------------------------------------------------------------------------------------------56
ESTRUCTURA DE ARRAYS--------------------------------------------------------------------------------------58