Un programa en C++ puede terminar por las siguientes causas: • Sentencia return desde main()
• Llamada a la función exit() desde cualquier función • Llamada a la función abort() desde cualquier función • Por lanzar una excepción no capturada
Por último, queremos destacar la función que aparece en el Código fuente 128.
int atexit(&fnct); // necesita #include <cstdio>
© Grupo EIDOS 9. Organización de código en C++
133
que ejecuta el código de fnct al salir de la correspondiente función. Debemos destacar que el número de llamadas a atexit está limitado en cada programa. Cuando se alcanza ese límite, se devuelve el valor 0.
Ejercicios
1. Definamos la función g como: int g(double x, float* r, int& a) { ... } ¿cuál de las siguientes invocaciones es correcta?
g(x, 2.0, a); g(&x, r, 1); g(x, &r, a); g(1.0, &r); 2. ¿Es correcto el siguiente código? ¿Porqué?
#include <cstdio> #include <iostream> using namespace std; int g (char *a) { return strlen(a); } int main() { char *z = "Visual C++"; int i = g(z);
cout << "i: " << i << endl; return 0;
}
3. ¿Es correcto el siguiente código?
void erase (double); void erase (float); void hh() { erase(1.0); }
4. ¿Es correcto el siguiente código?
void f (int x, double y = 0.0); void f (int x);
void g (int x) { int h = f(x); }
5. ¿Es correcto el siguiente código?
void f (int x, double y = 0.0, int z);
Lenguaje C / C++ / Visual C++ 6 © Grupo EIDOS
134
void f (int z, double y = 0.0, int x = 1);
7. Realizar un programa que calcule el factorial de un número entero a partir de una función recursiva. El factorial de un número N se define por el producto de sí mismo por todos los enteros positivos menores que él hasta 1, es decir: N*(N-1)*...*2*1.
8. Realizar una versión en C++ del programa cal descrito en el ejercicio 10, capítulo 5 (parte C). (Nota: la manipulación de argumentos en la línea de comandos es igual en C y en C++; el ancho del campo de impresión en cout se expresa llamando a la función cout.width(ancho);
antes de usarlo).
9. Crear una función para dividir dos números de doble precisión y que lance una excepción antes de dividir por cero.
10. Utilizar esta función para un programa calculadora que divide dos números introducidos por el usuario. Capture las excepciones lanzadas.
Respuestas a los ejercicios
1. Definamos la función g como: int g(double x, float* r, int& a) { ... } ¿cuál de las siguientes invocaciones es correcta?
g(x, 2.0, a); g(&x, r, 1); g(x, &r, a); g(1.0, &r); Respuesta:
g(x, 2.0, a); g(&x, r, 1); g(1.0, &r);
2. ¿Es correcto el siguiente código? ¿Porqué?
#include <cstdio> #include <iostream> using namespace std; int g (char *a) { return strlen(a); } int main() { char *z = "Visual C++"; int i = g(z);
cout << "i: " << i << endl; return 0;
}
Respuesta: Sí. Porque a es una cadena de caracteres. 3. ¿Es correcto el siguiente código?
© Grupo EIDOS 9. Organización de código en C++
135
void erase (double); void erase (float); void hh() { erase(1.0); }
Respuesta: No. No es posible determinar que función llamar. 4. ¿Es correcto el siguiente código?
void f (int x, double y = 0.0); void f (int x);
void g (int x) { int h = f(x); }
Respuesta: No. No es posible determinar que función sobrecargar. 5. ¿Es correcto el siguiente código?
void f (int x, double y = 0.0, int z);
Respuesta: No. El argumento y debería ser el último de la lista. 6. ¿Es correcto el siguiente código?
void f (int z, double y = 0.0, int x = 1);
Respuesta: Sí.
7. Realizar un programa que calcule el factorial de un número entero a partir de una función recursiva. El factorial de un número N se define por el producto de sí mismo por todos los enteros positivos menores que él hasta 1, es decir: N*(N-1)*...*2*1.
#include <iostream> using namespace std; long fact (int i) {
return (i > 1) ? i * fact (i-1) : 1; }
int main() {
int x;
cout << "Introduce un numero entero: "; cin >> x;
cout << "Factorial de " << x << " = " << fact (x) << endl; }
8. Realizar una versión en C++ del programa cal descrito en el ejercicio 10, capítulo 5 (parte C). (Nota: la manipulación de argumentos en la línea de comandos es igual en C y en C++; el
Lenguaje C / C++ / Visual C++ 6 © Grupo EIDOS
136
ancho del campo de impresión en cout se expresa llamando a la función cout.width(ancho);
antes de usarlo).
#include <iostream> #include <cstdlib> using namespace std; int bisiesto (int year) {
if ( ( year % 4 == 0 && year % 100 != 0 ) || (year % 400 == 0) ) return 1;
return 0; }
int main (int argc, char* argv[]) {
int i, dia_Ene1, mes, agno, fecha;
int dias_mes[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; char* nombre_mes[] = { "enero", "febrero", "marzo", "abril",
"mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre" };
char _string[60]; if (argc != 3) {
cout << "Uso: ex8 mes año\n"; exit (1);
}
mes = atoi (argv[1]); agno = atoi (argv[2]); if (mes < 1 || mes > 12) {
cout << "Error en la lectura del mes.\n"; exit (1);
}
if (agno < 1900) {
cout << "Error en la lectura del año.\n"; exit (1);
}
// Averiguando el dia de la semana para el año
for (fecha = 1900, dia_Ene1 = 1; fecha < agno; fecha++) {
if (bisiesto (fecha)) dia_Ene1 += 2; else dia_Ene1++;
if (dia_Ene1 >= 7) dia_Ene1 -= 7; }
// 366 dias para un año bisiesto if (bisiesto (agno)) ++dias_mes[1]; for (i = 1; i < mes; i++)
dia_Ene1 = (dia_Ene1 + dias_mes[i-1]) % 7; cout.width (15); cout << nombre_mes[mes-1] << ' '; cout.width (5); cout << agno << endl;
cout << "Dom Lun Mar Mie Jue Vie Sab\n" << "--- --- --- --- --- --- ---\n";
for (fecha = 1; fecha <= dia_Ene1 * 4; fecha++) cout << ' ';
for (fecha = 1; fecha <= dias_mes[mes-1]; fecha++) {
cout.width (3); cout << fecha;
if ((fecha + dia_Ene1) % 7 > 0) cout << ' '; else cout << endl;
© Grupo EIDOS 9. Organización de código en C++
137
cout << endl; return 0; }
9. Crear una función para dividir dos números de doble precisión y que lance una excepción antes de dividir por cero.
struct DividirCero { };
double dividir (double x, double y) {
if (y == 0.0) throw DividirCero; return y/x;
}
10. Utilizar esta función para un programa calculadora que divide dos números introducidos por el usuario. Capture las excepciones lanzadas.
#include <iostream> struct DividirCero { };
double dividir (double x, double y) { DividirCero tmp; if (y == 0.0) throw tmp; return x/y; } int main() { double x, y;
cout << "Introduce 2 números reales para dividirlos: "; cin >> x >> y;
try {
cout << x << " dividido por " << y << " = " << dividir (x, y) << endl;
}
catch (DividirCero) {
cout << "Error grave: intento de division por cero.\n"; }
return 0; }