Programacion Fundamentos
Programacion Fundamentos
Programacion Fundamentos
de la programación
RB
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Fundamentos de la programación
Programming. Principles and Practice Using C++
Del autor del lenguaje C++, un amplio tutorial que enseña a programar
en C++; hace un uso temprano de conceptos de orientación a objetos y
de la STL, que quedan fuera del temario de este curso
lenguaje
Fundamentos de la programación
Fundamentos de la programación
Fundamentos de la programación
1
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Informática, computadoras y programación 3
Lenguaje máquina y ensamblador 12
Lenguajes de programación de alto nivel 15
Un poco de historia 19
Programación e Ingeniería del Software 24
El lenguaje de programación C++ 27
Sintaxis de los lenguajes de programación 30
Un primer programa en C++ 35
Herramientas de desarrollo 39
C++: Un mejor C 45
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 3
Computadora
Máquina electrónica, analógica o digital,
dotada de una memoria de gran capacidad
y de métodos de tratamiento de la información,
capaz de resolver problemas matemáticos y lógicos
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 4
En todas partes y con muchas formas
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 5
Hardware
Componentes que integran
la parte material
de una computadora
Software
Programas, instrucciones
y reglas informáticas
para ejecutar tareas
en una computadora
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 6
Programar
Indicar a la computadora qué es lo que tiene que hacer
Programa
Secuencia de instrucciones
Instrucciones que entiende la computadora
Y que persiguen un objetivo: ¡resolver un problema!
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 7
Trabajo en equipo
Múltiples roles...
Gestores
Analistas
Parque Jurásico Diseñadores
Programadores
Probadores
Administradores de
sistemas
...
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 8
Esquema general
Memoria
temporal
Unidad Central de Proceso
Central Processor Unit
Dispositivos Dispositivos
C.P.U.
de entrada de salida
Teclado Monitor
Ratón Impresora
Escáner Altavoz
Luis Hernández Yáñez
Táctil Almacenamiento …
… permanente
Fundamentos de la programación: Computadoras y programación Página 9
Dispositivos de E/S
Una ALU de 2 bits (Wikipedia)
C.P.U. (Procesador)
A.L.U.
Unidad Aritmético‐Lógica
Memoria
Luis Hernández Yáñez
Unidad de Control
Fundamentos de la programación: Computadoras y programación Página 10
La memoria
Memoria Cada celda en una dirección
01 Celdas de 8 / 16 / 32 / 64 bits
02
03
Información volátil
04
Bus 05 1 Bit = 0 / 1
de 06 1 Byte = 8 bits = 1 carácter
datos 07
1 Kilobyte (KB) = 1024 Bytes
08
1 Megabyte (MB) = 1024 KB
. . .
1 Gigabyte (GB) = 1024 MB
1 Terabyte (TB) = 1024 GB
1 Petabyte (PB) = 1024 TB
Luis Hernández Yáñez
Dirección
210 = 1024 1000
Fundamentos de la programación: Computadoras y programación Página 11
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 12
Los procesadores trabajan con ceros y unos (bits)
Unidad de memoria básica: Byte (8 bits)
(2 dígitos hexadecimales: 01011011 0101 1011 5B)
Lenguaje máquina
Códigos hexadecimales que representan instrucciones,
registros de la CPU, direcciones de memoria o datos
Instrucción Significado Lenguaje de bajo nivel
A0 2F Acceder a la celda de memoria 2F Dependiente de la máquina
3E 01 Copiarlo el registro 1 de la ALU Programación difícil
A0 30 Acceder a la celda de memoria 30
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 13
Mayor legibilidad:
READ 2F Código fuente
REG 01 (lenguaje ensamblador)
READ 30
REG 02
ADD Programa
WRITE 31 ensamblador
(lenguaje máquina)
Fundamentos de la programación: Computadoras y programación Página 14
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 15
Fundamentos de la programación: Computadoras y programación Página 16
Traducción #include <iostream>
using namespace std;
Código fuente int main()
{
cout << "Hola Mundo!" << endl;
Compiladores: }
return 0;
Programa Para una arquitectura concreta
ejecutable y un sistema operativo
Fundamentos de la programación: Computadoras y programación Página 17
Haskell
Lisp Scheme 1987
1958 1975
Logo
1968
Fundamentos de la programación: Computadoras y programación Página 18
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 19
La prehistoria
El ábaco
Fundamentos de la programación: Computadoras y programación Página 20
Siglo XX
1936 Máquina de Turing
1946 ENIAC: Primera computadora digital
de propósito general
1947 El transistor
ENIAC (Wikipedia)
1953 IBM 650: Primera
computadora a gran escala
1966 ARPANET: Origen de Internet
1967 El disquete
1970 Sistema operativo UNIX
1972 Primer virus informático (Creeper)
Luis Hernández Yáñez
Lenguaje de programación C
1974 Protocolo TCP. Primera red local
Fundamentos de la programación: Computadoras y programación Página 21
IBM PC (Wikipedia)
1991 Sistema operativo Linux
Fundamentos de la programación: Computadoras y programación Página 22
1992 Windows 3.1
1995 Lenguaje de programación Java
DVD
1998 Se funda Google
1999 MSN Messenger
Siglo XXI
2001 Windows XP
Mac OS X
2002 Mozilla Firefox
2007 iPhone
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 23
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 24
¿Qué es programar?
Decirle a un tonto muy rápido exactamente lo que tiene que hacer
Especificar la estructura y el comportamiento de un programa,
así como probar que el programa realiza su tarea
adecuadamente y con un rendimiento aceptable
Fundamentos de la programación: Computadoras y programación Página 25
Análisis ¿Qué?
Diseño ¿Cómo?
Programación Implementación
Prueba y depuración
Luis Hernández Yáñez
Mantenimiento
Fundamentos de la programación: Computadoras y programación Página 26
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 27
#include <iostream>
using namespace std;
int main()
{
cout << "Hola Mundo!" << endl;
// Muestra Hola Mundo!
Luis Hernández Yáñez
return 0;
}
Fundamentos de la programación: Computadoras y programación Página 28
Instrucciones
Datos: literales, variables, tipos
Subprogramas (funciones)
Comentarios
Directivas Directiva
#include <iostream>
...
using namespace std;
Comentario
Dato
Instrucción return 0;
}
Fundamentos de la programación: Computadoras y programación Página 29
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 30
Sintaxis y semántica de los lenguajes
Sintaxis
— Reglas que determinan cómo se pueden construir
y secuenciar los elementos del lenguaje
Semántica
— Significado de cada elemento del lenguaje
¿Para qué sirve?
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 31
Especificación
Lenguajes (BNF)
Diagramas
Ejemplo: Números enteros (sin decimales)
BNF
<numero entero> ::= <signo opcional><secuencia de dígitos>
<signo opcional> ::= +|‐|<nada>
<secuencia de dígitos> ::= <dígito>|<dígito><secuencia de dígitos>
<dígito> ::= 0|1|2|3|4|5|6|7|8|9 +23
<nada> ::= | significa ó
‐159
1374
1‐34
+
3.4
Luis Hernández Yáñez
0 .. 9 002
‐
Fundamentos de la programación: Computadoras y programación Página 32
<numero entero> ::= <signo opcional><secuencia de dígitos>
<signo opcional> ::= +|‐|<nada>
<secuencia de dígitos> ::= <dígito>|<dígito><secuencia de dígitos>
<dígito> ::= 0|1|2|3|4|5|6|7|8|9
<nada> ::=
+23
<numero entero> ::= <signo opcional><secuencia de dígitos>
::= +<secuencia de dígitos> ::= +<dígito><secuencia de dígitos>
::= +2<secuencia de dígitos> ::= +2<dígito> ::= +23
1374
<numero entero> ::= <signo opcional><secuencia de dígitos>
::= <secuencia de dígitos> ::= <dígito><secuencia de dígitos>
::= 1<secuencia de dígitos> ::= 1<dígito><secuencia de dígitos>
::= 13<secuencia de dígitos> ::= 13<dígito><secuencia de dígitos>
::= 137<secuencia de dígitos> ::= 137<dígito> ::= 1374
Luis Hernández Yáñez
1‐34
<numero entero> ::= <signo opcional><secuencia de dígitos>
::= <secuencia de dígitos> ::= <dígito><secuencia de dígitos>
::= 1<secuencia de dígitos> ::= ERROR (‐ no es <dígito>)
Fundamentos de la programación: Computadoras y programación Página 33
+23 +
‐
0 .. 9 +23
1374 +
‐
0 .. 9 1374
1‐34 + ?
0 .. 9 1‐
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 34
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 35
Hola Mundo!
Un programa que muestra un saludo en la pantalla:
#include <iostream>
using namespace std;
int main()
// main() es donde empieza la ejecución
{
cout << "Hola Mundo!" << endl; // Muestra Hola Mundo!
Luis Hernández Yáñez
return 0;
}
Fundamentos de la programación: Computadoras y programación Página 36
Análisis del programa
Biblioteca
Instrucción using namespace std;
Coloreado sintáctico
Tipo Palabras reservadas
{
Bloque de código
Instrucción
Número
} Cuerpo de la función
Las instrucciones terminan en ;
Fundamentos de la programación: Computadoras y programación Página 37
Hola Mundo!
Casi todo es infraestructura
Sólo
cout << "Hola Mundo!" << endl
hace algo palpable
Fundamentos de la programación: Computadoras y programación Página 38
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 39
Editor
Bloc de notas, Wordpad, Word, Writer, Gedit, Kwrite, …
(texto simple, sin formatos)
Editores específicos: coloreado sintáctico
Recomendación: Notepad++
Instalación y uso:
Sección
Herramientas de desarrollo
en el Campus Virtual
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 40
hola.cpp Compilador hola.obj
(código fuente) (código objeto)
Código objeto de
Enlazador
la biblioteca iostream
Hola Mundo!
Cargador hola.exe
Luis Hernández Yáñez
(ejecutable)
Fundamentos de la programación: Computadoras y programación Página 41
Compilador
Importante: C++ estándar
Recomendación: GNU G++ (MinGW en Windows)
Instalación y uso:
Sección
Herramientas de desarrollo
en el Campus Virtual
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 42
Entornos de desarrollo
Para editar, compilar y probar el código del programa
Recomendaciones:
— Windows: MS Visual Studio / C++ Express o Eclipse
— Linux: Netbeans o Eclipse
Instalación y uso:
Sección
Herramientas de desarrollo
en el Campus Virtual
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 43
Inicio
Pantalla (cout)
_ Hola Mundo!
cout << "Hola Mundo!" << endl; _
Muestra Hola Mundo!
en la pantalla y salta de línea
return 0;
Devuelve 0 como código
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 44
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 45
El lenguaje C
Lenguaje creado por Dennis M. Ritchie en 1972
Lenguaje de nivel medio:
— Estructuras típicas de los lenguajes de alto nivel
Fundamentos de la programación: Computadoras y programación Página 46
Licencia CC (Creative Commons)
Este tipo de licencias ofrecen algunos derechos a terceras personas
bajo ciertas condiciones.
Este documento tiene establecidas las siguientes:
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
Fundamentos de la programación: Computadoras y programación Página 47
Fundamentos de la programación
2
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Constantes 167
La biblioteca cmath 171
Operaciones con caracteres 174
Fundamentos de la programación: Tipos e instrucciones I
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 50
Go North 3 Blocks;
Stop;
Fundamentos de la programación: Tipos e instrucciones I Página 51
Sintaxis del lenguaje de programación
= Literales
Start
instrucción Stop ;
avanzar
North 1
East 2
Luis Hernández Yáñez
dirección num 3
South
4
West
5
Fundamentos de la programación: Tipos e instrucciones I Página 52
N
El problema a resolver
Estando el coche en la posición A,
conseguir llegar al Cine Tívoli (B) B
Fundamentos de la programación: Tipos e instrucciones I Página 53
N
El algoritmo
Secuencia de pasos que hay que
seguir para resolver el problema
1.‐ Arrancar
2.‐ Ir un bloque al Norte
3.‐ Ir dos bloques al Este
4.‐ Ir cinco bloques al Norte
5.‐ Ir dos bloques al Este
6.‐ Parar
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 54
N
El programa
Instrucciones escritas en
el lenguaje de programación B
Start;
Go North 1 Blocks;
Go East 2 Blocks;
Go North 5 Blocks;
A
Go East 2 Blocks;
Stop;
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 55
El programa
Escribimos el código del programa en un editor
y lo guardamos en un archivo:
Stat;
Go North 1 Blocks Copiamos el archivo
Go East Blocks; en una llave USB
Go Noth 5 Blocks; y lo llevamos al coche
Go West 2 Blocks;
Luis Hernández Yáñez
Stop;
Fundamentos de la programación: Tipos e instrucciones I Página 56
La compilación
Introducimos la llave USB en el coche
y pulsamos el botón de ejecutar el programa:
Stat;
‐‐‐‐^ Unknown word.
Go North 1 Blocks
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐^ ; missing.
Go East Blocks; Errores
‐‐‐‐‐‐‐‐^ Number missing.
de sintaxis
Go Noth 5 Blocks;
‐‐‐‐‐‐‐^ Unknown word.
Go West 2 Blocks;
Luis Hernández Yáñez
Stop;
There are errors. Impossible to run the program.
Fundamentos de la programación: Tipos e instrucciones I Página 57
Depuración
Editamos el código para corregir los errores sintácticos:
Stat; Start;
Go North 1 Blocks Go North 1 Blocks;
Go East Blocks; Go East 3 Blocks;
Go Noth 5 Blocks; Go North 5 Blocks;
Go West 2 Blocks; Go West 2 Blocks;
Stop; Stop;
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 58
N
La ejecución
Se realiza lo que pide
cada instrucción: B
Start;
Go North 1 Blocks;
Go East 3 Blocks;
!
Error de ejecución
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 59
Depuración
Editamos el código para arreglar el error de ejecución:
Start; Start;
Go North 1 Blocks; Go North 1 Blocks;
Go East 3 Blocks; Go East 2 Blocks;
Go North 5 Blocks; Go North 5 Blocks;
Go West 2 Blocks; Go West 2 Blocks;
Stop; Stop;
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 60
N
La ejecución
Se realiza lo que pide ?
cada instrucción: B
Start;
Go North 1 Blocks;
Go East 2 Blocks;
Go North 5 Blocks;
Go West 2 Blocks;
Stop;
Luis Hernández Yáñez
Error lógico
¡El programa no llega al resultado deseado!
Fundamentos de la programación: Tipos e instrucciones I Página 61
Depuración
Editamos el código para arreglar el error lógico:
Start; Start;
Go North 1 Blocks; Go North 1 Blocks;
Go East 2 Blocks; Go East 2 Blocks;
Go North 5 Blocks; Go North 5 Blocks;
Go West 2 Blocks; Go East 2 Blocks;
Stop; Stop;
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 62
N
La ejecución
Se realiza lo que pide
cada instrucción:
Start;
Go North 1 Blocks;
Go East 2 Blocks;
Go North 5 Blocks;
Go East 2 Blocks;
Stop;
Luis Hernández Yáñez
¡Conseguido!
Fundamentos de la programación: Tipos e instrucciones I Página 63
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 64
Hola Mundo!
De vuelta en el programa que muestra un saludo en la pantalla:
#include <iostream>
using namespace std;
return 0;
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 65
Hola Mundo!
La única instrucción que produce algo tangible:
#include <iostream>
using namespace std;
int main() // main() es donde empieza la ejecución
{
cout << "Hola Mundo!" << endl;
return 0;
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 66
cout << "Hola Mundo!" << endl;
Hola Mundo!
_
Fundamentos de la programación: Tipos e instrucciones I Página 67
Pantalla en modo texto
Líneas de 80 caracteres (textos)
Aplicación en modo texto
80 caracteres
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 68
H o l a M u n d o !
...
Luis Hernández Yáñez
...
Fundamentos de la programación: Tipos e instrucciones I Página 69
El insertor << cout << ...;
Inserta textos en la pantalla de modo texto
Representación textual de los datos
A partir de la posición del cursor
Line wrap (continúa en la siguiente línea si no cabe)
Se pueden encadenar:
cout << ... << ... << ...;
Recuerda: las instrucciones terminan en ;
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 70
endl ¡Punto decimal, NO coma!
Fundamentos de la programación: Tipos e instrucciones I Página 71
El programa principal
La función main(): donde comienza la ejecución...
#include <iostream>
using namespace std;
Fundamentos de la programación: Tipos e instrucciones I Página 72
El programa principal
La función main():
Fundamentos de la programación: Tipos e instrucciones I Página 73
Documentando el código...
Comentarios (se ignoran):
#include <iostream>
using namespace std;
int main() // main() es donde empieza la ejecución
{
cout << "Hola Mundo!" << endl;
...
Hasta el final de la línea: // Comentario de una línea
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 74
La infraestructura
Código para reutilizar:
#include <iostream> Una directiva: empieza por #
using namespace std;
int main() // main() es donde empieza la ejecución
{
cout << "Hola Mundo!" << endl;
return 0;
}
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 75
Bibliotecas
Se incluyen con la directiva #include:
#include <iostream>
(Utilidades de entrada/salida por consola)
Para mostrar o leer datos hay que incluir la biblioteca iostream
Espacios de nombres
En iostream hay espacios de nombres; ¿cuál queremos?
#include <iostream>
using namespace std; Es una instrucción: termina en ;
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 76
Compilación y enlace
A menudo en un paso
Código objeto de
Enlazador
la biblioteca iostream
Hola Mundo!
Luis Hernández Yáñez
Cargador hola.exe
(ejecutable)
Fundamentos de la programación: Tipos e instrucciones I Página 77
Elementos del programa
Biblioteca
{
Bloque de código
Número
} Cuerpo de la función
Las instrucciones terminan en ;
Fundamentos de la programación: Tipos e instrucciones I Página 78
int main()
{ ¿Cuál se lee mejor?
cout << "Hola Mundo!" << endl;
Luis Hernández Yáñez
return 0;
}
Fundamentos de la programación: Tipos e instrucciones I Página 79
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 80
int main()
{
return 0;
}
Fundamentos de la programación: Tipos e instrucciones I Página 81
... recitado en la consola
Mostrar los textos con cout <<:
#include <iostream>
using namespace std;
int main()
{
cout << "En un lugar de la Mancha," << endl;
cout << "de cuyo nombre no quiero acordarme," << endl;
cout << "no ha mucho tiempo que vivía un hidalgo de los de
lanza en astillero, ..." << endl;
Luis Hernández Yáñez
return 0;
}
Fundamentos de la programación: Tipos e instrucciones I Página 82
return 0; ↲
}↲
Fundamentos de la programación: Tipos e instrucciones I Página 83
Introducción del código del programa
No hay que partir una cadena literal entre dos líneas:
cout << "no ha mucho tiempo que vivía un hidalgo de ↲
los de lanza en astillero, ..." << endl; ↲
Fundamentos de la programación: Tipos e instrucciones I Página 84
Mantenimiento y reusabilidad
Usa espacio en blanco para separar los elementos:
cout << "En un lugar de la Mancha," << endl;
mejor que
cout<<"En un lugar de la Mancha,"<<endl;
}
¡El estilo importa!
Fundamentos de la programación: Tipos e instrucciones I Página 85
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 86
Operadores aritméticos
+ Suma
‐ Resta
* Multiplicación
/ División
Operadores binarios
operando_izquierdo operador operando_derecho
Operación Resultado
3 + 4 7
2.56 ‐ 3 ‐0.44
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 87
Números literales (concretos)
Enteros: sin parte decimal
Signo negativo (opcional) + secuencia de dígitos
3 143 ‐12 67321 ‐1234
Fundamentos de la programación: Tipos e instrucciones I Página 88
cálculos.cpp
Ejemplo
#include <iostream>
using namespace std;
int main()
Un texto Un número
{
cout << "133 + 1234 = " << 133 + 1234 << endl;
cout << "1234 ‐ 111.5 = " << 1234 ‐ 111.5 << endl;
cout << "34 * 59 = " << 34 * 59 << endl;
cout << "3.4 * 5.93 = " << 3.4 * 5.93 << endl;
cout << "500 / 3 = " << 500 / 3 << endl; // Div. entera
cout << "500.0 / 3 = " << 500.0 / 3 << endl; // Div. real
Luis Hernández Yáñez
return 0;
}
Fundamentos de la programación: Tipos e instrucciones I Página 89
División entera
Luis Hernández Yáñez
División real
Fundamentos de la programación: Tipos e instrucciones I Página 90
División Resultado
500 / 3 166
500.0 / 3 166.667
500 / 3.0 166.667
500.0 / 3.0 166.667
Fundamentos de la programación: Tipos e instrucciones I Página 91
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 92
Fundamentos de la programación: Tipos e instrucciones I Página 93
Declaración de variables tipo nombre;
int cantidad;
Memoria
double precio; cantidad ?
Se reserva espacio suficiente precio ?
...
LAS VARIABLES NO SE INICIALIZAN
No se deben usar hasta que se les haya dado algún valor
Fundamentos de la programación: Tipos e instrucciones I Página 94
#include <iostream> cantidad ?
using namespace std;
precio ?
int main()
total ?
{
int cantidad; ...
double precio, total;
Fundamentos de la programación: Tipos e instrucciones I Página 95
Capacidad de las variables
int
‐2.147.483.648 ... 2.147.483.647
‐2147483648 .. 2147483647
double
2,23 x 10‐308 ... 1,79 x 10+308 y sus negativos
Problemas de precisión
Fundamentos de la programación: Tipos e instrucciones I Página 96
Fundamentos de la programación: Tipos e instrucciones I Página 97
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I Página 98
Expresiones
Secuencias de operandos y operadores
operando operador operando operador operando ...
total = cantidad * precio * 1.18;
Expresión
A igual prioridad se evalúan de izquierda a derecha
Fundamentos de la programación: Tipos e instrucciones I Página 99
Precedencia de los operadores
cantidad1 = 10;
cantidad2 = 2;
precio = 40.0;
total = cantidad1 + cantidad2 * precio;
* antes que + 10 + 2 * 40,0 10 + 80,0 90,0
total = (cantidad1 + cantidad2) * precio;
+ antes que * (10 + 2) * 40,0 12 * 40,0 480,0
Luis Hernández Yáñez
variables.cpp
int main()
{
int cantidad;
double precio, total;
cantidad = 12;
precio = 39.95;
total = cantidad * precio;
cout << cantidad << " x " << precio << " = "
<< total << endl;
Luis Hernández Yáñez
return 0;
}
#include <iostream> cantidad ?
using namespace std;
precio ?
int main()
{
total ?
int cantidad;
double precio, total;
...
Luis Hernández Yáñez
#include <iostream> cantidad 12
using namespace std;
precio ?
int main()
{
total ?
int cantidad;
double precio, total;
cantidad = 12; ...
Luis Hernández Yáñez
#include <iostream> cantidad 12
using namespace std;
precio 39.95
int main()
{
total ?
int cantidad;
double precio, total;
cantidad = 12; ...
precio = 39.95;
Luis Hernández Yáñez
#include <iostream> cantidad 12
using namespace std;
precio 39.95
int main()
{
total 479.4
int cantidad;
double precio, total;
cantidad = 12; ...
precio = 39.95;
total = cantidad * precio;
Luis Hernández Yáñez
#include <iostream> cantidad 12
using namespace std;
precio 39.95
int main()
{
total 479.4
int cantidad;
double precio, total;
cantidad = 12; ...
precio = 39.95;
total = cantidad * precio;
cout << cantidad << " x " << precio << " = "
<< total << endl;
Luis Hernández Yáñez
int main()
{
int cantidad;
double precio, total;
cantidad = 12;
precio = 39.95;
total = cantidad * precio;
cout << cantidad << " x " << precio << " = "
<< total << endl;
Luis Hernández Yáñez
return 0;
}
cin >> cantidad;
Memoria
cin >> cantidad; cantidad 12
?
...
12
1 2 ↲ _
Luis Hernández Yáñez
12 para cantidad
No se puede leer un real
0 para precio y Error
12 para cantidad
.5 0,5 para precio
Lo demás queda pendiente
¡¡¡Lectura correcta!!!
Luis Hernández Yáñez
resultado = numerador / denominador
4. Mostrar el resultado
1. Leer numerador
2. Leer denominador
4. Mostrar resultado
cin >> numerador;
2. Leer denominador
cin >> denominador;
3. Calcular división en resultado
resultado = numerador / denominador;
Luis Hernández Yáñez
4. Mostrar resultado
cout << resultado;
#include <iostream> Numerador: _129
using namespace std; _
Denominador: _
2
_
Resultado: _
64.5
64.5
int main() _
{
Declaraciones double numerador, denominador, resultado;
cout << "Numerador: ";
cin >> numerador;
Entrada
cout << "Denominador: ";
cin >> denominador;
Procesamiento resultado = numerador / denominador;
Luis Hernández Yáñez
Refinamiento
Operaciones (acciones)
cout << ... cin >> ...
area = base * altura / 2
Luis Hernández Yáñez
#include <iostream>
using namespace std;
int main()
{
Declaraciones
1. Mostrar en la pantalla el texto que pida la base del triángulo
return 0;
}
El programa: implementación
#include <iostream>
using namespace std; ¿triβngulo?
int main()
{
double base, altura, area; // Declaraciones
cout << "Introduzca la base del triángulo: "; // 1
cin >> base; // 2
cout << "Introduzca la altura del triángulo: "; // 3
cin >> altura; // 4
area = base * altura / 2; // 5
cout << "El área de un triángulo de base " << base // 6
<< " y altura " << altura << " es: " << area << endl;
Luis Hernández Yáñez
return 0;
} Recuerda: las instrucciones terminan en ;
Literales
Constantes
Con nombre
Datos
Pi = 3.141592653589
Variables
Luis Hernández Yáñez
base, altura, area Identificadores
Sintaxis:
a..z, A..Z, _
0..9, a..z, A..Z, _
typename union unsigned using virtual void
volatile while
balance interesAnual
_base_imponible años
EDAD12 salario_1_mes
cálculoNómina
__edad
valor%100 AlgunValor
100caracteres valor?
Luis Hernández Yáñez
_12_meses
____valor
Fundamentos de la programación: Tipos e instrucciones I Página 132
Luis Hernández Yáñez
int
Números enteros (sin decimales)
float
1363, ‐12, 49
Números reales 12.45, ‐3.1932, 1.16E+02
double
Números reales (mayores intervalo y precisión)
char
Caracteres 'a' , '{', '\t'
bool
Valores lógicos (verdadero/falso) true, false
string
Cadenas de caracteres (biblioteca string) "Hola Mundo!"
Luis Hernández Yáñez
void
Nada, ausencia de tipo, ausencia de dato (funciones)
ISO‐8859‐1
Luis Hernández Yáñez
Valores lógicos
Sólo dos valores posibles:
— Verdadero (true)
— Falso (false)
Literales:
true false
Cadenas de caracteres
"Hola" "Introduce el numerador: " "X142FG5TX?%A"
" "
char
Secuencias de caracteres
Programas con variables de tipo string:
#include <string>
using namespace std;
#include <iostream>
#include <string>
using namespace std; // Un solo using... para ambas bibliotecas
int main()
{
int entero = 3; // Podemos asignar (inicializar) al declarar
double real = 2.153;
char caracter = 'a';
bool cierto = true;
string cadena = "Hola";
cout << "Entero: " << entero << endl;
cout << "Real: " << real << endl;
cout << "Carácter: " << caracter << endl;
cout << "Booleano: " << cierto << endl;
Luis Hernández Yáñez
cout << "Cadena: " << cadena << endl;
Tipo Intervalo
int ‐2147483648 .. 2147483647
unsigned int 0 .. 4294967295
short int ‐32768 .. 32768
unsigned short int 0 .. 65535
long int ‐2147483648 .. 2147483647
unsigned long int 0 .. 4294967295
+|‐ 2.23e‐308 .. 1.79e+308
Luis Hernández Yáñez
double
long double +|‐ 3.37E‐4932 .. 1.18E+4932
[modificadores] tipo lista_de_variables;
Opcional
lista_de_variables Identificador
int i, j, l; ,
short int unidades;
unsigned short int monedas;
double balance, beneficio, perdida;
short int unidades; inicio
02
03
double balance; 04
05
unidades
06
07
balance
08
09
10
11
12
13
Luis Hernández Yáñez
14
15
. . .
— Al declararla
int i = 0, j, l = 26;
Luis Hernández Yáñez
En particular, una expresión
short int unidades = 100; puede ser un literal
int i, j = 2;
i = 23 + j * 5; // i toma el valor 33
Luis Hernández Yáñez
Errores
int a, b, c;
5 = a;
// ERROR: un literal no puede recibir un valor
a + 23 = 5;
// ERROR: no puede haber una expresión a la izda.
b = "abc";
// ERROR: un entero no puede guardar una cadena
c = 23 5;
// ERROR: expresión no válida (falta operador)
Luis Hernández Yáñez
Memoria Memoria
01 01
i i
02
03
04
? 23 + 2 * 5
02
03
04
33
05 05
j j
2 2
06 06
07 07
08 08
09 09
10 10
. . . . . .
Luis Hernández Yáñez
a 3.45 a 3.45
b 127.5 aux = a; b 127.5
aux ? aux 3.45
a 127.5
a = b; b 127.5
aux 3.45
a 127.5
Luis Hernández Yáñez
b = aux; b 3.45
aux 3.45
— Operadores aritméticos
— Asignación (=)
Operadores binarios
— Operando izquierdo operador operando derecho
Operandos: literales, constantes, variables o expresiones
Luis Hernández Yáñez
2 + 3 a * RATIO ‐a + b
(a % b) * (c / d)
División entera:
No se obtienen decimales Queda un resto
123 5
3 24
Luis Hernández Yáñez
123 % 5
#include <iostream> operadores.cpp
using namespace std;
int main() {
int entero1 = 15, entero2 = 4;
double real1 = 15.0, real2 = 4.0;
cout << "Operaciones entre los números 15 y 4:" << endl;
cout << "División entera (/): " << entero1 / entero2 << endl;
cout << "Resto de la división (%): " << entero1 % entero2 << endl;
cout << "División real (/): " << real1 / real2 << endl;
cout << "Num = " << real1 << endl;
real1 = ‐real1;
cout << "Cambia de signo (‐): " << real1 << endl;
real1 = ‐real1;
cout << "Vuelve a cambiar (‐): " << real1 << endl;
cout << "Se incrementa antes (++ prefijo): " << ++real1 << endl;
cout << "Se muestra antes de incrementar (posfijo ++): "
Luis Hernández Yáñez
<< real1++ << endl;
cout << "Ya incrementado: " << real1 << endl;
return 0;
}
44 / 4 ‐ 5
/ antes que ‐
11 ‐ 5 Pon espacio antes y después
de cada operador binario
Luis Hernández Yáñez
#include <iostream>
using namespace std;
int main()
{
double x, f;
cout << "Introduce el valor de X: ";
cin >> x;
f = 3 * x * x / 5 + 6 * x / 7 ‐ 3;
cout << "f(x) = " << f << endl;
return 0;
}
Luis Hernández Yáñez
Asignación Abreviatura
a = a + 12; a += 12;
Igual precedencia
a = a * 3; a *= 3; que la asignación
a = a ‐ 5; a ‐= 5;
a = a / 37; a /= 37; De momento,
mejor evitarlas
Luis Hernández Yáñez
a = a % b; a %= b;
const Declaración de variable con inicializador
const short int Meses = 12;
La constante no podrá volver a
const double Pi = 3.141592,
aparecer a la izquierda de un =
RATIO = 2.179 * Pi;
double total = compra1 + compra2;
cout << total << " (IVA: " << IVA << "%)" << endl;
#include <iostream>
using namespace std;
int main() {
const double Pi = 3.141592;
double radio = 12.2, circunferencia;
circunferencia = 2 * Pi * radio;
cout << "Circunferencia de un círculo de radio "
<< radio << ": " << circunferencia << endl;
const double Euler = 2.718281828459; // Número e
cout << "Número e al cuadrado: " << Euler * Euler << endl;
const int IVA = 21;
int cantidad = 12;
double precio = 39.95, neto, porIVA, total;
neto = cantidad * precio;
porIVA = neto * IVA / 100;
Luis Hernández Yáñez
total = neto + porIVA;
cout << "Total compra: " << total << endl;
return 0;
}
tan(x)
round(x) Redondeo al entero más próximo
trunc(x) Pérdida de la parte decimal (entero)
mates.cpp
#include <iostream>
using namespace std;
#include <cmath>
int main() {
double x, y, f; pow() con argumento entero:
cout << "Valor de X: "; Usa el molde double():
cin >> x; pow(double(i), 5)
cout << "Valor de Y: ";
cin >> y;
f = 2 * pow(x, 5) + sqrt(pow(x, 3) / pow(y, 2))
/ abs(x * y) ‐ cos(y);
cout << "f(x, y) = " << f << endl;
return 0;
Luis Hernández Yáñez
}
Pon un espacio detrás de cada coma en las listas de argumentos
char
Asignación, ++/‐‐ y operadores relacionales
...
#include <cctype>
int main() {
char caracter1 = 'A', caracter2 = '1', caracter3 = '&';
cout << "Carácter 1 (" << caracter1 << ").‐" << endl;
cout << "Alfanumérico? " << isalnum(caracter1) << endl;
cout << "Alfabético? " << isalpha(caracter1) << endl;
cout << "Dígito? " << isdigit(caracter1) << endl;
cout << "Mayúscula? " << isupper(caracter1) << endl;
caracter1 = tolower(caracter1);
cout << "En minúscula: " << caracter1 << endl;
cout << "Carácter 2 (" << caracter2 << ").‐" << endl;
cout << "Alfabético? " << isalpha(caracter2) << endl;
cout << "Dígito? " << isdigit(caracter2) << endl;
cout << "Carácter 3 (" << caracter3 << ").‐" << endl;
cout << "Alfanumérico? " << isalnum(caracter3) << endl;
Luis Hernández Yáñez
cout << "Alfabético? " << isalpha(caracter3) << endl;
cout << "Dígito? " << isdigit(caracter3) << endl;
return 0;
} 1 true / 0 false
Fundamentos de la programación: Tipos e instrucciones I Página 176
Luis Hernández Yáñez
Operadores (prioridad)
< menor que
...
<= menor o igual que
* / %
> mayor que
+ ‐
>= mayor o igual que
Luis Hernández Yáñez
< <= > >=
== igual que
== !=
!= distinto de
= += ‐= *= /= %=
}
else {
cout << num << " es impar";
}
Fundamentos de la programación: Tipos e instrucciones I Página 181
selección.cpp
#include <iostream>
using namespace std;
int main() {
int op1 = 13, op2 = 4;
int opcion;
cout << "1 ‐ Sumar" << endl;
cout << "2 ‐ Restar" << endl;
cout << "Opción: ";
cin >> opcion;
if (opcion == 1) {
cout << op1 + op2 << endl;
}
else {
cout << op1 ‐ op2 << endl;
Luis Hernández Yáñez
}
return 0;
}
{ instrucción } {
intrucción1
Tab ó intrucción2
3 esp. ...
int num, total = 0; intrucciónN
cin >> num; }
if (num > 0)
{
cout << "Positivo"; Ámbito local
total = total + num; (declaraciones locales)
Luis Hernández Yáñez
}
cout << endl;
true false
Condición
while (condición) {
Cuerpo cuerpo
}
Luis Hernández Yáñez
#include <iostream>
using namespace std;
int main() {
int i = 1, n = 0, suma = 0;
while (n <= 0) { // Sólo n positivo
cout << "¿Cuántos números quieres sumar? ";
cin >> n;
}
while (i <= n) {
suma = suma + i;
i++;
}
cout << "Sumatorio de i (1 a " << n << ") = "
Luis Hernández Yáñez
<< suma << endl;
return 0;
}
Iteración condicional
while (i <= n) {
suma = suma + i;
i++;
}
n 5
i 6
2
3
4
5
1
true false suma 15
10
1
3
60
i <= n
suma += i;
i++;
Luis Hernández Yáñez
#include <iostream>
Flujos de texto (streams) using namespace std;
Conectan la ejecución del programa con los dispositivos de E/S
Son secuencias de caracteres
Entrada por teclado: flujo de entrada cin (tipo istream)
Salida por pantalla: flujo de salida cout (tipo ostream)
cin cout
7 3 5 . 3 5 1 Programa 1 6 = l a t o T
cout << "Introduce tu edad: ";
cin >> edad;
#include <string>
using namespace std;
Recuerda:
Espacios en blanco son espacios, tabuladores, saltos de línea, ...
cout << d;
5 4 . 3 2 1
La biblioteca iostream
Luis Hernández Yáñez
T o t a l : 1 2 3 . 4 5 M e s e s : 7 Programa
cout
int meses = 7;
cout << "Total: " << 123.45 << endl << " Meses: " << meses;
cout << 123.45 << endl << " Meses: " << meses;
cout << endl << " Meses: " << meses;
cout << " Meses: " << meses;
Total: 123.45
Luis Hernández Yáñez
Meses: 7 cout << meses;
#include <iomanip>
cout << scientific << d << endl; 1.234500e+002
cout << fixed << setprecision(8) << d << endl; 123.45000000
// Instrucciones:
resultado = 2 * pow(x, 5) + sqrt(pow(x, 3)
/ pow(y, 2)) / abs(x * y) ‐ cos(y);
Luis Hernández Yáñez
return resultado; // Devolución del resultado
}
int valor = f(2, 3);
return 0; // main() devuelve 0 al S.O.
}
Los argumentos no se modifican
} return 0; 256
Esta instrucción }
no se ejecutará nunca
// Prototipos de las funciones (excepto main())
bool par(int num);
bool letra(char car);
int suma(int num);
double formula(int x, int y);
int main() {
int numero, sum, x, y;
char caracter;
double f;
cout << "Entero: ";
cin >> numero;
Luis Hernández Yáñez
if (par(numero)) {
cout << "Par";
}
...
else {
cout << "Impar";
}
cout << endl;
if (numero > 1) {
cout << "Sumatorio de 1 a " << numero << ": "
<< suma(numero) << endl;
}
cout << "Carácter: ";
cin >> caracter;
if (!letra(caracter)) {
cout << "no ";
}
cout << "es una letra" << endl;
cout << "f(x, y) = " << formula(x, y) << endl;
// Los argumentos pueden llamarse igual o no que los parámetros
Luis Hernández Yáñez
return 0;
}
...
bool par(int num) {
bool esPar;
if (num % 2 == 0) {
esPar = true;
}
else {
esPar = false;
}
return esPar;
}
Luis Hernández Yáñez
...
}
return sum;
}
...
f = 2 * pow(x, 5) + sqrt(pow(x, 3) / pow(y, 2))
/ abs(x * y) ‐ cos(y);
return f;
}
Luis Hernández Yáñez
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
2A
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
int 214
float 216
Notación científica 217
double 218
char 220
bool 221
string 222
Literales con especificación de tipo 223
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones I (Anexo)
Números enteros
Intervalo de valores:
‐2147483648 .. 2147483647
Bytes de memoria: 4* (*) Depende de la máquina 01
4 bytes es lo más habitual 02
Literales: Se puede saber cuántos 03
Números enteros
Intervalo de valores:
+/‐ 1.18e‐38 .. 3.40e+38
Bytes de memoria: 4* (*) sizeof(float) 01
+ +
0..9 . 0..9 e,E 0..9
‐ ‐
Intervalo de valores:
+/‐ 2.23e‐308 .. 1.79e+308
Bytes de memoria: 8* (*) sizeof(double) 01
+ +
0..9 . 0..9 e,E 0..9
‐ ‐
Caracteres
Intervalo de valores:
Juego de caracteres (ASCII)
Bytes de memoria: 1 (FC) 01
Literales: 02
03
'a', '%', '\t' 04
Constantes de barra invertida: 05
(O secuencias de escape) 06
Carácter
Valores lógicos
— Falso (false) 01
02
Bytes de memoria: 1 (FC) 03
Literales: 04
05
true, false 06
Secuencias de caracteres
Se asigna la memoria que se necesita para la secuencia concreta
Requieren la biblioteca string con el espacio de nombres std:
#include <string>
using namespace std;
¡Ojo!
Luis Hernández Yáñez
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
3
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
La instrucción switch 302
Repetición 313
El bucle while 316
Fundamentos de la programación: Tipos e instrucciones II
Luis Hernández Yáñez
Tipo
Conjunto de valores con sus posibles operaciones
Valor
Conjunto de bits interpretados como de un tipo concreto
Variable (o constante)
Cierta memoria con nombre para valores de un tipo
Declaración
Instrucción que identifica un nombre
Definición
Declaración que asigna memoria a una variable o constante
Luis Hernández Yáñez
int j = 9; j 9
char c = 'a'; c a
Simples
Estándar: int, float, double, char, bool
Conjunto de valores predeterminado
Estructurados (Tema 5)
Colecciones homogéneas: arrays
Todos los elementos de la colección de un mismo tipo
Promoción
double
double a = 1.5, b; float
long int
b = a + i * j;
int
short int
b = a + 3 * 2;
Valor 3 short int (2 bytes) int (4 bytes)
Luis Hernández Yáñez
b = 1.5 + 6;
Valor 6 int (4 bytes) double (8 bytes)
int a = 3, b = 2;
cout << a / b; // Muestra 1 (división entera)
cout << double(a) / b; // Muestra 1.5 (división real)
Identificador válido
typedef descripción tMiTipo;
typedef descripción tMoneda;
typedef descripción tTiposDeCalificacion;
Luis Hernández Yáñez
enum { Identificador }
enum { centimo, dos_centimos, cinco_centimos,
diez_centimos, veinte_centimos,
medio_euro, euro }
Valores literales que pueden tomar las variables (en amarillo)
Luis Hernández Yáñez
Mejoran la legibilidad
typedef descripción nombre_de_tipo;
Elegimos un nombre para el tipo: tMoneda descripción
typedef enum { centimo, dos_centimos, cinco_centimos,
diez_centimos, veinte_centimos,
medio_euro, euro } tMoneda;
moneda1 dos_centimos
moneda2 euro
(Internamente se usan enteros)
typedef enum { enero, febrero, marzo, abril, mayo, junio, julio,
agosto, septiembre, octubre, noviembre, diciembre } tMes;
int op;
cout << " 1 ‐ Enero" << endl;
cout << " 2 ‐ Febrero" << endl;
cout << " 3 ‐ Marzo" << endl;
cout << " 4 ‐ Abril" << endl;
cout << " 5 ‐ Mayo" << endl;
cout << " 6 ‐ Junio" << endl;
cout << " 7 ‐ Julio" << endl;
cout << " 8 ‐ Agosto" << endl;
cout << " 9 ‐ Septiembre" << endl;
cout << "10 ‐ Octubre" << endl;
cout << "11 ‐ Noviembre" << endl;
Luis Hernández Yáñez
if (mes == enero) {
cout << "enero";
}
if (mes == febrero) {
cout << "febrero";
}
if (mes == marzo) {
cout << "marzo";
}
...
if (mes == diciembre) {
cout << "diciembre";
Luis Hernández Yáñez
i++;
dia = tDiaSemana(i);
typedef enum { enero, febrero, marzo, abril, mayo,
junio, julio, agosto, septiembre, octubre,
noviembre, diciembre } tMes;
int main() {
tDiaSemana hoy = lunes;
Luis Hernández Yáñez
// Mostramos la fecha
cout << "Hoy es: " << cadDia(hoy) << " " << dia
<< " de " << cadMes(mes) << " de " << anio
<< endl;
cout << "Pasada la medianoche..." << endl;
dia++;
int i = int(hoy);
i++;
hoy = tDiaSemana(i);
// Mostramos la fecha
cout << "Hoy es: " << cadDia(hoy) << " " << dia
<< " de " << cadMes(mes) << " de " << anio
<< endl;
Luis Hernández Yáñez
return 0;
}
} }
— Cintas magnéticas
— Memorias USB
...
Normalmente terminan con un dato especial (centinela)
Por ejemplo, un NIF que sea X
Fundamentos de la programación: Tipos e instrucciones II Página 251
#include <fstream>
archivo.close();
Operaciones de lectura
Extractor (>>) archivo >> variable;
Salta primero los espacios en blanco (espacio, tab, Intro, ...)
Datos numéricos: lee hasta el primer carácter no válido
Cadenas (string): lee hasta el siguiente espacio en blanco
archivo.get(c)
Lee el siguiente carácter en la variable c, sea el que sea
getline(archivo, cadena)
Lee en la cadena todos los caracteres que queden en la línea
Incluidos los espacios en blanco
Luis Hernández Yáñez
1 ifstream archivo; 7
6
Flujo de entrada
2 archivo.open("compras.txt"); // Apertura 5
archivo
4
3 archivo >> nif >> unidades >> precio; 3
2
getline(archivo, producto); 1
Programa
4 archivo.close(); // Cierre
Luis Hernández Yáñez
archivo >> nif;
archivo >> unidades;
archivo >> precio;
getline(archivo, producto);
Espacio
12345678F 2 123.95 Reproductor de DVD
Leemos el espacio
(no hacemos nada con él)
Sin espacio
int main() {
const int IVA = 21;
string nif, producto;
int unidades;
double precio, neto, total, iva;
char aux;
ifstream archivo;
int contador = 0;
Luis Hernández Yáñez
archivo.open("compras.txt"); // Apertura
...
if (archivo.is_open()) { // Existe el archivo
archivo >> nif; // Primer NIF
while (nif != "X") {
archivo >> unidades >> precio;
archivo.get(aux); // Salta el espacio
getline(archivo, producto);
contador++;
neto = unidades * precio;
iva = neto * IVA / 100;
total = neto + iva;
cout << "Compra " << contador << ".‐" << endl;
cout << " " << producto << ": " << unidades
<< " x " << fixed << setprecision(2)
<< precio << " = " << neto << " ‐ I.V.A.: "
Luis Hernández Yáñez
¡Atención!
Si el archivo ya existe, se borra todo lo que hubiera
Luis Hernández Yáñez
¡Atención!
Si no se cierra el archivo se puede perder información
int valor = 999;
Programa
2
1 ofstream archivo; 1
Flujo de salida
2 archivo.open("output.txt"); // Apertura ! archivo
a
l
3 archivo << 'X' << " Hola! " << 123.45 o
<< endl << valor << "Bye!"; H
X
4 archivo.close(); // Cierre
Luis Hernández Yáñez
#include <iostream>
#include <string>
using namespace std;
#include <fstream>
int main() {
string nif, producto;
int unidades;
double precio;
char aux;
ofstream archivo;
archivo.open("output.txt"); // Apertura (creación)
Luis Hernández Yáñez
cout << "NIF del cliente (X para terminar): ";
cin >> nif;
...
cin >> nif;
}
...
return 0;
}
Luis Hernández Yáñez
Instrucción 1 cout << "Operando 1: ";
Flujo de ejecución
Instrucción 2 cin >> oper1;
Instrucción 3 cout << "Operando 2: ";
...
cout << "Producto: " << prod;
Luis Hernández Yáñez
Instrucción N return 0;
true
false
Instrucción T Instrucción F
true
false
if true
if‐else‐if
Luis Hernández Yáñez
false
switch
Diagramas de flujo
Inicialización
Sí No
¿Iterar?
Código
Luis Hernández Yáñez
while for
signo.cpp
int num;
cin >> num;
if (num < 0) {
cout << "Negativo";
} cin >> num;
else {
true false
cout << "Positivo"; num < 0
}
cout << "Negativo"; cout << "Positivo";
cout << endl;
Luis Hernández Yáñez
cout << endl;
cout << "Positivo";
Luis Hernández Yáñez
cout << endl;
int num;
cin >> num; ‐5
if (num < 0) { Negativo
cout << "Negativo"; _
}
else {
cout << "Positivo"; cin >> num;
}
cout << endl; true
num < 0 num ‐5
?
cout << "Negativo";
Luis Hernández Yáñez
cout << endl;
int main() {
double numerador, denominador, resultado;
cout << "Numerador: ";
cin >> numerador;
cout << "Denominador: ";
cin >> denominador;
if (denominador == 0) {
cout << "Imposible dividir entre 0!";
}
else {
resultado = numerador / denominador;
Luis Hernández Yáñez
cout << "Resultado: " << resultado << endl;
}
return 0;
}
Fundamentos de la programación: Tipos e instrucciones II Página 281
Luis Hernández Yáñez
Operadores (prioridad)
! NO Monario
...
&& Y Binario
!
|| O Binario
* / %
+ ‐
< <= > >=
== !=
Luis Hernández Yáñez
&&
||
bool cond1, cond2, resultado;
int a = 2, b = 3, c = 4;
resultado = !(a < 5); // !(2 < 5) !true false
cond1 = (a * b + c) >= 12; // 10 >= 12 false
cond2 = (a * (b + c)) >= 12; // 14 >= 12 true
Luis Hernández Yáñez
resultado = cond1 && cond2; // false && true false
resultado = cond1 || cond2; // false || true true
#include <iostream>
using namespace std;
int main()
{
int num;
cout << "Introduce un número entre 1 y 10: ";
cin >> num;
if ((num >= 1) && (num <= 10)) {
cout << "Número dentro del intervalo de valores válidos";
}
else {
cout << "Número no válido!";
}
return 0; Condiciones equivalentes
((num >= 1) && (num <= 10))
Luis Hernández Yáñez
}
((num > 0) && (num < 11))
¡Encierra las condiciones ((num >= 1) && (num < 11))
simples entre paréntesis! ((num > 0) && (num <= 10))
int mes, anio, dias;
cout << "Número de mes: ";
cin >> mes;
cout << "Año: ";
cin >> anio;
if (mes == 2) {
if (bisiesto(mes, anio)) {
dias = 29;
}
else {
dias = 28;
}
}
else {
if ((mes == 1) || (mes == 3) || (mes == 5) || (mes == 7)
|| (mes == 8) || (mes == 10) || (mes == 12)) {
dias = 31;
Luis Hernández Yáñez
}
else {
dias = 30;
}
}
Fundamentos de la programación: Tipos e instrucciones II Página 287
esBisiesto = false;
}
return esBisiesto;
}
}
Luis Hernández Yáñez
else { ...
• Condición compuesta:
Combinación de condiciones simples y operadores lógicos
!isalpha(car)
(num < 0) || (car == 'a')
(num < 0) && ((car == 'a') || !isalpha(car))
Luis Hernández Yáñez
true
false
true
false
true
false
true
false
Luis Hernández Yáñez
if‐else‐if
switch
Ejemplo:
Calificación (en letras)
de un estudiante en base
a su nota numérica (0‐10) == 10
true
cout << "MH"
false
true
>= 9 cout << "SB"
Si nota == 10 entonces MH false
true
si no, si nota >= 9 entonces SB >= 7 cout << "NT"
false
si no, si nota >= 7 entonces NT >= 5
true
cout << "AP"
si no, si nota >= 5 entonces AP false
cout << "SS"
si no SS
Luis Hernández Yáñez
cout << "SS";
} else {
} cout << "SS";
} }
}
Fundamentos de la programación: Tipos e instrucciones II Página 297
if (nota < 5) { cout << "SS"; }
else if (nota < 7) { cout << "AP"; }
else if (nota < 9) { cout << "NT"; }
else if (nota < 10) { cout << "SB"; }
else { cout << "MH"; }
if (nota >= 5) { cout << "AP"; }
else if (nota >= 7) { cout << "NT"; }
Luis Hernández Yáñez
else if (nota >= 9) { cout << "SB"; }
else if (nota == 10) { cout << "MH"; }
else { cout << "SS"; }
Sólo muestra AP o SS
Fundamentos de la programación: Tipos e instrucciones II Página 298
Simplificación de las condiciones
0 SS 5 AP 7 NT 9 SB 10
if (nota == 10) { cout << "MH"; } MH
else if ((nota < 10) && (nota >= 9)) { cout << "SB"; }
else if ((nota < 9) && (nota >= 7)) { cout << "NT"; }
else if ((nota < 7) && (nota >= 5)) { cout << "AP"; }
else if (nota < 5) { cout << "SS"; }
Siempre true: ramas else
Si no es 10, es menor que 10
if (nota == 10) { cout << "MH"; } Si no es >= 9, es menor que 9
else if (nota >= 9) {cout << "SB"; } Si no es >= 7, es menor que 7
Luis Hernández Yáñez
else if (nota >= 7) { cout << "NT"; } …
else if (nota >= 5) { cout << "AP"; } true && X X
else { cout << "SS"; }
nivel.cpp
else {
cout << "Valor no válido" << endl;
}
return 0;
}
Fundamentos de la programación: Tipos e instrucciones II Página 300
if (num == 4) { cout << "Muy alto" << endl; }
else if (num == 3) { cout << "Alto" << endl; }
else if (num == 2) { cout << "Medio" << endl; }
else if (num == 1) { cout << "Bajo" << endl; }
else cout << "Valor no válido" << endl; }
if (num == 4) cout << "Muy alto";
else if (num == 3) cout << "Alto";
else if (num == 2) cout << "Medio";
else if (num == 1) cout << "Bajo";
Luis Hernández Yáñez
else cout << "Valor no válido";
cout << endl;
...
nivel2.cpp
switch (num) {
case 4:
Si num == 4 Muy alto
{ Si num == 3 Alto
}
cout << "Muy alto"; Si num == 2 Medio
break; Si num == 1 Bajo
case 3:
{
cout << "Alto";
}
break;
case 2:
{
cout << "Medio";
}
break;
case 1:
{
cout << "Bajo";
}
break;
Luis Hernández Yáñez
default:
{
cout << "Valor no válido";
}
}
...
}
switch (num) {
...
case 3:
{
cout << "Alto";
}
case 2:
{ Num: 3
cout << "Medio"; Alto
} Medio
case 1: Bajo
{ Valor no válido
cout << "Bajo";
}
default:
Luis Hernández Yáñez
{
cout << "Valor no válido";
}
}
Fundamentos de la programación: Tipos e instrucciones II Página 306
true
num==4 Muy alto
break;
false
Sin break;
true
num==3 Alto
break;
false
Sin break;
true
num==2 Medio
break;
false
Sin break;
true
num==1 Bajo break;
false Sin break;
No válido
Luis Hernández Yáñez
default
return op;
}
{
cout << "En la opción 4..." << endl;
} // En la última no necesitamos break
}
int opcion;
...
opcion = menu();
while (opcion != 0) {
switch (opcion) {
case 1:
{
cout << "En la opción 1..." << endl;
}
break;
...
case 4:
{
cout << "En la opción 4..." << endl;
}
} // switch
...
Luis Hernández Yáñez
opcion = menu();
} // while
cout << "Aprobado"; }
}
break; // 5 o 6: AP
typedef enum { enero, febrero, marzo, abril, mayo, junio,
julio, agosto, septiembre, octubre, noviembre, diciembre }
tMes;
tMes mes;
...
switch (mes) {
case enero:
{
cout << "enero";
}
break;
case febrero:
{
cout << "febrero";
}
break;
...
Luis Hernández Yáñez
case diciembre:
{
cout << "diciembre";
}
}
Fundamentos de la programación: Tipos e instrucciones II Página 312
Luis Hernández Yáñez
Inicialización
Sí No
¿Iterar?
Cuerpo
int i = 1; // Inicialización de la variable i
while (i <= 100) {
cout << i << endl;
i++;
}
Muestra los números del 1 al 100
Luis Hernández Yáñez
int i = 1;
true false
while (i <= 100) { Condición
cout << i << endl; Cuerpo
i++;
}
i = 1
i 100
101
99
?3
2
1
4 _
1
true false 2
i <= 100
3
cout << i << endl;
99
100
Luis Hernández Yáñez
i++ _
primero.cpp
cout << "1er. entero con cuadrado mayor que 1.000: "
<< num << endl;
Luis Hernández Yáñez
return 0;
}
Recorre la secuencia de números 1, 2, 3, 4, 5, ...
Fundamentos de la programación: Tipos e instrucciones II Página 320
sumamedia.cpp
#include <iostream>
using namespace std; Recorre la secuencia
int main() { de números introducidos
double num, suma = 0, media = 0;
int cont = 0;
cout << "Introduce un número (0 para terminar): ";
cin >> num; Leemos el primero
while (num != 0) { // 0 para terminar
suma = suma + num;
cont++;
cout << "Introduce un número (0 para terminar): ";
cin >> num; Leemos el siguiente
}
if (cont > 0) {
media = suma / cont;
}
Luis Hernández Yáñez
cout << "Suma = " << suma << endl;
cout << "Media = " << media << endl;
return 0;
}
for (inicialización; condición; paso) cuerpo
for (int i = 1; i <= 100; i++) {
cout << i;
}
i = 1
true false
i <= 100
cout << i;
i++
Luis Hernández Yáñez
for (int i = 1; i <= 100; i++) {
cout << i << endl;
}
i 2?3
100
101
1
1
... i = 1 2
3
true false
i <= 100
99
cout << i << endl; 100
_
i++
Luis Hernández Yáñez
Muy importante
El cuerpo del bucle NUNCA debe alterar el valor del contador
Garantía de terminación
Todo bucle debe terminar su ejecución
Luis Hernández Yáñez
#include <iostream>
using namespace std;
long long int suma(int n);
int main() {
int num;
cout << "Número final: ";
cin >> num;
if (num > 0) { // El número debe ser positivo
cout << "La suma de los números entre 1 y "
<< num << " es: " << suma(num);
}
return 0;
}
long long int suma(int n) {
long long int total = 0;
Luis Hernández Yáñez
for (int i = 1; i <= n; i++) {
total = total + i;
} Recorre la secuencia de números
return total; 1, 2, 3, 4, 5, ..., n
}
Fundamentos de la programación: Tipos e instrucciones II Página 327
Bucles infinitos
for (int i = 1; i <= 100; i‐‐) ...
1 0 ‐1 ‐2 ‐3 ‐4 ‐5 ‐6 ‐7 ‐8 ‐9 ‐10 ‐11 ...
Luis Hernández Yáñez
Es un error de diseño/programación
3 1
...
#include <iostream>
using namespace std; 1 x 1 = 1
#include <iomanip> 1 x 2 = 2
1 x 3 = 3
1 x 4 = 4
int main() {
...
for (int i = 1; i <= 10; i++) { 1 x 10 = 10
for (int j = 1; j <= 10; j++) { 2 x 1 = 2
cout << setw(2) << i << " x " 2 x 2 = 4
<< setw(2) << j << " = " ...
10 x 7 = 70
<< setw(3) << i * j << endl; 10 x 8 = 80
} 10 x 9 = 90
} 10 x 10 = 100
Luis Hernández Yáñez
return 0;
}
tablas2.cpp
#include <iostream>
using namespace std;
#include <iomanip>
int main() {
for (int i = 1; i <= 10; i++) {
cout << "Tabla del " << i << endl;
cout << "‐‐‐‐‐‐‐‐‐‐‐‐‐‐" << endl;
for (int j = 1; j <= 10; j++) {
cout << setw(2) << i << " x "
<< setw(2) << j << " = "
<< setw(3) << i * j << endl;
}
cout << endl;
Luis Hernández Yáñez
return 0;
}
Fundamentos de la programación: Tipos e instrucciones II Página 334
menú.cpp
#include <iostream>
using namespace std;
#include <iomanip>
int menu(); // 1: Tablas de multiplicación; 2: Sumatorio
long long int suma(int n); // Sumatorio
int main() {
int opcion = menu();
while (opcion != 0) {
switch (opcion) {
case 1:
{
for (int i = 1; i <= 10; i++) {
for (int j = 1; j <= 10; j++) {
cout << setw(2) << i << " x "
<< setw(2) << j << " = "
Luis Hernández Yáñez
<< setw(3) << i * j << endl;
}
}
}
break; ...
Fundamentos de la programación: Tipos e instrucciones II Página 335
case 2:
{
int num = 0;
while (num <= 0) {
cout << "Hasta (positivo)? ";
cin >> num;
}
cout << "La suma de los números del 1 al "
<< num << " es: " << suma(num) << endl;
}
} // switch
opcion = menu();
} // while (opcion != 0)
return 0;
}
Luis Hernández Yáñez
total = total + i;
}
return total;
}
Fundamentos de la programación: Tipos e instrucciones II Página 337
while (opcion != 0) {
...
for (int i = 1; i <= 10; i++) {
for (int j = 1; j <= 10; j++) {
...
}
}
while (num <= 0) {
...
} suma()
for (int i = 1; i <= n; i++) {
...
}
while ((op < 0) || (op > 2)) {
Luis Hernández Yáñez
...
} menu()
}
Fundamentos de la programación: Tipos e instrucciones II Página 338
Luis Hernández Yáñez
cout << "Media = " << suma / cont << endl;
return 0;
}
int main() {
double d; Ámbito de la variable d
if (...) {
int cont = 0;
for (int i = 0; i <= 10; i++) {
...
}
}
char c;
if (...) {
double x;
...
Luis Hernández Yáñez
}
return 0;
}
}
return 0;
}
int main() {
double d;
if (...) {
int cont = 0;
for (int i = 0; i <= 10; i++) {
...
} Ámbito de la variable i
}
char c;
if (...) {
double x;
...
Luis Hernández Yáñez
}
return 0;
}
}
return 0;
}
int main() {
double d;
if (...) {
int cont = 0;
for (int i = 0; i <= 10; i++) {
...
}
}
char c;
if (...) {
double x;
... Ámbito de la variable x
Luis Hernández Yáñez
}
return 0;
}
int main() {
int i, x; Oculta , en su ámbito, a la i anterior
if (...) {
int i = 0; Oculta , en su ámbito, a la i anterior
for(int i = 0; i <= 10; i++) {
...
}
}
char c;
if (...) {
double x; Oculta , en su ámbito, a la x anterior
...
Luis Hernández Yáñez
}
return 0;
}
elemento secuencia
secuencia o
1 34 12 26 4 87 184 52
Comienza en un primer elemento (si no está vacía)
A cada elemento le sigue otra secuencia (vacía, si es el último)
Acceso secuencial (lineal)
Se comienza siempre accediendo al primer elemento
Desde un elemento sólo se puede acceder a su elemento siguiente
Luis Hernández Yáñez
1 34 12 26 4 87 184 52 ‐1
Valor centinela:
Valor especial al final que no puede darse en la secuencia
(Secuencia de números positivos centinela: cualquier negativo)
Luis Hernández Yáñez
12 4 37 23 8 19 83 63 2 35 17 76 15 ‐1
12 4 37 23 8 19 83 63 ‐1 35 17 76 15
No se procesan
Búsqueda
Recorrido de la secuencia hasta encontrar un elemento buscado
Ej.‐ Localizar el primer número que sea mayor que 1.000
Termina al localizar el primer elemento que cumple la condición
Luis Hernández Yáñez
true
¿Al final?
false No sabemos cuántos
elementos hay
Obtener elemento
No podemos
Procesar elemento implementar con for
Luis Hernández Yáñez
Finalización
Obtener siguiente
Luis Hernández Yáñez
Finalización
}
cout << "Suma = " << suma << endl; Finalización
int longitud() {
int l = 0;
char c;
cout << "Texto terminado en punto: ";
cin >> c; // Obtener primer carácter
while (c != '.') { // Mientras no el centinela
l++; // Procesar
cin >> c; // Obtener siguiente carácter
}
Luis Hernández Yáñez
return l;
}
}
cout << buscado << " aparece " << cont
<< " veces.";
Fundamentos de la programación: Tipos e instrucciones II Página 361
Centinela: 0
int sumaSecuencia() {
double d, suma = 0;
ifstream archivo; // Archivo de entrada (lectura)
archivo.open("datos.txt");
if (archivo.is_open()) {
archivo >> d; // Obtener el primero
while (d != 0) { // Mientras no sea el centinela
suma = suma + d; // Procesar el dato
archivo >> d; // Obtener el siguiente
}
Luis Hernández Yáñez
archivo.close();
}
return suma;
}
Fundamentos de la programación: Tipos e instrucciones II Página 362
Luis Hernández Yáñez
sumatorio.cpp
Recurrencia: ei+1 = ei + 1 e1 = 1
1 2 3 4 5 6 7 8 ...
Suma de los números de la secuencia calculada:
int main() {
int num;
cout << "N = ";
cin >> num;
cout << "Sumatorio:" << suma(num);
return 0;
}
long long int suma(int n) {
int sumatorio = 0;
for (int i = 1; i <= n; i++) {
Luis Hernández Yáñez
sumatorio = sumatorio + i;
}
return sumatorio;
Último elemento de la secuencia: n
}
Fundamentos de la programación: Tipos e instrucciones II Página 364
long long int suma(int n) {
int sumatorio = 0;
for (int i = 1; i <= n; i++) {
sumatorio = sumatorio + i;
}
...
sumatorio = 0;
int i = 1;
n 5
?
sumatorio 15
10
01
3
6 false
i <= n
i 2
51
4
3
6 2 1
1
5 4 3 2 1
4 3 2 1
3 2 1
true
sumatorio += i;
Secuencia
Luis Hernández Yáñez
i = i + 1;
Definición
Fi = Fi‐1 + Fi‐2
F1 = 0
F2 = 1
0 1 1 2 3 5 8 13 21 34 55 89 ...
¿Fin de la secuencia?
Primer número de Fibonacci mayor que un número dado
Ese número de Fibonacci actúa como centinela
Si num es 50, la secuencia será:
Luis Hernández Yáñez
0 1 1 2 3 5 8 13 21 34
}
¿Demasiados comentarios?
Para no oscurecer el código, mejor una explicación al principio
fibMenos1 3
1
2
?
Luis Hernández Yáñez
fibMenos2 2
1
0
?
Inicialización / encontrado = false;
Obtener elemento
¿Encontrado?
Luis Hernández Yáñez
Finalización
Obtener siguiente
Luis Hernández Yáñez
Finalización
Centinela: ‐1
double d, num;
bool encontrado = false;
cout << "Encontrar primero mayor que: ";
cin >> num;
cout << "Siguiente (‐1 para terminar): ";
cin >> d; // Obtener el primer elemento
while ((d != ‐1) && !encontrado) {
// Mientras no sea el centinela y no se encuentre
if (d > num) { // ¿Encontrado?
encontrado = true;
}
else {
Luis Hernández Yáñez
cout << "Siguiente (‐1 para terminar): ";
cin >> d; // Obtener el siguiente elemento
}
}
Fundamentos de la programación: Tipos e instrucciones II Página 373
Luis Hernández Yáñez
Estructura secuencial
Cada elemento se encuentra en una posición (índice):
Los índices son enteros positivos
El índice del primer elemento siempre es 0
Los índices se incrementan de uno en uno
ventas 125.40 76.95 328.80 254.62 435.00 164.29 0.00
0 1 2 3 4 5 6
Acceso directo
A cada elemento se accede a través de su índice:
ventas[4] accede al 5º elemento (contiene el valor 435.00)
Luis Hernández Yáñez
cout << ventas[4];
ventas[4] = 442.75; Datos de un mismo tipo base:
Se usan como cualquier variable
Ejemplos:
typedef double tTemp[7];
typedef short int tDiasMes[12];
typedef char tVocales[5];
typedef double tVentas[31];
typedef tMoneda tCalderilla[15]; // Enumerado tMoneda
Ejemplos:
tTemp tempMax; tempMax ? ? ? ? ? ? ?
0 1 2 3 4 5 6
ventasFeb ? ? ? ? ? ? ? ? ? ? ? ? ? ... ?
tVentas ventasFeb;
Luis Hernández Yáñez
0 1 2 3 4 5 6 7 8 9 10 11 12 30
nombre[índice]
Cada elemento se accede a través de su índice (posición en el array)
tVocales vocales; typedef char tVocales[5];
5 elementos, índices de 0 a 4:
vocales[0] vocales[1] vocales[2] vocales[3] vocales[4]
Procesamiento de cada elemento:
Como cualquier otra variable del tipo base
cout << vocales[4];
Luis Hernández Yáñez
vocales[3] = 'o';
if (vocales[i] == 'e') ...
tTemp temp;
double media, total = 0; Memoria
... Dias 7
for (int i = 0; i < Dias; i++) { temp[0] 12.40
total = total + temp[i];
temp[1] 10.96
}
temp[2] 8.43
i = 0 temp[3] 11.65
temp[4] 13.70
i++ i 3
70
2
4
1
#include <iostream>
using namespace std;
int main() {
tTemp temp;
for (int i = 0; i < Dias; i++) { // Recorrido del array
cout << "Temperatura del día " << i + 1 << ": ";
cin >> temp[i];
}
cout << "Temperatura media: " << media(temp) << endl;
Luis Hernández Yáñez
return 0;
} Los usuarios usan de 1 a 7 para numerar los días
... La interfaz debe aproximarse a los usuarios,
aunque internamente se usen los índices de 0 a 6
return med;
}
tCalderilla bolsillo; // Exactamente llevo Cuantas monedas
bolsillo[0] = euro;
bolsillo[1] = cinco_centimos;
bolsillo[2] = medio_euro;
bolsillo[3] = euro;
bolsillo[4] = centimo;
...
Luis Hernández Yáñez
for (int moneda = 0; moneda < Cuantas; moneda++)
cout << aCadena(bolsillo[moneda]) << endl;
if (!encontrado) {
ind = ‐1;
}
return ind;
}
Fundamentos de la programación: Tipos e instrucciones II Página 389
Luis Hernández Yáñez
#include <iostream>
using namespace std;
#include <fstream>
int main() {
tArray lista;
int contador = 0;
double valor, med;
ifstream archivo;
archivo.open("lista.txt");
if (archivo.is_open()) {
archivo >> valor;
Luis Hernández Yáñez
while ((valor != ‐1) && (contador < Max)) {
lista[contador] = valor;
contador++;
archivo >> valor;
} ...
Fundamentos de la programación: Tipos e instrucciones II Página 395
archivo.close();
med = media(lista, contador);
cout << "Media de los elementos de la lista: " << med << endl;
}
else {
cout << "¡No se pudo abrir el archivo!" << endl;
}
return 0;
}
med = total / cont;
return med;
}
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
3A
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
?:
c = false ? 2 : 3; = += ‐= *= /= %=
c = 3;
Es equivalente a:
if (a + b == 10) c = 2;
else c = 3;
Se pueden concatenar:
cout << (nota == 10 ? "MH" : (nota >= 9 ? "SB" :
(nota >= 7 ? "NT" : (nota >= 5 ? "AP" : "SS"))))
Esto es equivalente a la escala if‐else‐if de la siguiente sección.
Luis Hernández Yáñez
"SS"
else if (nota >= 5) { cout << "AP"; }
else { cout << "SS"; }
3E
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Recorridos 404
Un aparcamiento 405
¿Paréntesis bien emparejados? 409
¿Dos secuencias iguales? 412
Números primos menores que N 413
Búsquedas 417
Búsqueda de un número en un archivo 419
Búsquedas en secuencias ordenadas 420
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones II (Anexo II)
Luis Hernández Yáñez
int main() {
int coches;
char c;
bool terminar = false;
ifstream archivo;
archivo.open("parking.txt");
if (!archivo.is_open()) {
cout << "¡No se ha podido abrir el archivo!" << endl;
}
else {
// Recorrido...
archivo.close();
Luis Hernández Yáñez
}
return 0;
}
Fundamentos de la programación: Tipos e instrucciones II (Anexo II) Página 406
while (!terminar) {
archivo >> c;
if (c == '.') { // . como primer carácter? (centinela)
terminar = true;
}
else {
coches = 0;
while (c != '.') { // Recorrido de la secuencia
cout << c;
if (c == 'E') {
coches++;
}
else if (c == 'S') {
coches‐‐;
}
Luis Hernández Yáñez
archivo >> c;
}
...
Fundamentos de la programación: Tipos e instrucciones II (Anexo II) Página 407
parking.cpp
if (coches >= 0) {
cout << endl << "Quedan " << coches << " coches.";
}
else {
cout << endl << "Error: Más salidas que entradas!";
}
cout << endl;
}
}
Luis Hernández Yáñez
Fundamentos de la programación: Tipos e instrucciones II (Anexo II) Página 408
if (!error) {
cin >> c;
}
}
Fundamentos de la programación: Tipos e instrucciones II (Anexo II) Página 410
parentesis.cpp
if (error) {
cout << "Error: cierre sin apertura (pos. " << pos
<< ")";
}
else if (anidamiento > 0) {
cout << "Error: Apertura sin cierre";
}
else {
cout << "Correcto";
}
cout << endl;
Luis Hernández Yáñez
bool iguales() {
bool sonIguales = true;
double d1, d2;
ifstream sec1, sec2;
bool final = false;
sec1.open("secuencia1.txt");
sec2.open("secuencia2.txt");
sec1 >> d1;
sec2 >> d2; // Al menos estarán los centinelas (0)
while (sonIguales && !final) {
sonIguales = (d1 == d2);
final = ((d1 == 0) || (d2 == 0));
if (!final) {
sec1 >> d1;
sec2 >> d2;
}
} Cambia secuencia2.txt por secuencia3.txt
Luis Hernández Yáñez
primos.cpp
}
}
return 0;
}
Fundamentos de la programación: Tipos e instrucciones II (Anexo II) Página 413
bool primo(int n) {
bool esPrimo = true;
return esPrimo;
}
Luis Hernández Yáñez
primos2.cpp
Mejoras: probar sólo impares; sólo pueden ser divisibles por impares;
no pueden ser divisibles por ninguno mayor que su mitad
candidato = 2;
cout << candidato << " "; // Mostrar el número primo 2
candidato++; // Seguimos con el 3, que es primo
while (candidato < num) {
cout << candidato << " "; // Mostrar número primo
candidato = candidato + 2; // Sólo probamos impares
while (!primo(candidato)) { // Siguiente número primo
candidato = candidato + 2;
}
} ...
bool primo(int n) {
bool esPrimo = true;
for (int i = 3; i <= n / 2; i = i + 2) {
Luis Hernández Yáñez
if (n % i == 0) {
esPrimo = false; // Es divisible por i
}
}...
Fundamentos de la programación: Tipos e instrucciones II (Anexo II) Página 415
primos3.cpp
int i = 3;
while ((i <= n / 2) && esPrimo) {
if (n % i == 0) {
esPrimo = false;
}
i = i + 2;
}
return esPrimo;
}
Luis Hernández Yáñez
int main() {
int num, linea;
cout << "Valor a localizar: ";
cin >> num;
linea = busca(num);
if (linea != ‐1) {
cout << "Encontrado (línea " << linea << ")" << endl;
}
else {
Luis Hernández Yáñez
cout << "No encontrado" << endl;
}
return 0;
}
}
archivo.close();
}
return linea;
}
Fundamentos de la programación: Tipos e instrucciones II (Anexo II) Página 419
Luis Hernández Yáñez
cout << "No encontrado";
}
cout << endl;
archivo.close();
Fundamentos de la programación: Tipos e instrucciones II (Anexo II) Página 421
Si el elemento está: procesamiento similar a secuencias desordenadas
archivo >> i;
num 9
?
(i != 0) false
&& (i < num)
i 9
5
?
2 true
cont++;
archivo >> i;
Luis Hernández Yáñez
No se procesa
2 5 9 15 16 24 41 73 78 82 123 153 159 ...
el resto
de la secuencia
archivo >> i;
num 10
?
(i != 0) false
&& (i < num)
i 5
2
9
?
15 true
cont++;
archivo >> i;
Luis Hernández Yáñez
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
4
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Diseño descendente: Tareas y subtareas 427
Subprogramas 434
Subprogramas y datos 441
Parámetros 446
Argumentos 451
Resultado de la función 467
Prototipos 473
Ejemplos completos 475
Funciones de operador 477
Diseño descendente (un ejemplo) 480
Precondiciones y postcondiciones 490
Luis Hernández Yáñez
Fundamentos de la programación: La abstracción procedimental
Luis Hernández Yáñez
Refinamientos sucesivos
Tareas que ha de realizar un programa:
Se pueden dividir en subtareas más sencillas
Subtareas:
También se pueden dividir en otras más sencillas...
Refinamientos sucesivos
Diseño en sucesivos pasos en los se amplía el detalle
Ejemplos:
Dibujar
Luis Hernández Yáñez
2. Dibujar 1. Dibujar
Misma tarea
3. Dibujar 2. Dibujar
2.1. Dibujar
3. Dibujar
1. Dibujar
2. Dibujar
2.1. Dibujar
4 tareas, pero dos de ellas son iguales
2.2. Dibujar Nos basta con saber cómo dibujar:
3. Dibujar
Luis Hernández Yáñez
void dibujarSecantes()
Dibujar
{ ... }
void dibujarLinea()
{ ... }
Dibujar Dibujar Dibujar
void dibujarTriangulo()
{
dibujarSecantes();
dibujarLinea();
Dibujar Dibujar }
int main() {
dibujarCirculo();
Luis Hernández Yáñez
dibujarTriangulo();
dibujarSecantes();
return 0;
}
Mostrar HOLA MAMA
H O L A M A
Tareas básicas
Luis Hernández Yáñez
H O L A Espacio en blanco M
{ ... }
return 0;
void mostrarA() }
{ ...}
Flujo de ejecución
int main()
{
mostrarH();
mostrarO();
...
}
void mostrarH()
{
}
...
void mostrarO()
Luis Hernández Yáñez
{
}
...
...
Tipos de subprogramas
Procedimientos (acciones):
NO devuelven ningún resultado de su ejecución con return
Tipo: void
Llamada: instrucción independiente
mostrarH();
Funciones:
SÍ devuelven un resultado con la instrucción return
Tipo distinto de void
Llamada: dentro de cualquier expresión
x = 12 * y + cuadrado(20) ‐ 3;
Luis Hernández Yáñez
Procedimientos
Subprogramas de tipo void
...
void menu() int main()
{
{
int op;
cout << "1 – Editar" << endl; ...
cout << "2 – Combinar" << endl; menu();
cout << "0 – Cancelar" << endl; ...
cout << "Opción: ";
cin >> op;
if (op == 1) {
editar();
}
Luis Hernández Yáñez
else if (op == 2) {
combinar();
}
}
#include <iostream>
using namespace std;
int main() {
int op;
Datos locales a main()
Luis Hernández Yáñez
...
return 0; Se conocen MAX (global), op (local)
} e ingresos (global)
Excepciones:
Constantes globales (valores inalterables)
Luis Hernández Yáñez
Datos de entrada/salida:
Subprograma
Aceptados y modificados
Luis Hernández Yáñez
Declaración de parámetros
Sólo dos clases de parámetros en C++:
— Sólo de entrada (por valor)
&
De salida
Luis Hernández Yáñez
&
Misma identidad que la variable pasada como argumento
void incrementa(int &x)
void intercambia(double &x, double &y)
void proc(char &c, int &x, double &a, bool &b)
Reciben las variables en la llamada del subprograma: ¡Variables!
Los argumentos pueden quedar modificados
¡No usaremos parámetros por valor en las funciones!
Sólo en procedimientos
Puede haber tanto por valor como por referencia
nombre(argumentos)
— Tantos argumentos como parámetros y en el mismo orden
— Concordancia de tipos argumento‐parámetro
— Por valor: Expresiones válidas (se pasa el resultado)
— Por referencia: ¡Sólo variables!
double d = 3;
proc(12, d);
double d = 3;
int i = 124;
proc(i, 33 * d);
double d = 3;
int i = 124;
proc(cuad(20) * 34 + i, i * d);
Luis Hernández Yáñez
{ ... } i 124
d 3.0
int main() ...
{
int i = 124;
...
double d = 3; x 124
proc(i, 33 * d); a 99.0
... ...
return 0;
Luis Hernández Yáñez
return 0;
Luis Hernández Yáñez
int main() {
int cociente, resto;
for (int j = 1; j <= 4; j++) {
for (int i = 1; i <= 4; i++) {
divide(i, j, cociente, resto);
cout << i << " entre " << j << " da un cociente de "
<< cociente << " y un resto de " << resto << endl;
}
}
Luis Hernández Yáñez
return 0;
}
...
void divide(int op1, int op2, int &div, int &rem) {
// Divide op1 entre op2 y devuelve el cociente y el resto
div = op1 / op2;
rem = op1 % op2; Memoria
} cociente ?
resto ?
int main() {
int cociente, resto; i 1
for (int j = 1; j <= 4; j++) { j 1
for (int i = 1; i <= 4; i++) { ...
divide(i, j, cociente, resto);
...
}
}
Luis Hernández Yáñez
return 0;
}
return 0; ...
}
...
void divide(int op1, int op2, int &div, int &rem) {
// Divide op1 entre op2 y devuelve el cociente y el resto
div = op1 / op2;
rem = op1 % op2; Memoria
} div cociente 1
rem resto 0
int main() {
int cociente, resto; i 1
for (int j = 1; j <= 4; j++) { j 1
for (int i = 1; i <= 4; i++) { ...
divide(i, j, cociente, resto);
...
} op1 1
}
op2 1
Luis Hernández Yáñez
return 0; ...
}
return 0;
}
...
void intercambia(double &valor1, double &valor2) {
// Intercambia los valores
double tmp; // Variable local (temporal)
tmp = valor1; Memoria temporal
valor1 = valor2; del procedimiento
valor2 = tmp; tmp ?
}
...
int main() {
double num1, num2;
cout << "Valor 1: "; Memoria de main()
cin >> num1; valor1 num1 13.6
cout << "Valor 2: ";
valor2 num2 317.14
cin >> num2;
intercambia(num1, num2); ...
Luis Hernández Yáñez
cout << "Ahora el valor 1 es " << num1
<< " y el valor 2 es " << num2 << endl;
return 0;
}
int main() {
double precio, pago;
int euros, cent50, cent20, cent10, cent5, cent2, cent1;
cout << "Precio: ";
cin >> precio;
cout << "Pago: ";
cin >> pago;
cambio(precio, pago, euros, cent50, cent20, cent10, cent5, cent2,
cent1);
cout << "Cambio: " << euros << " euros, " << cent50 << " x 50c., "
<< cent20 << " x 20c., " << cent10 << " x 10c., "
<< cent5 << " x 5c., " << cent2 << " x 2c. y "
Luis Hernández Yáñez
<< cent1 << " x 1c." << endl;
return 0;
}
cent2 = cantidad / 2;
cent1 = cantidad % 2;
}
}
error = true;
}
else {
error = false;
...
Fundamentos de la programación: La abstracción procedimental Página 465
cambio.cpp
if (error) {
cout << "Error: El pago es inferior al precio" << endl;
}
else {
...
Fundamentos de la programación: La abstracción procedimental Página 466
Luis Hernández Yáñez
no se ejecutará nunca }
Factorial (N) = 1 x 2 x 3 x ... x (N‐2) x (N‐1) x N
long long int factorial(int n); // Prototipo
int main() {
int num;
cout << "Num: ";
cin >> num;
cout << "Factorial de " << num << ": " << factorial(num) << endl;
return 0;
}
}
else if (val1 < val2) {
return ‐1; ¡3 puntos de salida!
}
else {
return 1;
}
}
Luis Hernández Yáñez
if (val1 == val2) {
resultado = 0;
}
else if (val1 < val2) {
resultado = ‐1;
}
else {
resultado = 1;
}
#include <iostream>
using namespace std;
void intercambia(double &valor1, double &valor2); // Prototipo
int main() {
double num1, num2;
cout << "Valor 1: "; Asegúrate de que los prototipos
cin >> num1; coincidan con las implementaciones
cout << "Valor 2: ";
cin >> num2;
intercambia(num1, num2);
cout << "Ahora el valor 1 es " << num1
<< " y el valor 2 es " << num2 << endl;
return 0;
}
void intercambia(double &valor1, double &valor2) {
Luis Hernández Yáñez
double tmp; // Variable local (temporal)
tmp = valor1;
valor1 = valor2;
valor2 = tmp;
}
mates.cpp
// Prototipos if (n < 0) {
long long int factorial(int n); fact = 0;
int sumatorio(int n); }
else {
int main() { for (int i = 1; i <= n; i++) {
int num; fact = fact * i;
cout << "Num: "; }
cin >> num; }
cout << "Factorial de "
<< num << ": " return fact;
<< factorial(num) }
<< endl
<< "Sumatorio de 1 a " int sumatorio(int n) {
<< num << ": " int sum = 0;
<< sumatorio(num)
<< endl; for (int i = 1; i <= n; i++) {
Luis Hernández Yáñez
Paso 1.‐
Desarrollar un programa que haga operaciones de conversión
de medidas hasta que el usuario decida que no quiere hacer más
Pulgadas a centímetros
Libras a gramos
Luis Hernández Yáñez
Paso 2.‐
Desarrollar un programa que muestre al usuario un menú con
cuatro operaciones de conversión de medidas:
Pulgadas a centímetros
Libras a gramos
Grados Fahrenheit a centígrados
Galones a litros
Y lea la elección del usuario y proceda con la conversión, hasta que
el usuario decida que no quiere hacer más
6 grandes tareas:
Luis Hernández Yáñez
Conversiones
Paso 3.‐
Menú:
Mostrar las cuatro opciones más una para salir
Validar la entrada y devolver la elegida
Pulgadas a centímetros:
Devolver el equivalente en centímetros del valor en pulgadas
Libras a gramos:
Devolver el equivalente en gramos del valor en libras
Grados Fahrenheit a centígrados:
Devolver el equivalente en centígrados del valor en Fahrenheit
Galones a litros:
Devolver el equivalente en litros del valor en galones
Luis Hernández Yáñez
int main() {
double valor;
int op = ‐1;
while (op != 0) {
op = menu();
switch (op) {
case 1:
{
Luis Hernández Yáñez
cout << "Pulgadas: ";
cin >> valor;
cout << "Son " << pulgACm(valor) << " cm." << endl;
}
. . .
break;
Fundamentos de la programación: La abstracción procedimental Página 486
case 2:
{
cout << "Libras: ";
cin >> valor;
cout << "Son " << lbAGr(valor) << " gr." << endl;
}
break;
case 3:
{
cout << "Grados Fahrenheit: ";
cin >> valor;
cout << "Son " << grFAGrC(valor) << " ºC" << endl;
}
break;
case 4:
{
cout << "Galones: ";
cin >> valor;
cout << "Son " << galALtr(valor) << " l." << endl;
}
Luis Hernández Yáñez
break;
}
}
return 0;
} . . .
Fundamentos de la programación: La abstracción procedimental Página 487
int menu() {
int op = ‐1;
return op;
}
Luis Hernández Yáñez
. . .
Fundamentos de la programación: La abstracción procedimental Página 489
Luis Hernández Yáñez
Aserciones:
Condiciones que si no se cumplen interrumpen la ejecución
Luis Hernández Yáñez
Función assert()
Precondiciones
Por ejemplo, no realizaremos conversiones de valores negativos:
double pulgACm(double pulg) {
assert(pulg > 0);
}
else { // Se cumple la precondición...
...
Postcondiciones
Un subprograma puede garantizar condiciones al terminar:
int menu() {
int op = ‐1;
while ((op < 0) || (op > 4)) {
...
cout << "Elige: ";
cin >> op;
if ((op < 0) || (op > 4)) {
cout << "Opción no válida" << endl;
}
}
assert ((op >= 0) && (op <= 4));
Luis Hernández Yáñez
return op;
}
El subprograma debe asegurarse de que se cumpla
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
4A
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Archivos como parámetros 498
La función main() 501
Argumentos implícitos 504
Sobrecarga de subprogramas 508
Luis Hernández Yáñez
Fundamentos de la programación: La abstracción procedimental (Anexo)
Luis Hernández Yáñez
#include <iostream>
using namespace std;
#include <fstream>
void sumatorio_archivo(ifstream &arch, double &suma);
int main() {
double resultado;
ifstream archivo;
archivo.open("datos.txt");
if (!archivo.is_open()) {
cout << "ERROR DE APERTURA" << endl;
}
else {
sumatorio_archivo(archivo, resultado)
cout << "Suma = " << resultado << endl;
archivo.close();
Luis Hernández Yáñez
return 0;
}
suma = 0;
arch >> dato;
Parámetros de main():
— argc: número de argumentos que se proporcionan
Una vez asignado un valor implícito, todos los que siguen
han de tener también valor implícito
Fundamentos de la programación: La abstracción procedimental (Anexo) Página 505
Parámetros y argumentos implícitos
void p(int i, int j = 2, int k = 3);
Se copian los argumentos en los parámetros del primero al último
los que no tengan correspondencia tomarán los implícitos
void p(int i, int j = 2, int k = 3);
...
p(13); // i toma 13, j y k sus valores implícitos
p(5, 7); // i toma 5, j toma 7 y k su valor implícito
p(3, 9, 12); // i toma 3, j toma 9 y k toma 12
Luis Hernández Yáñez
#include <iostream>
using namespace std;
int main() {
double x, y;
cout << "X = "; No podemos dejar signo por defecto
cin >> x; y concretar delta
cout << "Y = ";
cin >> y;
cout << "signo y delta por defecto: " << f(x, y) << endl;
cout << "signo ‐1 y delta por defecto: " << f(x, y, ‐1) << endl;
cout << "signo y delta concretos: " << f(x, y, 1, 1.25) << endl;
return 0;
}
Luis Hernández Yáñez
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
5
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Tipos de datos 514
Arrays de nuevo 517
Arrays y bucles for 520
Más sobre arrays 522
Inicialización de arrays 523
Enumerados como índices 524
Paso de arrays a subprogramas 525
Implementación de listas 528
Cadenas de caracteres 531
Cadenas de caracteres de tipo string 535
Entrada/salida con string 539
Luis Hernández Yáñez/Pablo Moreno Ger
Operaciones con string 541
Estructuras 543
Estructuras dentro de estructuras 549
Arrays de estructuras 550
Arrays dentro de estructuras 551
Listas de longitud variable 552
Un ejemplo completo 558
El bucle do..while 562
Fundamentos de la programación: Tipos de datos estructurados
Luis Hernández Yáñez/Pablo Moreno Ger
Clasificación de tipos
Simples
Estándar: int, float, double, char, bool
Conjunto de valores predeterminado
Definidos por el usuario: enumerados
Conjunto de valores definido por el programador
Estructurados
Luis Hernández Yáñez/Pablo Moreno Ger
Acceso directo []
A cada elemento se accede a través de su índice:
ventas[4] accede al 5º elemento (contiene el valor 435.00)
cout << ventas[4];
ventas[4] = 442.75; Datos de un mismo tipo base:
Se usan como cualquier variable
tVentas ventas;
¡NO se inicializan los elementos automáticamente!
¡Es responsabilidad del programador usar índices válidos!
No se pueden copiar arrays directamente (array1 = array2)
Hay que copiarlos elemento a elemento
double media, total = 0;
... typedef double tVentas[Dias];
for (int i = 0; i < Dias; i++) {
total = total + ventas[i];
}
media = total / Dias;
tVentas ventas;
Memoria
double media, total = 0;
Dias 7
...
ventas[0] 12.40
for (int i = 0; i < Dias; i++) {
ventas[1] 10.96
total = total + ventas[i];
} ventas[2] 8.43
ventas[3] 11.65
i = 0 ventas[4] 13.70
Luis Hernández Yáñez/Pablo Moreno Ger
ventas[5] 13.41
true false ventas[6] 14.07
i<Dias
media ?
... total 84.62
23.36
31.79
12.40
0.00
43.44
total+=ventas[i]
i 3
2
70
4
1
i++
1º 2º 3º 4º 5º ... 10º
cout << "Cantidad de azul (0‐255): ";
cin >> color[azul];
inicializa(array);
Si inicializa() modifica algún elemento de tabla,
automáticamente queda modificado ese elemento de array
inicializa(array); // array queda modificado
for (int i = 0; i < Dim; i++)
cout << array[i] << " ";
...
0 1 2 3 4 5 6 7 8 9
Recorrido de la lista:
for (int i = 0; i < NUM; i++) {
Luis Hernández Yáñez/Pablo Moreno Ger
...
Búsqueda en la lista:
while ((i < NUM) && !encontrado) {
...
...
Búsqueda en la lista:
while ((i < contador) && !encontrado) {
...
H o l a
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Longitud actual: 4
Longitud de la cadena
A d i ó s
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Longitud: 5
S u p e r c a l i f r a g i l í s t i c o
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Longitud: 21
Luis Hernández Yáñez/Pablo Moreno Ger
Tipo string
Cadenas más sofisticadas
Sin longitud máxima (gestión automática de la memoria)
Multitud de funciones de utilidad (biblioteca string)
string.cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string cad1("Hola"); // inicialización
string cad2 = "amigo"; // inicialización
string cad3;
cad3 = cad1; // copia
cout << "cad3 = " << cad3 << endl;
cad3 = cad1 + " "; // concatenación
Luis Hernández Yáñez/Pablo Moreno Ger
cad3 += cad2; // concatenación
cout << "cad3 = " << cad3 << endl;
cad1.swap(cad2); // intercambio
cout << "cad1 = " << cad1 << endl;
cout << "cad2 = " << cad2 << endl;
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main() {
string nombre, apellidos;
cout << "Introduzca un nombre: ";
cin >> nombre;
cout << "Introduzca los apellidos: ";
cin.sync();
getline(cin, apellidos);
Luis Hernández Yáñez/Pablo Moreno Ger
cout << "Nombre completo: " << nombre << " "
<< apellidos << endl;
return 0;
}
cadena.substr(posición, longitud)
Subcadena de longitud caracteres desde posición
string cad = "abcdefg";
cout << cad.substr(2, 3); // Muestra cde
cadena.find(subcadena)
Posición de la primera ocurrencia de subcadena en cadena
string cad = "Olala";
cout << cad.find("la"); // Muestra 1
Luis Hernández Yáñez/Pablo Moreno Ger
http://www.cplusplus.com/reference/string/string/
typedef struct {
... // declaraciones de campos (como variables)
} tTipo; // nombre de tipo ‐ ¡al final!
typedef struct {
string nombre;
string apellidos;
int edad;
string nif;
} tPersona;
Luis Hernández Yáñez/Pablo Moreno Ger
Campos:
Tipos estándar o previamente declarado
typedef struct {
string nombre;
string apellidos; Memoria
int edad;
string nif; Luis
} tPersona; persona.nombre
Antonio
tPersona persona;
persona
Hernández
persona.apellidos
Yáñez
nombre Luis Antonio
Luis Hernández Yáñez/Pablo Moreno Ger
persona.edad 22
apellidos Hernández Yáñez
persona.nif 00223344F
edad 22
nif 00223344F
typedef struct { typedef struct {
string dni; ...
char letra; tNif nif;
} tNif; } tPersona;
nif
Acceso a la letra del NIF: dni
letra
persona.nif.letra
Acceso al DNI:
persona.nif.dni
} tPersona; 2
nombre
apellidos
edad
typedef tPersona tArray[MAX]; nif
typedef struct {
tArray elementos;
Luis Hernández Yáñez/Pablo Moreno Ger
tLista lista;
Nombre de la tercera persona: lista.elementos[2].nombre
Edad de la duodécima persona: lista.elementos[11].edad
NIF de la primera persona: lista.elementos[0].nif
Fundamentos de la programación: Tipos de datos estructurados Página 551
/ Pablo Moreno Ger
Luis Hernández Yáñez/Pablo Moreno Ger
elementos
Luis Hernández Yáñez/Pablo Moreno Ger
contador 6
42.0
12.0 ‐2.2 5.4 0.0 36.2 35.0 X X X X
nuevo
0 1 2 3 4 5 6 7 8 9
3 6
pos
Operación en 3 pasos:
1.‐ Abrir hueco para el nuevo elemento (desde la posición)
2.‐ Colocar el elemento nuevo en la posición
3.‐ Incrementar el contador
if (lista.contador < N) {
// Abrir hueco
for (int i = lista.contador; i > pos; i‐‐) {
lista.elementos[i] = lista.elementos[i ‐ 1];
}
// Insertar e incrementar contador
lista.elementos[pos] = nuevoElemento;
lista.contador++;
}
Luis Hernández Yáñez/Pablo Moreno Ger
42.0
12.0 ‐2.2 5.4 42.0 0.0 36.2 35.0 X X X
nuevo
0 1 2 3 4 5 6 7 8 9
3 7
pos
Descripción
Programa que mantenga una lista de los estudiantes de una clase
De cada estudiante: nombre, apellidos, edad, NIF y nota
Se desconoce el número total de estudiantes (máximo 100)
La información de la lista se mantiene en un archivo clase.txt
Se carga al empezar y se guarda al finalizar
El programa debe ofrecer estas opciones:
Luis Hernández Yáñez/Pablo Moreno Ger
#include <iostream>
#include <string>
using namespace std;
#include <fstream>
#include <iomanip>
// Prototipos
int menu(); // Menú del programa ‐ devuelve la opción elegida
void cargar(tLista &lista, bool &ok); // Carga del archivo
void guardar(const tLista &lista); // La guarda en el archivo
void leerEstudiante(tEstudiante &estudiante); // Lee los datos
void insertarEstudiante(tLista &lista, tEstudiante estudiante,
bool &ok); // Inserta un nuevo estudiante en la lista
void eliminarEstudiante(tLista &lista, int pos, bool &ok);
// Elimina el estudiante en esa posición
string nombreCompleto(tEstudiante estudiante);
void calificar(tLista &lista); // Notas de los estudiantes
Luis Hernández Yáñez/Pablo Moreno Ger
El bucle do..while
do cuerpo while (condición); Condición al final del bucle
int i = 1;
do {
cout << i << endl;
Luis Hernández Yáñez/Pablo Moreno Ger
i++;
} while (i <= 100);
i = 1;
El cuerpo
Luis Hernández Yáñez/Pablo Moreno Ger
cout << i << endl;
se ejecuta
i++;
al menos
true una vez
i <= 100
false
cout << "Opción: "; do { // Más simple
cin >> op; // Lectura del 1º cout << "Opción: ";
while ((op < 0) || (op > 4)) { cin >> op;
cout << "Opción: "; } while ((op < 0) || (op > 4));
cin >> op;
}
do {
cout << "1 ‐ Añadir un nuevo estudiante" << endl;
cout << "2 ‐ Eliminar un estudiante" << endl;
cout << "3 ‐ Calificar a los estudiantes" << endl;
cout << "4 ‐ Listado de estudiantes" << endl;
cout << "0 ‐ Salir" << endl;
cout << "Opción: ";
cin >> op;
Luis Hernández Yáñez/Pablo Moreno Ger
return op;
}
El archivo clase.txt
Un dato en cada línea ↲
↲
↲
Por cada estudiante: ↲
↲
↲
Nombre (cadena) ↲
↲
↲
Apellidos (cadena) ↲
↲
↲
Edad (entero) ↲
↲
↲
NIF (cadena) ↲
↲
Luis Hernández Yáñez/Pablo Moreno Ger
↲
Nota (real; ‐1 si no calificado) ↲
↲
Termina con XXX como nombre ↲
↲
↲
↲
↲
archivo >> estudiante.nif;
archivo >> estudiante.nota;
archivo.get(aux); // Saltamos el Intro
lista.elementos[lista.contador] = estudiante; // Al final
lista.contador++;
getline(archivo, estudiante.nombre); // Siguiente nombre
} // Si hay más de MAX estudiantes, ignoramos el resto
archivo.close();
}
}
Fundamentos de la programación: Tipos de datos estructurados Página 569
Simplemente, un dato en cada línea y en orden:
void guardar(const tLista &lista) {
ofstream archivo;
archivo.open("clase.txt");
for (int i = 0; i < lista.contador; i++) {
archivo << lista.elementos[i].nombre << endl;
archivo << lista.elementos[i].apellidos << endl;
archivo << lista.elementos[i].edad << endl;
archivo << lista.elementos[i].nif << endl;
archivo << lista.elementos[i].nota << endl;
Luis Hernández Yáñez/Pablo Moreno Ger
}
archivo << "XXX" << endl; // Centinela final
archivo.close();
}
void leerEstudiante(tEstudiante &estudiante) {
cin.sync(); // Descartamos cualquier entrada pendiente
cout << "Nombre: ";
getline(cin, estudiante.nombre);
cout << "Apellidos: ";
getline(cin, estudiante.apellidos);
cout << "Edad: ";
cin >> estudiante.edad;
cout << "NIF: ";
cin >> estudiante.nif;
estudiante.nota = ‐1; // Sin calificar de momento
Luis Hernández Yáñez/Pablo Moreno Ger
cin.sync(); // Descartamos cualquier entrada pendiente
}
ok = true;
if (lista.contador == MAX) {
ok = false;
}
else {
lista.elementos[lista.contador] = estudiante;
// Insertamos al final
lista.contador++;
Luis Hernández Yáñez/Pablo Moreno Ger
}
}
void eliminarEstudiante(tLista &lista, int pos, bool &ok) {
// Espera el índice del elemento en pos
if ((pos < 0) || (pos > lista.contador ‐ 1)) {
ok = false; // Elemento inexistente
}
else {
ok = true;
for (int i = pos; i < lista.contador ‐ 1; i++) {
lista.elementos[i] = lista.elementos[i + 1];
}
Luis Hernández Yáñez/Pablo Moreno Ger
lista.contador‐‐;
}
}
void calificar(tLista &lista) {
for (int i = 0; i < lista.contador; i++) {
cout << "Nota del estudiante "
<< nombreCompleto(lista.elementos[i]) << ": ";
cin >> lista.elementos[i].nota;
}
Luis Hernández Yáñez/Pablo Moreno Ger
for (int i = 0; i < lista.contador; i++) {
if (lista.elementos[i].nota > max) {
max = lista.elementos[i].nota;
pos = i;
}
}
return pos;
}
if (i == mayor) {
cout << " <<< Mayor nota!";
}
cout << endl;
}
cout << "Media de la clase: " << fixed << setprecision(1)
<< media << endl << endl;
}
int main() {
tLista lista;
tEstudiante estudiante;
bool exito;
int op, pos;
cargar(lista, exito);
if (!exito) {
cout << "No se ha podido cargar la lista!" << endl;
}
else {
do { // El bucle do evita tener que leer antes la primera opción
op = menu();
Luis Hernández Yáñez/Pablo Moreno Ger
switch (op) {
case 1:
{
leerEstudiante(estudiante);
insertarEstudiante(lista, estudiante, exito);
if (!exito) {
cout << "Lista llena: imposible insertar" << endl;
}
}
break;
case 4:
{
listado(lista, mediaClase(lista), mayorNota(lista));
}
}
} while (op != 0);
guardar(lista);
}
return 0;
}
Fundamentos de la programación: Tipos de datos estructurados Página 578
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
Luis Hernández Yáñez/Pablo Moreno Ger
5A
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Cadenas al estilo de C 582
E/S con cadenas al estilo de C 583
La biblioteca cstring 584
Ejemplo 585
Luis Hernández Yáñez/Pablo Moreno Ger
Fundamentos de la programación: Cadenas al estilo de C (Anexo)
Arrays de caracteres terminados en nulo
const Max = 15;
typedef char tCadena[Max];
tCadena cadena = "Adiós"; // Inicialización al declarar
Siempre hay al final un carácter nulo (código ASCII 0 – '\0')
Indica que en esa posición termina la cadena (exclusive)
cadena A d i ó s \0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
Luis Hernández Yáñez/Pablo Moreno Ger
tCadena cadena;
cin >> cadena; // Se añade un nulo al final
Extractor: la lectura termina en el primer espacio en blanco
¡No se comprueba si se leen más caracteres de los que caben!
setw(): máximo de caracteres a colocar (incluyendo el nulo)
cin >> setw(15) >> cadena;
cin.getline(cadena_estilo_C, máx):
Para leer también los espacios en blanco y no más de máx‐1
Luis Hernández Yáñez/Pablo Moreno Ger
cin.getline(cadena, 15); // Hasta 14 caracteres
cout << cadena << endl; // El nulo no se muestra
cadenas.cpp
#include <iostream>
using namespace std;
#include <cstring>
int main() {
const int MAX = 20;
typedef char tCad[MAX];
tCad cadena = "Me gusta C++";
cout << cadena << endl;
cout << "Cadena: ";
cin >> cadena; // Lee hasta el primer espacio en blanco
Luis Hernández Yáñez/Pablo Moreno Ger
cout << cadena << endl;
cin.sync(); // Sincronizar la entrada
cout << "Cadena: ";
cin.getline(cadena, MAX);
cout << cadena << endl;
cout << "Longitud: " << strlen(cadena) << endl;
strcpy(cadena, "Hola");
...
}
cout << endl;
return 0;
}
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
Luis Hernández Yáñez/Pablo Moreno Ger
6
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Recorrido de arrays 590
Arrays completos 593
Arrays no completos con centinela 594
Arrays no completos con contador 595
Ejemplos 597
Generación de números aleatorios 601
Búsquedas en arrays 604
Arrays completos 606
Arrays no completos con centinela 607
Arrays no completos con contador 608
Ejemplo 610
Recorridos y búsquedas en cadenas 614
Más ejemplos de manejo de arrays 617
Arrays multidimensionales 630
Inicialización de arrays multidimensionales 638
Luis Hernández Yáñez
Recorrido de un array bidimensional 641
Recorrido de un array N‐dimensional 644
Búsqueda en un array multidimensional 647
Fundamentos de la programación: Recorrido y búsqueda en arrays
Luis Hernández Yáñez
Esquema de recorrido
Inicialización Inicialización
Procesar elemento
Luis Hernández Yáñez
Finalización
double elemento;
for (int i = 0; i < N; i++) {
elemento = ventas[i];
Luis Hernández Yáñez
// Procesar el elemento ...
}
int i = 0;
int i = 0; double elemento;
double elemento = datos[i]; do {
while (elemento != ‐1) { elemento = datos[i];
Luis Hernández Yáñez
// Procesar el elemento ... if (elemento != ‐1) {
// Procesar el elemento...
i++; i++;
elemento = datos[i]; }
} } while (elemento != ‐1);
contador 7
0 1 2 3 4 5 6 7 99
numDig 0 0 0 0 0 0
0 1 2 3 4 5
...
numeros[0] = rand(); // Entre 0 y 32766
int main() {
const int NUM = 100;
typedef int tNum[NUM]; // Exactamente 100 números
const int DIG = 5;
typedef int tDig[DIG];
tNum numeros;
tDig numDig = { 0 }; // Inicializa todo el array a 0
Luis Hernández Yáñez
srand(time(NULL)); // Inicia la secuencia aleatoria
...
Esquema de búsqueda
Inicialización / encontrado = false;
Inicialización
Mientras no se encuentre el elemento
true
y no se esté al final de la secuencia: ¿Al final o
encontrado?
Obtener el siguiente elemento false
Comprobar si el elemento
Obtener elemento
satisface la condición
Finalización ¿Encontrado?
(tratar el elemento encontrado
o indicar que no se ha encontrado)
Luis Hernández Yáñez
Finalización
}
if (encontrado) // ...
Con centinela
const int N = 10;
typedef int tArray[N];
int buscado; tArray array;
cout << "Valor a buscar: "; const int centinela = ‐1;
cin >> buscado;
int pos = 0;
bool encontrado = false;
while ((array[pos] != centinela) && !encontrado) {
if (array[pos] == buscado) {
encontrado = true;
}
else {
pos++;
}
}
Luis Hernández Yáñez
if (encontrado) // ...
}
}
if (encontrado) // ...
anual[2].ventas[3][0]
#include <iostream> umbral.cpp
using namespace std;
#include <fstream>
const int N = 100;
typedef double tArray[N];
typedef struct {
tArray elementos;
int contador;
} tLista;
int main() {
tLista lista;
bool ok;
Luis Hernández Yáñez
cargar(lista, ok);
if (!ok) {
cout << "Error: no hay archivo o demasiados datos"
<< endl;
}
Fundamentos de la programación: Recorrido y búsqueda en arrays Página 611
else {
double umbral;
cout << "Valor umbral: "; cin >> umbral;
bool encontrado = false;
int pos = 0;
while ((pos < lista.contador) && !encontrado) {
if (lista.elementos[pos] > umbral) {
encontrado = true;
}
else {
pos++;
}
}
if (encontrado) {
cout << "Valor en pos. " << pos + 1 << " ("
<< lista.elementos[pos] << ")" << endl;
}
else {
Luis Hernández Yáñez
cout << "¡No encontrado!" << endl;
}
}
return 0;
}
Fundamentos de la programación: Recorrido y búsqueda en arrays Página 612
}
archivo.close();
}
ok = abierto && !overflow;
}
Fundamentos de la programación: Recorrido y búsqueda en arrays Página 613
Luis Hernández Yáñez
inversa.cpp
inversa = car + inversa; // Inserta car al principio
pos++;
} // ...
pos++;
}
}
if (encontrado) // ...
vectores.cpp
return suma;
}
i++;
}
return !encontrado;
}
Fundamentos de la programación: Recorrido y búsqueda en arrays Página 620
}
return i ‐ 1;
}
while ((i < N) && !encontrado) {
j = i + 1;
while ((j < N) && !encontrado) {
encontrado = (v[i] == v[j]);
j++;
}
i++;
}
return encontrado;
}
Luis Hernández Yáñez
#include <iostream>
using namespace std;
int main() {
tVector1 v1 = { 'a', 'b', 'c' };
tVector2 v2 = { 'a', 'r', 'e', 't', 'z', 's', 'a', 'h', 'b', 'x' };
bool ok = vectorIncluido(v1, v2);
if (ok) {
cout << "OK: v1 esta incluido en v2" << endl;
}
Luis Hernández Yáñez
else {
cout << "NO: v1 no esta incluido en v2" << endl;
}
return 0;
}
return encontrado;
}
while (encontrado && (i < N ‐ 1)) {
i++;
Luis Hernández Yáñez
encontrado = esta(v1[i], v2);
}
return encontrado;
}
anagramas.cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string cad1, cad2;
bool sonAnagramas = true;
int numCar, posEnCad2;
cout << "Introduce la primera cadena: ";
getline(cin, cad1);
cout << "Introduce la segunda cadena: ";
getline(cin, cad2);
if (cad1.length() != cad2.length()) { // No son anagramas
sonAnagramas = false;
}
Luis Hernández Yáñez
else {
numCar = 0; // Contador de caracteres de la primera cadena
while (sonAnagramas && (numCar < cad1.length())) {
posEnCad2 = buscaCaracter(cad2, cad1.at(numCar));
if (sonAnagramas) {
cout << "Las palabras introducidas son anagramas" << endl;
}
else {
cout << "Las palabras introducidas NO son anagramas" << endl;
}
Luis Hernández Yáñez
return 0;
}
while ((pos < lon) && !encontrado) {
if (cad.at(pos) == c) {
encontrado = true;
}
else {
pos++;
}
}
if (!encontrado) {
pos = ‐1;
}
return pos;
Luis Hernández Yáñez
0 1 2 3 ... 98 99
0 ...
1 ...
2 ...
... ... ... ... ... ... ... ...
Luis Hernández Yáñez
48 ...
49 ...
temp.cpp
int main() {
const int MaxDias = 31;
const int MED = 2; // Nº de medidas
typedef double tTemp[MaxDias][MED]; // Día x mín./máx.
tTemp temp;
double tMaxMedia = 0, tMinMedia = 0,
tMaxAbs = ‐100, tMinAbs = 100;
int dia = 0;
double max, min;
ifstream archivo;
archivo.open("temp.txt");
if (!archivo.is_open()) {
cout << "No se ha podido abrir el archivo!" << endl;
}
Luis Hernández Yáñez
else {
archivo >> min >> max;
// El archivo termina con ‐99 ‐99
...
tMaxAbs = temp[i][1];
}
}
...
return 0;
}
Luis Hernández Yáñez
Para cada valor del primer índice: todos los valores del segundo
Luis Hernández Yáñez
cuads[0][0] 1 0 1 1
1 2 4
cuads[0][1] 1
2 3 9
cuads[1][0] 2
3 4 16
cuads[1][1] 4
4 5 25
cuads[2][0] 3
cuads[2][1] 9 Si hay menos valores que elementos,
cuads[3][0] 4 el resto se inicializan a cero
cuads[3][1] 16 Inicialización a cero de todo el array:
Luis Hernández Yáñez
matriz[0][1][1][1] 11
matriz[0][1][1][2] 12
matriz[0][2][0][0] 0
... 0
const int FILAS = 10;
const int COLUMNAS = 5;
typedef double tMatriz[FILAS][COLUMNAS];
tMatriz matriz;
for (int mes = 0; mes < Meses; mes++) {
for (int dia = 0; dia < diasMes[mes]; dia++) {
cout << "Ventas del día " << dia + 1
Luis Hernández Yáñez
<< " del mes " << mes + 1 << ": ";
cin >> ventas[mes][dia];
}
}
Fundamentos de la programación: Recorrido y búsqueda en arrays Página 642
0 1 2 3 4 ... 28 29 30
0 201 125 234 112 156 ... 234 543 667
1 323 231 675 325 111 ...
2 523 417 327 333 324 ... 444 367 437
3 145 845 654 212 562 ... 354 548
4 327 652 555 222 777 ... 428 999 666
Celdas no
5 854 438 824 547 175 ... 321 356
Meses utilizadas
6 654 543 353 777 437 ... 765 678 555
7 327 541 164 563 327 ... 538 159 235
8 333 327 432 249 777 ... 528 529
Luis Hernández Yáñez
typedef double tMatriz[DIM1][DIM2][DIM3][DIM4];
tMatriz matriz;
Bucles anidados, desde la primera dimensión hasta la última:
for (int n1 = 0; n1 < DIM1; n1++) {
for (int n2 = 0; n2 < DIM2; n2++) {
for (int n3 = 0; n3 < DIM3; n3++) {
for (int n4 = 0; n4 < DIM4; n4++) {
// Procesar matriz[n1][n2][n3][n4]
}
Luis Hernández Yáñez
}
}
}
anual[i].ventas[j][k] double
const int MESES = 12;
typedef tMes tVentaAnual[MESES];
tVentaAnual anual;
double total = 0;
for (int mes = 0; mes < MESES; mes++) {
for (int dia = 0; dia < anual[mes].dias; dia++) {
for (int suc = 0; suc < SUCURSALES; suc++) {
total = total + anual[mes].ventas[dia][suc];
Luis Hernández Yáñez
}
}
}
if (!encontrado) {
mes++;
}
}
if (encontrado) { ...
Fundamentos de la programación: Recorrido y búsqueda en arrays Página 647
Licencia CC (Creative Commons)
Este tipo de licencias ofrecen algunos derechos a terceras personas
bajo ciertas condiciones.
Este documento tiene establecidas las siguientes:
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
7
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Algoritmos de ordenación 651
Algoritmo de ordenación por inserción 654
Ordenación de arrays por inserción 665
Algoritmo de ordenación por inserción
con intercambios 672
Claves de ordenación 680
Estabilidad de la ordenación 688
Complejidad y eficiencia 692
Ordenaciones naturales 694
Ordenación por selección directa 701
Método de la burbuja 716
Listas ordenadas 722
Búsquedas en listas ordenadas 729
Búsqueda binaria 731
Luis Hernández Yáñez
Fundamentos de la programación: Algoritmos de ordenación
Luis Hernández Yáñez
Ordenación de listas
array
125.40 76.95 328.80 254.62 435.00 164.29 316.05 219.99 93.45 756.62
0 1 2 3 4 5 6 7 8 9
Algoritmo de ordenación
(de menor a mayor)
array
76.95 93.45 125.40 164.29 219.99 254.62 316.05 328.80 435.00 756.62
0 1 2 3 4 5 6 7 8 9
array[i] <= array[i + 1]
Luis Hernández Yáñez
6
1 Baraja de nueve cartas numeradas del 1 al 9
3
8
2
9
Las cartas están desordenadas
4
7
Luis Hernández Yáñez
6
1 Colocamos el primer elemento en la lista vacía
3
8
2
9
4
7
5 Lista ordenada:
5
Luis Hernández Yáñez
6
1 El 7 es mayor que todos los elementos de la lista
3
8 Lo insertamos al final
2
9
4
7
Lista ordenada:
5 7
Luis Hernández Yáñez
6
1 Primer elemento (5) mayor que el nuevo (4):
3
8 Desplazamos todos una posición a la derecha
2
9
Insertamos el nuevo en la primera posición
Lista ordenada:
5 5
4 7 7
Luis Hernández Yáñez
6
1 9 es mayor que todos los elementos de la lista
3
8 Lo insertamos al final
2
9
Lista ordenada:
4 5 7 9
Luis Hernández Yáñez
6
1 Primer elemento (4) mayor que el nuevo (2):
3
8 Desplazamos todos una posición a la derecha
2 Insertamos el nuevo en la primera posición
Lista ordenada:
4 4
2 5 5
7 7
9 9
Luis Hernández Yáñez
6
1 El 9 es el primer elemento mayor que el nuevo (8):
3
8 Desplazamos desde ese hacia la derecha
Insertamos donde estaba el 9
Lista ordenada:
2 4 5 7 8
4 9 9
Luis Hernández Yáñez
6
1 Segundo elemento (4) mayor que el nuevo (3):
3 Desplazamos desde ese hacia la derecha
Insertamos donde estaba el 4
Lista ordenada:
2 3
4 4 4
5 5
7 7
8 8
9 9
Luis Hernández Yáñez
6
1 Primer elemento (2) mayor que el nuevo (1):
Desplazamos todos una posición a la derecha
Insertamos el nuevo en la primera posición
Lista ordenada:
2 2
1 3 3
4 4
5 5
7 7
8 8
9 9
Luis Hernández Yáñez
1 2 3 4 5 6
7 7
8 8
9 9
Luis Hernández Yáñez
7 14 20 32 5 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
20 7 14 32 5 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
Luis Hernández Yáñez
nuevo 7
Primer elemento mayor o igual: índice 0
20 7 14 32 5 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
nuevo 7
7 20 14 32 5 14 27 12 13 15
Luis Hernández Yáñez
0 1 2 3 4 5 6 7 8 9
nuevo 7
Implementación const int N = 15;
typedef int tLista[N];
... tLista lista;
int nuevo, pos;
// Desde el segundo elemento hasta el último...
for (int i = 1; i < N; i++) {
nuevo = lista[i];
pos = 0;
while ((pos < i) && !(lista[pos] > nuevo)) {
pos++;
}
// pos: índice del primer mayor; i si no lo hay
for (int j = i; j > pos; j‐‐) {
lista[j] = lista[j ‐ 1];
Luis Hernández Yáñez
}
lista[pos] = nuevo;
}
i 1 pos 0 nuevo 7
20 7 14 32 5 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
20 20 14 32 5 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
7 20 14 32 5 14 27 12 13 15
Luis Hernández Yáñez
0 1 2 3 4 5 6 7 8 9
7 14 20 32 5 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
i 4 pos 0 nuevo 5
7 14 20 32 5 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
7 7 14 20 32 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
5
Luis Hernández Yáñez
7 14 20 32 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
i 5 pos 3 nuevo 14
5 7 14 20 32 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
5 7 14 20 20 32 27 12 13 15
0 1 2 3 4 5 6 7 8 9
14 20
Luis Hernández Yáñez
5 7 14 32 27 12 13 15
0 1 2 3 4 5 6 7 8 9
5 7 14 20 32 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
5 7 14 20 14 32 27 12 13 15
0 1 2 3 4 5 6 7 8 9
Luis Hernández Yáñez
5 7 14 14 20 32 27 12 13 15
0 1 2 3 4 5 6 7 8 9
7 14 20 32 5 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
7 14 20 5 32 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
7 14 5 20 32 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
7 5 14 20 32 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
Luis Hernández Yáñez
5 7 14 20 32 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
}
}
#include <iostream> insercion.cpp
using namespace std;
#include <fstream>
int main() {
tLista lista;
ifstream archivo;
Luis Hernández Yáñez
int dato, pos, tmp;
lista.contador = 0;
...
cout << endl;
}
return 0;
}
Fundamentos de la programación: Algoritmos de ordenación Página 678
Consideración de implementación
¿Operador relacional adecuado?
lista[pos ‐ 1] ¿ > o >= ? lista[pos]
Con >= se realizan intercambios inútiles:
5 7 14 20 32 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
5 7 14 20 14 32 27 12 13 15
0 1 2 3 4 5 6 7 8 9
Luis Hernández Yáñez
5 7 14 14 20 32 27 12 13 15
0 1 2 3 4 5 6 7 8 9
¡Intercambio inútil!
Clave de ordenación:
Luis Hernández Yáñez
Claves de ordenación
tDato tmp;
while ((pos > 0)
&& (lista[pos ‐ 1].nombre > lista[pos].nombre)) {
tmp = lista[pos];
lista[pos] = lista[pos ‐ 1];
lista[pos ‐ 1] = tmp;
pos‐‐;
}
tDato tmp;
while ((pos > 0) && (lista[pos ‐ 1] > lista[pos])) {
tmp = lista[pos];
lista[pos] = lista[pos ‐ 1];
lista[pos ‐ 1] = tmp;
pos‐‐;
Luis Hernández Yáñez
claves.cpp
Claves de ordenación
#include <iostream>
#include <string>
using namespace std;
#include <fstream>
#include <iomanip>
const int N = 15;
typedef struct {
int codigo;
string nombre;
double sueldo;
} tDato;
typedef tDato tArray[N];
typedef struct {
tArray datos;
Luis Hernández Yáñez
int cont;
} tLista;
...
lista.cont++;
archivo >> dato.codigo;
}
archivo.close(); ...
Fundamentos de la programación: Algoritmos de ordenación Página 685
cout << "Antes de ordenar:" << endl;
mostrar(lista);
for (int i = 1; i < lista.cont; i++) {
// Desde el segundo elemento hasta el último
int pos = i;
while ((pos > 0)
&& (lista.datos[pos‐1] > lista.datos[pos])) {
tDato tmp;
tmp = lista.datos[pos];
lista.datos[pos] = lista.datos[pos ‐ 1];
lista.datos[pos ‐ 1] = tmp;
pos‐‐;
}
}
cout << "Después de ordenar:" << endl;
Luis Hernández Yáñez
mostrar(lista);
}
return 0;
} ...
Fundamentos de la programación: Algoritmos de ordenación Página 686
void mostrar(tLista lista) {
for (int i = 0; i < lista.cont; i++) {
cout << setw(10)
<< lista.datos[i].codigo
<< setw(20)
<< lista.datos[i].nombre
<< setw(12)
<< fixed
<< setprecision(2)
<< lista.datos[i].sueldo
<< endl;
}
}
10000 Sergei 100000
33333 Tarazona 120000
12345 Turégano 100000
11111 Urpiano 90000
10000 Sergei 100000 10000 Hernández 150000
10000 Hernández 150000 10000 Sergei 100000
11111 Urpiano 90000 11111 Benítez 100000
11111 Benítez 100000 11111 Durán 120000
11111 Pérez 90000 11111 Pérez 90000
11111 Durán 120000 11111 Urpiano 90000
12345 Sánchez 90000 12345 Álvarez 120000
12345 Álvarez 120000 12345 Gómez 100000
12345 Turégano 100000 12345 Sánchez 90000
12345 Gómez 100000 12345 Turégano 100000
21112 Domínguez 90000 21112 Domínguez 90000
21112 Jiménez 100000 21112 Jiménez 100000
22222 Fernández 120000 22222 Fernández 120000
33333 Tarazona 120000 33333 Tarazona 120000
No estable: Estable:
Luis Hernández Yáñez
21112 Domínguez 90000 12345 Álvarez 120000
21112 Jiménez 100000 22222 Fernández 120000
22222 Fernández 120000 33333 Tarazona 120000
33333 Tarazona 120000 10000 Hernández 150000
Ordenaciones naturales
Si el algoritmo trabaja menos cuanto más ordenada está
inicialmente la lista, se dice que la ordenación es natural
Ordenación por inserción con la lista inicialmente ordenada:
Versión que busca el lugar primero y luego desplaza:
No hay desplazamientos; mismo número de comparaciones
Comportamiento no natural
Versión con intercambios:
Trabaja mucho menos; basta una comparación cada vez
Comportamiento natural
Luis Hernández Yáñez
Intercambios
Asumimos que tardan un tiempo similar
Cálculo de la complejidad
Ordenación por inserción (con intercambios):
...
for (int i = 1; i < N; i++) {
int pos = i;
while ((pos > 0) && (lista[pos ‐ 1] > lista[pos])) {
int tmp; Comparación
tmp = lista[pos];
lista[pos] = lista[pos ‐ 1];
lista[pos ‐ 1] = tmp;
pos‐‐; Intercambio
}
Luis Hernández Yáñez
}
Intercambios y comparaciones:
Tantos como ciclos realicen los correspondientes bucles
... N ‐ 1 ciclos
for (int i = 1; i < N; i++) {
int pos = i; Nº variable de ciclos
while ((pos > 0) && (lista[pos ‐ 1] > lista[pos])) {
int tmp;
tmp = lista[pos];
lista[pos] = lista[pos ‐ 1];
lista[pos ‐ 1] = tmp;
pos‐‐;
}
Luis Hernández Yáñez
}
Caso en el que el while se ejecuta más: caso peor
Caso en el que se ejecuta menos: caso mejor
Cálculo de la complejidad
Caso mejor: lista inicialmente ordenada
La primera comparación falla: ningún intercambio
(N ‐ 1) * (1 comparación + 0 intercambios) = N ‐ 1 O(N)
Caso peor: lista inicialmente ordenada al revés
Para cada pos, entre i y 1: 1 comparación y 1 intercambio
1 + 2 + 3 + 4 + ... + (N ‐ 1)
((N ‐ 1) + 1) x (N ‐ 1) / 2
N * (N ‐ 1) / 2
(N2 ‐ N) / 2 O(N2)
Notación O grande: orden de complejidad en base a N
Luis Hernández Yáñez
Órdenes de complejidad
O(log N) < O(N) < O(N log N) < O(N2) < O(N3) ...
N log2 N N2
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
1 0 1
2 1 4
4 2 16
8 3 64
16 4 256
32 5 1024
64 6 4096
Luis Hernández Yáñez
128 7 16384
256 8 65536
...
Lista desordenada: 5 7 4 9 2 8 3 1 6
Lista ordenada:
Luis Hernández Yáñez
Lista desordenada: 5 7 4 9 2 8 3 6
Lista ordenada: 1
Luis Hernández Yáñez
Lista desordenada: 5 7 4 9 8 3 6
Lista ordenada: 1 2
Luis Hernández Yáñez
Lista desordenada: 5 7 4 9 8 6
Lista ordenada: 1 2 3
Luis Hernández Yáñez
Lista desordenada: 5 7 9 8 6
Lista ordenada: 1 2 3 4
Luis Hernández Yáñez
Lista desordenada: 7 9 8 6
Lista ordenada: 1 2 3 4 5
Luis Hernández Yáñez
Lista desordenada: 7 9 8
Lista ordenada: 1 2 3 4 5 6
Luis Hernández Yáñez
Lista desordenada: 9 8
Lista ordenada: 1 2 3 4 5 6 7
Luis Hernández Yáñez
Lista desordenada: 9
Lista ordenada: 1 2 3 4 5 6 7 8
Luis Hernández Yáñez
Lista desordenada:
Lista ordenada: 1 2 3 4 5 6 7 8 9
Luis Hernández Yáñez
20 7 14 32 5 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
im
Sólo intercambiamos si no es la misma posición
Luis Hernández Yáñez
5 7 14 32 20 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
5 7 14 32 20 14 27 12 13 15
0 1 2 3 4 5 6 7 8 9
i m
5 7 12 32 20 14 27 14 13 15
0 1 2 3 4 5 6 7 8 9
i m
Luis Hernández Yáñez
5 7 12 13 20 14 27 14 32 15
0 1 2 3 4 5 6 7 8 9
seleccion.cpp
Implementación const int N = 15;
typedef int tLista[N];
tLista lista;
// Desde el primer elemento hasta el penúltimo...
for (int i = 0; i < N ‐ 1; i++) {
int menor = i;
// Desde i + 1 hasta el final...
for (int j = i + 1; j < N; j++) {
if (lista[j] < lista[menor]) {
menor = j;
}
}
if (menor > i) {
int tmp;
tmp = lista[i];
Luis Hernández Yáñez
lista[i] = lista[menor];
lista[menor] = tmp;
}
}
Fundamentos de la programación: Algoritmos de ordenación Página 714
Complejidad de la ordenación por selección directa
¿Cuántas comparaciones se realizan?
Bucle externo: N ‐ 1 ciclos
Tantas comparaciones como elementos queden en la lista:
(N ‐ 1) + (N ‐ 2) + (N ‐ 3) + ... + 3 + 2 + 1 =
N x (N ‐ 1) / 2 = (N2 ‐ N) / 2 O(N2)
Mismo número de comparaciones en todos los casos
Complejidad: O(N2) Igual que el método de inserción
Algo mejor (menos intercambios; uno en cada paso)
No es estable: intercambios “a larga distancia”
Luis Hernández Yáñez
9 9 9 9 1
4 4 4 1 9
3 3 1 4 4
6 1 3 3 3
Luis Hernández Yáñez
1 6 6 6 6
12 32 14 5 14 7
0 1 2 3 4 5
12 32 14 5 7 14
0 1 2 3 4 5
12 32 14 5 7 14
0 1 2 3 4 5
12 32 5 14 7 14
0 1 2 3 4 5
12 5 32 14 7 14
Luis Hernández Yáñez
0 1 2 3 4 5
5 12 32 14 7 14
0 1 2 3 4 5
... const int N = 10;
int tmp; typedef int tLista[N];
// Del primero al penúltimo... tLista lista;
for (int i = 0; i < N ‐ 1; i++) {
// Desde el último hasta el siguiente a i...
for (int j = N ‐ 1; j > i; j‐‐) {
if (lista[j] < lista[j ‐ 1]) {
tmp = lista[j];
lista[j] = lista[j ‐ 1];
Luis Hernández Yáñez
lista[j ‐ 1] = tmp;
}
}
}
14 14 14 12
16 16 12 14
La lista ya está ordenada
35 12 16 16
Luis Hernández Yáñez
bool inter = true;
int i = 0;
// Desde el 1º hasta el penúltimo si hay intercambios...
while ((i < N ‐ 1) && inter) {
inter = false;
// Desde el último hasta el siguiente a i...
for (int j = N ‐ 1; j > i; j‐‐) {
if (lista[j] < lista[j ‐ 1]) {
int tmp;
tmp = lista[j];
lista[j] = lista[j ‐ 1];
lista[j ‐ 1] = tmp;
inter = true;
}
}
if (inter) {
Luis Hernández Yáñez
i++;
}
} Esta variación sí tiene un comportamiento natural
lista.cpp
typedef struct {
int codigo;
string nombre;
double sueldo;
} tRegistro;
typedef struct {
tArray registros;
int cont;
} tLista;
Luis Hernández Yáñez
Nuevas implementaciones:
Operadores relacionales
Inserción (mantener el orden)
Búsqueda (más eficiente)
Se guarda la lista en orden, por lo que cargar() no cambia
lista.registros[i] = registro;
lista.cont++;
}
}
5 7 12 13 14 14 15 20 27 32
0 1 2 3 4 5 6 7 8 9
cout << "No encontrado!" << endl;
}
Complejidad: O(N)
5 7 12 14 14 15 18 20 27 32
Luis Hernández Yáñez
0 1 2 3 4 5 6 7 8 9
5 7 12
14 14 15 18 20 27 32
0 1 2 3 4 5 6 7 8 9
5 7 12 14 14 15 18 20 27 32
0 1 2 3 4 5 6 7 8 9
Buscamos el 12
5 7 12 14 14 15 18 20 27 32
0 1 2 3 4 5 6 7 8 9
12 < lista[mitad] fin = mitad – 1
ini mitad fin
5 7 12 14 14 15 18 20 27 32
0 1 2 3 4 5 6 7 8 9
12 > lista[mitad] ini = mitad + 1
ini fin
Luis Hernández Yáñez
5 7 12 14 14 15 18 20 27 32
0 1 2 3 4 5 6 7 8 9
mitad ¡Encontrado!
Fundamentos de la programación: Algoritmos de ordenación Página 734
Si el elemento no está, nos quedamos sin sublista: ini > fin
Para el 13: mitad
ini fin
5 7 12 14 14 15 18 20 27 32
0 1 2 3 4 5 6 7 8 9
13 > lista[mitad] ini = mitad + 1
mitad
ini
fin
5 7 12 14 14 15 18 20 27 32
0 1 2 3 4 5 6 7 8 9
Luis Hernández Yáñez
13 < lista[mitad] fin = mitad – 1 2
¡¡¡ ini > fin !!! No hay dónde seguir buscando No está
Implementación const int N = 10;
typedef int tLista[N];
int buscado; tLista lista;
cout << "Valor a buscar: ";
cin >> buscado;
int ini = 0, fin = N – 1, mitad;
bool encontrado = false;
while ((ini <= fin) && !encontrado) {
mitad = (ini + fin) / 2; // División entera
if (buscado == lista[mitad]) {
encontrado = true;
}
else if (buscado < lista[mitad]) {
fin = mitad ‐ 1;
}
else {
Luis Hernández Yáñez
ini = mitad + 1;
}
} // Si se ha encontrado, está en [mitad]
const int N = 100;
typedef int tArray[N];
typedef struct {
tArray elementos;
int cont;
} tLista;
int main() {
tLista lista;
ifstream archivo;
Luis Hernández Yáñez
int dato;
lista.cont = 0;
archivo.open("ordenados.txt"); // Existe y es correcto
archivo >> dato;
...
Fundamentos de la programación: Algoritmos de ordenación Página 737
cout << "No encontrado!" << endl;
}
return 0;
} ...
pos = mitad;
}
return pos;
}
Complejidad
¿Qué orden de complejidad tiene la búsqueda binaria?
Caso peor:
No está o se encuentra en una sublista de 1 elemento
Nº de comparaciones = Nº de mitades que podemos hacer
N / 2, N / 4, N / 8, N / 16, ..., 8, 4, 2, 1
1, 2, 4, 8, ..., N / 16, N / 8, N / 4, N / 2
Si hacemos que N sea igual a 2k:
20, 21, 22, 23, ..., 2k‐4, 2k‐3, 2k‐2, 2k‐1
Nº de elementos de esa serie: k
Luis Hernández Yáñez
Nº de comparaciones = k N = 2k k = log2 N
Complejidad: O(log2 N) Mucho más rápida que O(N)
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
7A
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Ordenación por intercambio 744
Mezcla de dos listas ordenadas 747
Luis Hernández Yáñez
Fundamentos de la programación: Algoritmos de ordenación (Anexo)
Luis Hernández Yáñez
14 7 12 32 20 14 27 5 13 15
0 1 2 3 4 5 6 7 8 9
7 14 12 32 20 14 27 5 13 15
0 1 2 3 4 5 6 7 8 9
Luis Hernández Yáñez
5 14 12 32 20 14 27 7 13 15
0 1 2 3 4 5 6 7 8 9
const int N = 10;
typedef int tLista[N];
tLista lista;
...
for (int i = 0; i < N ‐ 1; i++) {
// Desde el primer elemento hasta el penúltimo
for (int j = i + 1; j < N; j++) {
// Desde i+1 hasta el final
if (lista[j] < lista[i]) {
int tmp;
tmp = lista[i];
lista[i] = lista[j];
lista[j] = tmp;
}
}
Luis Hernández Yáñez
}
Igual número de comparaciones, muchos más intercambios
No es estable
Fundamentos de la programación: Algoritmos de ordenación (Anexo) Página 746
Luis Hernández Yáñez
while ((pos1 < lista1.cont) && (pos2 < lista2.cont)
&& (listaM.cont < N)) {
if (lista1.elementos[pos1] < lista2.elementos[pos2]) {
listaM.elementos[listaM.cont] = lista1.elementos[pos1];
pos1++;
}
else {
listaM.elementos[listaM.cont] = lista2.elementos[pos2];
pos2++;
}
listaM.cont++;
Luis Hernández Yáñez
}
...
// Pueden quedar datos en alguna de las listas
if (pos1 < lista1.cont) {
while ((pos1 < lista1.cont) && (listaM.cont < N)) {
listaM.elementos[listaM.cont] = lista1.elementos[pos1];
pos1++;
listaM.cont++;
}
}
else { // pos2 < lista2.cont
while ((pos2 < lista2.cont) && (listaM.cont < N)) {
listaM.elementos[listaM.cont] = lista2.elementos[pos2];
pos2++;
listaM.cont++;
}
}
}
Luis Hernández Yáñez
// Los archivos existen y son correctos
archivo1.open(nombre1.c_str());
archivo2.open(nombre2.c_str());
mezcla.open(nombreM.c_str());
archivo1 >> dato1;
archivo2 >> dato2;
Luis Hernández Yáñez
while ((dato1 != ‐1) && (dato2 != ‐1)) {
// Mientras quede algo en ambos archivos
...
mezcla << dato2 << endl;
archivo2 >> dato2;
}
}
...
Fundamentos de la programación: Algoritmos de ordenación (Anexo) Página 752
mezcla2.cpp
archivo2.close();
archivo1.close();
mezcla << ‐1 << endl;
mezcla.close();
}
Luis Hernández Yáñez
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
8
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Programas multiarchivo y compilación separada 757
Interfaz frente a implementación 762
Uso de módulos de biblioteca 768
Ejemplo: Gestión de una lista ordenada I 770
Compilación de programas multiarchivo 778
El preprocesador 780
Cada cosa en su módulo 782
Ejemplo: Gestión de una lista ordenada II 784
El problema de las inclusiones múltiples 789
Compilación condicional 794
Protección frente a inclusiones múltiples 795
Ejemplo: Gestión de una lista ordenada III 796
Implementaciones alternativas 804
Espacios de nombres 808
Implementaciones alternativas 817
Luis Hernández Yáñez
Calidad y reutilización del software 827
Fundamentos de la programación: Programación modular
Luis Hernández Yáñez
Programas multiarchivo
Código fuente repartido entre varios archivos (módulos)
Cada módulo con sus declaraciones y sus subprogramas
Módulo: Unidad funcional (estructura de datos, utilidades, ...)
Lista Principal Cálculos Archivos
const int N = 10; int main() { double mean(tArray lista); bool cargar(tArray &lista,
typedef double tArray[N]; tArray lista; string nombre);
typedef struct { bool ok; double min(tArray lists);
tArray elem; init(lista); bool guardar(tArray lista,
int cont; cargar(lista, "bd.txt"); double max(tArray lista); string nombre);
} tArray; sort(lista);
double dato; double desv(tArray lista); bool mezclar(string arch1,
void init(tArray &lista); cout << "Dato: "; string arch2);
cin >> dato; int minIndex(tArray lista);
void insert(tArray &lista, insert(lista, dato, ok); int size(string nombre);
double elem, bool &ok); cout << min(lista) << endl; int maxIndex(tArray lista);
cout << max(lista) << endl; bool exportar(string nombre);
void remove(tArray &lista, cout << sum(lista) << endl; double sum(tArray lista);
int pos, bool &ok); guardar(lista, "bd.txt");
...
return 0;
}
Luis Hernández Yáñez
Ejecutable
Fundamentos de la programación: Programación modular Página 758
Compilación separada
Cada módulo se compila a código objeto de forma independiente
Lista lista.obj
const int N = 10; 00101110101011001010010010101
typedef double tArray[N]; 00101010010101011111010101000
typedef struct { 10100101010101010010101010101
tArray elem; 01100101010101010101010101001
int cont; 01010101010100000101010101101
} tArray; 01001010101010101000010101011
11001010101010111100110010101
void init(tArray &lista);
void insert(tArray &lista,
01101010101010010010101001111
00101010101001010100101010010
10100101010100101000010011110
Archivos archivos.obj
double elem, bool &ok); 10010101011001010101001010100
10101010101010010101001010101 11101010110010100100101010010
bool cargar(tArray &lista,
void remove(tArray &lista, 01000010101011100101010010100 10100101010111110101010001010
string nombre);
int pos, bool &ok); 01110101011101001101010100101 01010101010100101010101010110
... 01011111110101011001101010111 01010101010101010101010010101
bool guardar(tArray lista,
00001001010100101010101010110 01010101000001010101011010100
string nombre);
10101010101010000101010111100
bool mezclar(string arch1, 10101010101111001100101010110
string arch2); 10101010100100101010011110010
Compilación separada
Al compilar el programa principal, se adjuntan los módulos compilados
Principal
Módulos del programa int main() {
tArray lista;
Bibliotecas del sistema
bool ok;
init(lista);
cargar(lista, "bd.txt");
sort(lista);
lista.obj double dato; iostream.obj
cout << "Dato: ";
cin >> dato;
insert(lista, dato, ok);
calculos.obj cout << min(lista) << endl;
cout << max(lista) << endl;
fstream.obj
cout << sum(lista) << endl;
guardar(lista, "bd.txt");
archivos.obj ... }
return 0; math.obj ...
Luis Hernández Yáñez
Ejecutable
lista.cpp main.cpp
COMPILACIÓN
lista.obj iostream.obj
calculos.obj
fstream.obj
archivos.obj
main.obj
math.obj
... ...
ENLACE
Luis Hernández Yáñez
Ejecutable
Fundamentos de la programación: Programación modular Página 761
Luis Hernández Yáñez
Etcétera
+ Implementación de los subprogramas (cómo se hace)
void insert(tArray &lista,
Biblioteca
void init(tArray &lista); double elem, bool &ok) {
if (lista.cont == N) {
void insert(tArray &lista, ok false;
double elem, bool &ok); }
else {
void remove(tArray &lista, ...
int pos, bool &ok);
...
main.cpp
#include "lista.h"
Los nombres de archivos de cabecera
... propios (no del sistema) se encierran
entre dobles comillas, no entre ángulos
Interfaz
typedef double tArray[N];
typedef struct {
tArray elem;
int cont;
} tArray;
void insert(tArray &lista,
void remove(tArray &lista,
void init(tArray &lista);
Implementación #include "lista.h"
void init(tArray &lista) {
lista.cont = 0;
void insert(tArray &lista,
double elem, bool &ok) {
01000010101011100101010010100
01110101011101001101010100101
01011111110101011001101010111
00001001010100101010101010110
Archivo de cabecera lista.h
} tLista;
const string BD = "bd.txt";
...
¡Documenta bien el código!
Implementación lista.cpp
tRegistro nuevo() {
tRegistro registro;
cout << "Introduce el código: ";
cin >> registro.codigo;
cout << "Introduce el nombre: ";
cin >> registro.nombre;
Luis Hernández Yáñez
cout << "Introduce el sueldo: ";
cin >> registro.sueldo;
return registro;
} ...
Fundamentos de la programación: Programación modular Página 772
void insertar(tLista &lista, tRegistro registro, bool &ok) {
ok = true;
if (lista.cont == N) {
ok = false; // Lista llena
}
else {
int i = 0;
while ((i < lista.cont) && (lista.registros[i] < registro)) {
i++;
}
// Insertamos en la posición i
for (int j = lista.cont; j > i; j‐‐) {
// Desplazamos a la derecha
lista.registros[j] = lista.registros[j ‐ 1];
}
Luis Hernández Yáñez
lista.registros[i] = registro;
lista.cont++;
}
} ...
Fundamentos de la programación: Programación modular Página 773
void eliminar(tLista &lista, int pos, bool &ok) { // pos = 1..
ok = true;
if ((pos < 1) || (pos > lista.cont)) {
ok = false; // Posición inexistente
}
else {
pos‐‐; // Pasamos a índice del array
for (int i = pos + 1; i < lista.cont; i++) {
// Desplazamos a la izquierda
lista.registros[i ‐ 1] = lista.registros[i];
}
lista.cont‐‐;
}
}
Luis Hernández Yáñez
...
Fundamentos de la programación: Programación modular Página 774
Programa principal bd.cpp
int menu();
int main() {
tLista lista;
bool ok;
int op, pos;
cargar(lista, ok);
if (!ok) {
cout << "No se ha podido abrir el archivo!" << endl;
}
Luis Hernández Yáñez
else {
do {
mostrar(lista);
op = menu(); ...
Fundamentos de la programación: Programación modular Página 775
if (op == 1) {
tRegistro registro = nuevo();
insertar(lista, registro, ok);
if (!ok) {
cout << "Error: Lista llena!" << endl;
}
}
else if (op == 2) {
cout << "Posición: ";
cin >> pos;
eliminar(lista, pos, ok);
if (!ok) {
cout << "Error: Posicion inexistente!" << endl;
}
}
else if (op == 3) {
string nombre;
cin.sync();
Luis Hernández Yáñez
cout << "Nombre: ";
cin >> nombre;
int pos = buscar(lista, nombre);
...
Fundamentos de la programación: Programación modular Página 776
if (pos == ‐1) {
cout << "No se ha encontrado!" << endl;
}
else {
cout << "Encontrado en la posición " << pos << endl;
}
}
} while (op != 0);
guardar(lista);
}
return 0;
}
int menu() {
cout << endl;
cout << "1 ‐ Insertar" << endl;
cout << "2 ‐ Eliminar" << endl;
cout << "3 ‐ Buscar" << endl;
Luis Hernández Yáñez
Fundamentos de la programación: Programación modular Página 777
Luis Hernández Yáñez
Visual C++/Studio
Archivos de cabecera e implementación en grupos distintos:
Con Depurar ‐> Generar solución
se compilan todos los .cpp
typedef struct { typedef struct {
int codigo; int codigo;
string nombre; string nombre;
double sueldo; double sueldo;
} tRegistro; } tRegistro;
typedef tRegistro typedef tRegistro
tArray[N]; tArray[N];
Luis Hernández Yáñez
typedef struct { typedef struct {
tArray registros; tArray registros;
int cont; int cont;
} tLista; } tLista;
... ...
int menu();
...
typedef struct {
Cada estructura, en su módulo
tArray registros;
int cont;
} tLista;
Cabecera registro.h
typedef struct {
int codigo;
string nombre;
double sueldo;
} tRegistro;
tRegistro nuevo();
bool operator>(tRegistro opIzq, tRegistro opDer);
bool operator<(tRegistro opIzq, tRegistro opDer);
void mostrar(int pos, tRegistro registro);
Luis Hernández Yáñez
tRegistro nuevo() {
tRegistro registro;
cout << "Introduce el código: ";
cin >> registro.codigo;
cout << "Introduce el nombre: ";
cin >> registro.nombre;
cout << "Introduce el sueldo: ";
cin >> registro.sueldo;
return registro;
}
Luis Hernández Yáñez
Cabecera lista2.h
void mostrar(const tLista &lista);
void cargar(tLista &lista, bool &ok);
void guardar(tLista lista);
bd2.cpp
int menu();
int main() {
tLista lista;
¡No intentes compilar este ejemplo!
bool ok; Tiene errores
int op, pos;
cargar(lista, ok);
if (!ok) {
cout << "No se pudo abrir el archivo!" << endl;
}
Luis Hernández Yáñez
else {
do {
mostrar(lista);
op = menu();
...
Fundamentos de la programación: Programación modular Página 788
Luis Hernández Yáñez
...
registro.h #include "registro.h"
#include "lista2.h"
#include <string>
...
...
registro.cpp
...
#include "registro.h"
... lista2.h
...
#include "registro.h"
...
lista2.cpp
Luis Hernández Yáñez
...
Incluye... #include "lista2.h"
...
int menu(); #include <string>
#include <string> using namespace std;
... using namespace std;
#include "registro.h" typedef struct {
...
const int N = 100; } tRegistro;
typedef tRegistro tArray[N]; ...
typedef struct {
Luis Hernández Yáñez
tArray registros;
int cont;
} tLista;
...
#include <string> ...
using namespace std;
#include <string>
using namespace std;
typedef struct {
¡Identificador duplicado!
Luis Hernández Yáñez
...
} tRegistro;
...
Compilación condicional
Directivas #ifdef, #ifndef, #else y #endif
Se usan en conjunción con la directiva #define
#define X #define X
#ifdef X #ifndef X
... // Código if ... // Código if
[#else [#else
... // Código else ... // Código else
] ]
#endif #endif
La directiva #define define un símbolo (identificador)
Izquierda: se compilará el “Código if” y no el “Código else”
Luis Hernández Yáñez
Cabecera registrofin.h
typedef struct {
int codigo;
string nombre;
double sueldo;
} tRegistro;
tRegistro nuevo();
Luis Hernández Yáñez
tRegistro nuevo() {
tRegistro registro;
cout << "Introduce el código: ";
cin >> registro.codigo;
cout << "Introduce el nombre: ";
cin >> registro.nombre;
cout << "Introduce el sueldo: ";
cin >> registro.sueldo;
return registro;
}
Luis Hernández Yáñez
Cabecera listafin.h
int buscar(tLista lista, string nombre);
void cargar(tLista &lista, bool &ok);
void guardar(tLista lista);
#endif
for (int j = lista.cont; j > i; j‐‐) {
// Desplazamos a la derecha
lista.registros[j] = lista.registros[j ‐ 1];
}
...
Fundamentos de la programación: Programación modular Página 799
bdfin.cpp
int menu();
int main() {
tLista lista;
bool ok; ¡Ahora ya puedes compilarlo!
int op, pos;
cargar(lista, ok);
if (!ok) {
cout << "No se pudo abrir el archivo!" << endl;
}
Luis Hernández Yáñez
else {
do {
mostrar(lista);
op = menu();
...
Fundamentos de la programación: Programación modular Página 800
Gestión de una lista ordenada III
Preprocesamiento de #include en bdfin.cpp:
#include <iostream> #ifndef registrofin_h
using namespace std;
#define registrofin_h
#include <string>
#include "registrofin.h" using namespace std;
int menu();
...
int menu(); ¡registrofin_h ya está definido!
...
i++; lista.registros[lista.cont] = registro;
} lista.cont++;
// Insertamos en la posición i }
for (int j = lista.cont; j > i; j‐‐) { }
// Desplazamos a la derecha
lista.registros[j] = lista.registros[j ‐ 1];
...
for (int j = lista.cont; j > i; j‐‐) {
// Desplazamos a la derecha
lista.registros[j] = lista.registros[j ‐ 1];
}
lista.registros[i] = registro;
...
}
Variables i y d declaradas en el espacio de nombres miEspacio
} }
Ahora se distingue entre primero::x y segundo::x
cout << y << endl; // y es segundo::y
cout << primero::y << endl; // espacio explícito
cout << segundo::x << endl; // espacio explícito
return 0;
}
Fundamentos de la programación: Programación modular Página 811
using namespace
Introduce todos los nombres de un espacio en el ámbito actual:
#include <iostream>
using namespace std;
namespace primero {
int x = 5; 5
int y = 10;
} using [namespace] 10
namespace segundo { sólo tiene efecto 3.1416
double x = 3.1416; en el bloque
double y = 2.7183; en que se encuentra 2.7183
}
int main() {
using namespace primero;
cout << x << endl; // x es primero::x
cout << y << endl; // y es primero::y
Luis Hernández Yáñez
cout << segundo::x << endl; // espacio explícito
cout << segundo::y << endl; // espacio explícito
return 0;
}
void guardar(tLista lista);
} // namespace
#endif
Implementación
#include <iostream>
#include <fstream>
using namespace std;
#include "listaEN.h"
void ord::eliminar(tLista &lista, int pos, bool &ok) {
// ...
}
int ord::buscar(tLista lista, string nombre) {
// ...
Luis Hernández Yáñez
...
int menu();
int main() {
ord::tLista lista;
bool ok;
ord::cargar(lista, ok);
if (!ok) {
cout << "No se pudo abrir el archivo!" << endl;
}
Luis Hernández Yáñez
else {
ord::mostrar(lista);
...
O usar una instrucción using namespace ord;
Fundamentos de la programación: Programación modular Página 815
int menu();
int main() {
tLista lista;
bool ok;
cargar(lista, ok);
if (!ok) {
cout << "No se pudo abrir el archivo!" << endl;
Luis Hernández Yáñez
}
else {
mostrar(lista);
...
Cabecera listaEN.h
Implementaciones alternativas
Todo lo común puede estar fuera de la estructura namespace:
#ifndef listaEN_H
#define listaEN_H
#include "registrofin.h"
void mostrar(const tLista &lista);
void eliminar(tLista &lista, int pos, bool &ok); // pos = 1..N
...
listaEN.cpp
#include <iostream>
using namespace std;
#include <fstream>
#include "listaEN.h"
// IMPLEMENTACIÓN DE LOS SUBPROGRAMAS COMUNES
void eliminar(tLista &lista, int pos, bool &ok) { // ...
}
// IMPLEMENTACIÓN DE LOS SUBPROGRAMAS DEL ESPACIO DE NOMBRES ord
void ord::insertar(tLista &lista, tRegistro registro, bool &ok) {
ok = true;
if (lista.cont == N) {
ok = false; // Lista llena
}
Luis Hernández Yáñez
else {
int i = 0;
while ((i < lista.cont) && (lista.registros[i] < registro)) {
i++;
} ...
}
else {
ini = mitad + 1;
}
} ...
if (encontrado) {
mitad++;
}
else {
mitad = ‐1;
}
return mitad;
}
}
else {
pos++;
}
} ...
if (encontrado) {
pos++;
}
else {
pos = ‐1;
}
return pos;
}
Programa principal
#include <iostream>
using namespace std;
#include "registrofin.h"
#include "listaEN.h"
using namespace ord;
int menu();
int main() {
tLista lista;
bool ok;
...
tRegistro registro = nuevo();
insertar(lista, registro, ok);
if (!ok) {
Luis Hernández Yáñez
...
bdEN.cpp
Programa principal
#include <iostream>
using namespace std;
#include "registrofin.h"
#include "listaEN.h"
using namespace des;
int menu();
int main() {
tLista lista;
bool ok;
...
tRegistro registro = nuevo();
insertar(lista, registro, ok);
if (!ok) {
Luis Hernández Yáñez
...
Software de calidad
El software debe ser desarrollado con buenas prácticas de
ingeniería del software que aseguren un buen nivel de calidad
Los distintos módulos de la aplicación deben ser probados
exhaustivamente, tanto de forma independiente como en su
relación con los demás módulos
La prueba y depuración es muy importante y todos los equipos
deberán seguir buenas pautas para asegurar la calidad
Los módulos deben ser igualmente bien documentados, de
forma que otros desarrolladores puedan aprovecharlos
Luis Hernández Yáñez
No reinventemos la rueda
Desarrollar el software pensando en su posible reutilización
Un software de calidad debe poder ser fácilmente reutilizado
Nuestros módulos deben ser fácilmente usados y modificados
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
8A
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
ventas.cpp
int cont;
typedef struct { } tListaVentas;
int id_prod;
string codigo; ...
int menu();
int main() {
...
int cont;
typedef struct { Producto } tListaVentas;
int id_prod;
string codigo; ...
void mostrar(tProducto producto);
...
Lista de ventas
void inicializar(tListaVentas &lista);
void cargar(tListaVentas &lista);
void insertar(tListaVentas &lista, tVenta venta, bool &ok);
void buscar(const tListaVentas &lista, int id, tVenta &venta, bool &ok);
void eliminar(tListaVentas &lista, int id, bool &ok);
void ventasPorClientes(const tListaVentas &lista);
void ventasPorProductos(const tListaVentas &lista);
double totalVentas(const tListaVentas &ventas, string nif,
const tListaClientes &clientes,
const tListaProductos &productos);
void stock(const tListaVentas &ventas, const tListaClientes &clientes,
const tListaProductos &productos);
int menu();
Luis Hernández Yáñez
int main() {
...
Ventas
main.cpp
producto.cpp listaproductos.cpp
typedef struct {
int id_prod;
string codigo;
string nombre; producto.h string
double precio;
int unidades;
} tProducto;
#ifndef cliente_h
#define cliente_h
#include <string>
using namespace std;
typedef struct {
int id_cli;
string nif;
string nombre;
string telefono;
} tCliente;
tCliente nuevoCliente();
bool operator<(tCliente opIzq, tCliente opDer); // Por NIF
Luis Hernández Yáñez
#endif
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
9
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Direcciones de memoria y punteros 849
Operadores de punteros 854
Punteros y direcciones válidas 864
Punteros no inicializados 866
Un valor seguro: NULL 867
Copia y comparación de punteros 868
Tipos puntero 873
Punteros a estructuras 875
Punteros a constantes y punteros constantes 877
Punteros y paso de parámetros 879
Punteros y arrays 883
Memoria y datos del programa 886
Memoria dinámica 891
Punteros y datos dinámicos 895
Gestión de la memoria 907
Luis Hernández Yáñez
Errores comunes 911
Arrays de datos dinámicos 916
Arrays dinámicos 928
Fundamentos de la programación: Punteros y memoria dinámica
Luis Hernández Yáñez
El tipo del dato (int) indica cuántos bytes (4) requiere el dato:
00000000 00000000 00000000 00000101 5
(La codificación de los datos puede ser diferente; y la de las direcciones también)
&
Obtener la dirección de memoria de ...
...
i 0F03:1A38
int i, j;
0F03:1A39
... 0F03:1A3A
int *punt; 0F03:1A3B
j 0F03:1A3C
0F03:1A3D
0F03:1A3E
0F03:1A3F
...
punt 0F07:0417
Luis Hernández Yáñez
0F07:0418
0F07:0419
0F07:041A
...
i 0F03:1A38 00
int i, j;
0F03:1A39 00
... 0F03:1A3A 00
int *punt; 0F03:1A3B 05
... j 0F03:1A3C
0F03:1A3D
i = 5;
0F03:1A3E
0F03:1A3F
...
punt 0F07:0417
Luis Hernández Yáñez
0F07:0418
0F07:0419
i 5
0F07:041A
...
&
Obtener la dirección de memoria de ...
...
i 0F03:1A38 00
int i, j;
0F03:1A39 00
... 0F03:1A3A 00
int *punt; 0F03:1A3B 05
... j 0F03:1A3C
0F03:1A3D
i = 5;
0F03:1A3E
punt = &i;
0F03:1A3F
...
0F07:0418 03
i 0F07:0419 1A
5
0F07:041A 38
...
*
Obtener lo que hay en la dirección ...
...
i 0F03:1A38 00
int i, j;
0F03:1A39 00
... 0F03:1A3A 00
int *punt; 0F03:1A3B 05
... j 0F03:1A3C
0F03:1A3D
i = 5;
0F03:1A3E
punt = &i;
0F03:1A3F
j = *punt; ...
punt 0F07:0417 0F
Luis Hernández Yáñez
0F07:0418 03
0F07:0419 1A
punt:
0F07:041A 38
...
i 0F03:1A38 00
int i, j;
0F03:1A39 00
... 0F03:1A3A 00
Direccionamiento
int *punt; indirecto 0F03:1A3B 05
punt 0F07:0417 0F
Luis Hernández Yáñez
0F07:0418 03
0F07:0419 1A
*punt:
0F07:041A 38
...
*
Obtener lo que hay en la dirección ...
...
i 0F03:1A38 00
int i, j;
0F03:1A39 00
... 0F03:1A3A 00
int *punt; 0F03:1A3B 05
... j 0F03:1A3C 00
0F03:1A3D 00
i = 5;
0F03:1A3E 00
punt = &i;
0F03:1A3F 05
j = *punt; ...
punt 0F07:0417 0F
Luis Hernández Yáñez
0F07:0418 03
0F07:0419 1A
0F07:041A 38
...
int main() {
int i = 5;
int j = 13;
int *punt;
punt = &i;
cout << *punt << endl; // Muestra el valor de i
punt = &j;
cout << *punt << endl; // Ahora muestra el valor de j
int *otro = &i;
cout << *otro + *punt << endl; // i + j
int k = *punt;
Luis Hernández Yáñez
cout << k << endl; // Mismo valor que j
return 0;
}
int i;
int *q; // q no tiene aún una dirección válida
int *p = &i; // p toma una dirección válida
Luis Hernández Yáñez
q = p; // ahora q ya tiene una dirección válida
q = NULL; // otra dirección válida para q
punt1 X punt2
Luis Hernández Yáñez
x 5
punt1 punt2
Luis Hernández Yáñez
x 5
punt1 punt2
tipos.cpp
Con *puntero podemos hacer lo que con otros datos del tipo base
puntero‐>codigo puntero‐>nombre puntero‐>sueldo
puntero‐>... (*puntero)....
structPtr.cpp
Punteros a constantes:
typedef const int *tIntCtePtr; // Puntero a constante
int entero1 = 5, entero2 = 13;
tIntCtePtr punt_a_cte = &entero1;
(*punt_a_cte)++; // ERROR: ¡Dato no modificable!
Luis Hernández Yáñez
punt_a_cte = &entero2; // OK: El puntero no es cte.
constPtr.cpp
Punteros constantes:
typedef int *const tIntPtrCte; // Puntero constante
int entero1 = 5, entero2 = 13;
tIntPtrCte punt_cte = &entero1;
(*punt_cte)++; // OK: El puntero no apunta a cte.
Luis Hernández Yáñez
param.cpp
SÍ puede cambiar
cout << entero << endl;
Mostrará 6 en la consola
cout << entero << endl; entero 6
Prototipo equivalente:
void foo(int *param1, double *param2, char *param3);
intPtr inicializar();
Datos globales
Código del
Memoria principal
programa
Luis Hernández Yáñez
S.O.
S.O.
typedef struct {
...
} tRegistro;
const int N = 1000;
typedef tRegistro tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
Luis Hernández Yáñez
int main() {
...
S.O.
void func(tLista lista, double &total)
{
tLista aux;
int i;
...
func(lista, resultado)
Datos dinámicos
Se crean y se destruyen durante la ejecución del programa
Se les asigna memoria del montón
Creación
Montón
Dato dinámico
Destrucción
Datos dinámicos
En el montón cuando el programa lo solicita
Luis Hernández Yáñez
Datos estáticos
Datos declarados como de un tipo concreto:
int i;
Se acceden directamente a través del identificador:
cout << i;
Datos dinámicos
Datos accedidos a través de su dirección de memoria
Esa dirección de memoria debe estar el algún puntero
Los punteros son la base del SGMD
Luis Hernández Yáñez
// estática i (accesible con i o con *p1)
p2 = new int; // Puntero que da acceso a una variable
// dinámica (accesible sólo a través de p2)
int main() {
tRegistro reg;
reg = nuevo();
Luis Hernández Yáñez
El operador delete
delete puntero; Devuelve al montón la memoria usada por
la variable dinámica apuntada por puntero
int *p;
p = new int;
*p = 12;
...
delete p; // Ya no se necesita el entero apuntado por p
#include <iostream>
using namespace std;
int main() {
double a = 1.5; p1 Identificadores:
double *p1, *p2, *p3;
p1 = &a; 4
p2 = new double; (a, p1, p2, p3)
*p2 = *p1; a 1.5
p3 = new double;
*p3 = 123.45;
cout << *p1 << endl; p2 1.5 Variables:
cout << *p2 << endl;
cout << *p3 << endl; 6
delete p2; (+ *p2 y *p3)
Luis Hernández Yáñez
#include <iostream>
using namespace std; PILA
a 1.5
int main() { p1 ?
double a = 1.5;
p2 ?
double *p1, *p2, *p3;
p3 ?
Luis Hernández Yáñez
MONTÓN
MONTÓN
#include <iostream>
using namespace std; PILA
a 1.5
int main() { p1
double a = 1.5;
p2
double *p1, *p2, *p3;
p1 = &a; p3 ?
p2 = new double;
Luis Hernández Yáñez
MONTÓN
1.5
MONTÓN
#include <iostream>
using namespace std; PILA
a 1.5
int main() { p1
double a = 1.5;
p2
double *p1, *p2, *p3;
p1 = &a; p3
p2 = new double;
*p2 = *p1;
p3 = new double;
Luis Hernández Yáñez
1.5
MONTÓN
123.45
Luis Hernández Yáñez
1.5
MONTÓN
#include <iostream>
using namespace std; PILA
a 1.5
int main() { p1
double a = 1.5;
p2 ?
double *p1, *p2, *p3;
p1 = &a; p3
p2 = new double;
*p2 = *p1;
p3 = new double;
*p3 = 123.45;
cout << *p1 << endl;
cout << *p2 << endl;
cout << *p3 << endl;
delete p2; 123.45
Luis Hernández Yáñez
MONTÓN
delete p3;
MONTÓN
Colisión pila‐montón
Los límites de ambas regiones se encuentran
Se agota la memoria
Desbordamiento de la pila
Luis Hernández Yáñez
return 0;
Sólo se ha creado
Luis Hernández Yáñez
}
una variable
mostrar(*p);
delete p;
...
mostrar(*p); p ha dejado de apuntar
al dato dinámico destruido
return 0; Acceso a memoria inexistente
}
Luis Hernández Yáñez
int cont;
} tLista; Se crean a medida que se insertan
Se destruyen a medida que se eliminan
tLista lista;
lista.cont = 0;
lista.cont 0
0 1 2 3 4 5 6 998 999
lista.registros
Luis Hernández Yáñez
lista.cont 1
0 1 2 3 4 5 6 998 999
lista.registros
Luis Hernández Yáñez
tLista lista;
lista.cont = 0;
lista.registros[lista.cont] = new tRegistro(nuevo());
lista.cont++;
lista.registros[lista.cont] = new tRegistro(nuevo());
lista.cont++;
lista.cont 2
0 1 2 3 4 5 6 998 999
lista.registros
Luis Hernández Yáñez
lista.cont 3
0 1 2 3 4 5 6 998 999
lista.registros
Luis Hernández Yáñez
lista.cont 3
0 1 2 3 4 5 6 998 999
lista.registros
Luis Hernández Yáñez
lista.cont 3
0 1 2 3 4 5 6 998 999
lista.registros
Luis Hernández Yáñez
lista.h
#ifndef lista_h
#define lista_h registro.h con el tipo puntero:
#include "registro.h"
typedef tRegistro *tRegPtr;
const int N = 1000;
const string BD = "bd.dat";
typedef tRegPtr tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
void mostrar(const tLista &lista);
void insertar(tLista &lista, tRegistro registro, bool &ok);
void eliminar(tLista &lista, int code, bool &ok);
int buscar(const tLista &lista, int code);
void cargar(tLista &lista, bool &ok);
Luis Hernández Yáñez
#endif
}
lista.cont‐‐;
}
}
delete lista.registros[i];
}
lista.cont = 0;
}
...
#include <iostream>
using namespace std;
#include "registro.h"
#include "lista.h"
int main() {
tLista lista;
bool ok;
cargar(lista, ok);
if (ok) {
mostrar(lista);
destruir(lista);
}
return 0;
Luis Hernández Yáñez
#include <iostream>
using namespace std;
const int N = 10;
int main() {
int *p = new int[N];
for (int i = 0; i < N; i++) {
p[i] = i;
}
for (int i = 0; i < N; i++) {
cout << p[i] << endl;
}
delete [] p;
¡No olvides destruir el array dinámico!
Luis Hernández Yáñez
return 0;
}
...
#include "registro.h"
// Lista: array dinámico (puntero) y contador
typedef struct {
tRegPtr registros;
int cont;
} tLista;
...
Luis Hernández Yáñez
listaAD.cpp
lista.registros[i ‐ 1] = lista.registros[i];
}
lista.cont‐‐;
}
} ...
lista.cont = 0;
}
...
archivo >> registro.codigo;
}
archivo.close();
}
}
0 1 2 3 4 5 6 7
Luis Hernández Yáñez
Montón
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
9A
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Aritmética de punteros 940
Recorrido de arrays con punteros 953
Referencias 962
Listas enlazadas 964
Luis Hernández Yáñez
Fundamentos de la programación: Punteros y memoria dinámica (Anexo)
Luis Hernández Yáñez
punt 0F07:041B 0F
0F07:041C 03
0F07:041D 1A
0F07:041E 38
...
punt 0F07:041B 0F
0F07:041C 03
punt 0F07:041B 0F
0F07:041C 03
0F07:041D 1A
Restando pasamos a elementos anteriores 0F07:041E 40
...
punt 0F07:041B 0F
0F07:041C 03
0F07:041D 1A
0F07:041E 3C
...
short int (2 bytes)
dias[0] 0F03:1A38
0F03:1A39 31
short int dias[12] = {31, 28, 31, 30, dias[1] 0F03:1A3A
28
0F03:1A3B
31, 30, 31, 31, 30, 31, 30, 31}; dias[2] 0F03:1A3C
0F03:1A3D 31
typedef short int* tSIPtr; dias[3] 0F03:1A3E
tSIPtr punt = dias; 0F03:1A3F 30
dias[4] 0F03:1A40
0F03:1A41 31
...
dias 0F07:0417 0F
0F07:0418 03
0F07:0419 1A
0F07:041A 38
punt 0F07:041B 0F
Luis Hernández Yáñez
0F07:041C 03
0F07:041D 1A
0F07:041E 38
...
short int dias[12] = {31, 28, 31, 30,
...
31, 30, 31, 31, 30, 31, 30, 31};
dias[0] 0F03:1A38
typedef short int* tSIPtr; 0F03:1A39 31
dias[1] 0F03:1A3A
tSIPtr punt = dias; 0F03:1A3B 28
punt++; dias[2] 0F03:1A3C
31
0F03:1A3D
dias[3] 0F03:1A3E
0F03:1A3F 30
dias[4] 0F03:1A40
0F03:1A41 31
...
dias 0F07:0417 0F
0F07:0418 03
0F07:0419 1A
0F07:041A 38
punt 0F07:041B 0F
Luis Hernández Yáñez
0F07:041C 03
0F07:041D 1A
0F07:041E 3A
...
0F07:041C 03
0F07:041D 1A
0F07:041E 40
...
short int dias[12] = {31, 28, 31, 30,
...
31, 30, 31, 31, 30, 31, 30, 31};
dias[0] 0F03:1A38
typedef short int* tSIPtr; 0F03:1A39 31
dias[1] 0F03:1A3A
tSIPtr punt = dias; 0F03:1A3B 28
punt++; dias[2] 0F03:1A3C
0F03:1A3D 31
punt = punt + 3; dias[3] 0F03:1A3E
punt‐‐; 0F03:1A3F 30
dias[4] 0F03:1A40
0F03:1A41 31
...
dias 0F07:0417 0F
0F07:0418 03
0F07:0419 1A
0F07:041A 38
punt 0F07:041B 0F
Luis Hernández Yáñez
0F07:041C 03
0F07:041D 1A
0F07:041E 3E
...
punt‐‐; 0F03:1A3F 30
dias[4] 0F03:1A40
tSIPtr punt2; 0F03:1A41 31
...
dias 0F07:0417 0F
0F07:0418 03
0F07:0419 1A
0F07:041A 38
punt 0F07:041B 0F
Luis Hernández Yáñez
0F07:041C 03
0F07:041D 1A
0F07:041E 3E
punt2 0F07:041F ?
short int dias[12] = {31, 28, 31, 30,
...
31, 30, 31, 31, 30, 31, 30, 31};
dias[0] 0F03:1A38
typedef short int* tSIPtr; 0F03:1A39 31
dias[1] 0F03:1A3A
siPtr punt = dias; 0F03:1A3B 28
punt++; dias[2] 0F03:1A3C
0F03:1A3D 31
punt = punt + 3; dias[3] 0F03:1A3E
punt‐‐; 0F03:1A3F 30
dias[4] 0F03:1A40
tSIPtr punt2; 0F03:1A41 31
...
punt2 = dias; dias 0F07:0417 0F
0F07:0418 03
0F07:0419 1A
0F07:041A 38
punt 0F07:041B 0F
Luis Hernández Yáñez
0F07:041C 03
0F07:041D 1A
0F07:041E 3E
punt2 0F07:041F 0F
punt‐‐; 0F03:1A3F 30
dias[4] 0F03:1A40
tSIPtr punt2; 0F03:1A41 31
...
punt2 = dias; dias 0F07:0417 0F
0F07:041C 03
0F07:041D 1A
0F07:041E 3E
punt2 0F07:041F 0F
punt++;
}
...
intPtr punt = lista.elementos;
punt
0 1 2 3 4 5 6 7 8 ... 98 99
lista.elementos 4 13 3 47 53 19 7 48
lista.cont 8
Luis Hernández Yáñez
i 0 punt
0 1 2 3 4 5 6 7 8 ... 98 99
lista.elementos 4 13 3 47 53 19 7 48
lista.cont 8
Luis Hernández Yáñez
...
for (int i = 0; i < lista.cont; i++) { 4
cout << *punt << endl;
punt++;
}
i 1 punt
0 1 2 3 4 5 6 7 8 ... 98 99
lista.elementos 4 13 3 47 53 19 7 48
lista.cont 8
Luis Hernández Yáñez
i 2 punt
0 1 2 3 4 5 6 7 8 ... 98 99
lista.elementos 4 13 3 47 53 19 7 48
lista.cont 8
Luis Hernández Yáñez
...
for (int i = 0; i < lista.cont; i++) { 4
13
cout << *punt << endl; 3
punt++;
}
i 3 punt
0 1 2 3 4 5 6 7 8 ... 98 99
lista.elementos 4 13 3 47 53 19 7 48
lista.cont 8
Luis Hernández Yáñez
. . .
i 7 punt
0 1 2 3 4 5 6 7 8 ... 98 99
lista.elementos 4 13 3 47 53 19 7 48
lista.cont 8
Luis Hernández Yáñez
...
for (int i = 0; i < lista.cont; i++) { 4
13
cout << *punt << endl; 3
punt++; 47
} 53
19
7
48
i 8 punt
0 1 2 3 4 5 6 7 8 ... 98 99
lista.elementos 4 13 3 47 53 19 7 48
lista.cont 8
Luis Hernández Yáñez
Vacía
Lista ¡Definición recursiva!
Elemento seguido de una lista
lista
struct tNodo;
typedef tNodo *tLista;
struct tNodo {
tRegistro reg;
tLista sig;
};
tLista lista = NULL; // Lista vacía
lista = new tNodo;
lista‐>reg = nuevo();
lista‐>sig = NULL;
Luis Hernández Yáñez
lista ítem1
p
Luis Hernández Yáñez
lista ítem1
tLista lista = NULL; // Lista vacía
lista = new tNodo;
lista‐>reg = nuevo();
lista‐>sig = NULL;
tLista p;
p = lista;
p‐>sig = new tNodo;
p‐>sig‐>reg = nuevo();
p‐>sig‐>sig = NULL;
p
Luis Hernández Yáñez
struct tNodo;
typedef tNodo *tLista;
struct tNodo {
tRegistro reg;
tLista sig;
};
listaenlazada.cpp
} p
p‐>sig = nuevo;
}
lista
}
} ...
else {
ant = p; lista
p = p‐>sig;
}
} ...
if (!encontrado) {
ok = false; // No existe ese código
}
else {
ant‐>sig = p‐>sig;
delete p;
}
}
}
...
ant p
lista
Luis Hernández Yáñez
while (p != NULL) {
mostrar(p‐>reg);
p = p‐>sig;
}
} ...
...
lista = lista‐>sig;
delete p;
}
}
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
10
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Concepto de recursión 983
Algoritmos recursivos 986
Funciones recursivas 987
Diseño de funciones recursivas 989
Modelo de ejecución 990
La pila del sistema 992
La pila y las llamadas a función 994
Ejecución de la función factorial() 1005
Tipos de recursión 1018
Recursión simple 1019
Recursión múltiple 1020
Recursión anidada 1022
Recursión cruzada 1026
Código del subprograma recursivo 1027
Parámetros y recursión 1032
Ejemplos de algoritmos recursivos 1034
Luis Hernández Yáñez
Búsqueda binaria 1035
Torres de Hanoi 1038
Recursión frente a iteración 1043
Estructuras de datos recursivas 1045
Fundamentos de la programación: Introducción a la recursión
Luis Hernández Yáñez
(wikipedia.org)
La imagen del paquete
Luis Hernández Yáñez
factorial.cpp
Funciones recursivas
long long int factorial(int n) {
long long int resultado;
if (n == 0) { // Caso base
resultado = 1;
}
else {
resultado = n * factorial(n ‐ 1);
}
return resultado;
}
factorial(5) 5 x factorial(4) 5 x 4 x factorial(3)
5 x 4 x 3 x factorial(2) 5 x 4 x 3 x 2 x factorial(1)
Luis Hernández Yáñez
5 x 4 x 3 x 2 x 1 x factorial(0) 5 x 4 x 3 x 2 x 1 x 1
120 Caso base
Datos del programa
S.O.
2
7 7 7
Luis Hernández Yáñez
4 4 4 4
... Pila
Llamada a función:
<DIR1> cout << funcA(4);
Entra la dirección de vuelta
...
... Pila
<DIR1> cout << funcA(4);
...
... Pila
<DIR1> cout << funcA(4);
...
... Pila
<DIR1> cout << funcA(4);
...
... Pila
<DIR1> cout << funcA(4);
...
... Pila
<DIR1> cout << funcA(4);
...
... Pila
<DIR1> cout << funcA(4);
...
... Pila
<DIR1> cout << funcA(4);
...
... Pila
<DIR1> cout << funcA(4);
...
... Pila
<DIR1> cout << funcA(4); La ejecución continúa
en esa dirección
...
... funcC(...)
}
int funcA(...) { funcC
...
... funcB(...) funcB
}
int main() { funcA
Luis Hernández Yáñez
...
cout << funcA(...); Pila
...
cout << factorial(5) << endl;
Luis Hernández Yáñez
factorial(5)
resultado = ?
Luis Hernández Yáñez
n = 5
Pila
resultado = ?
n = 4
resultado = ?
Luis Hernández Yáñez
n = 5
Pila
factorial(5)
factorial(4)
factorial(3)
resultado = ?
n = 3
resultado = ?
n = 4
resultado = ?
Luis Hernández Yáñez
n = 5
Pila
resultado = ?
n = 2
resultado = ?
n = 3
resultado = ?
n = 4
resultado = ?
Luis Hernández Yáñez
n = 5
Pila
factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
resultado = ?
n = 1
resultado = ?
n = 2
resultado = ?
n = 3
resultado = ?
n = 4
resultado = ?
Luis Hernández Yáñez
n = 5
Pila
factorial(0) resultado = ?
n = 1
resultado = ?
n = 2
resultado = ?
n = 3
resultado = ?
n = 4
resultado = ?
Luis Hernández Yáñez
n = 5
Pila
factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
factorial(0) resultado = 1
n = 1
resultado = ?
1
n = 2
resultado = ?
n = 3
resultado = ?
n = 4
resultado = ?
Luis Hernández Yáñez
n = 5
Pila
resultado = 2
1
n = 2
1 resultado = ?
n = 3
resultado = ?
n = 4
resultado = ?
Luis Hernández Yáñez
n = 5
Pila
factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
factorial(0)
1
1 resultado = 6
n = 3
2
resultado = ?
n = 4
resultado = ?
Luis Hernández Yáñez
n = 5
Pila
1
1
2
resultado = 24
6 n = 4
resultado = ?
Luis Hernández Yáñez
n = 5
Pila
factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
factorial(0)
1
1
2
6
24 resultado = 120
Luis Hernández Yáñez
n = 5
Pila
1
1
2
6
24
Luis Hernández Yáñez
120
Pila
0 si n = 0
Fib(n) 1 si n = 1
Fib(n‐1) + Fib(n‐2) si n > 1
... 0 si n = 0
int main() { Fib(n) 1 si n = 1
for (int i = 0; i < 20; i++) { Fib(n‐1) + Fib(n‐2) si n > 1
cout << fibonacci(i) << endl;
}
return 0;
}
n + 1 si m = 0
n + 1 si m = 0
Números de Ackermann Ack(m, n) Ack(m‐1, 1) si m > 0 y n = 0
}
Pruébalo con números muy bajos:
Se generan MUCHAS llamadas recursivas
n + 1 si m = 0
Números de Ackermann Ack(m, n) Ack(m‐1, 1) si m > 0 y n = 0
Ack(m‐1, Ack(m, n‐1)) si m > 0 y n > 0
ackermann(1, 1)
ackermann(0, ackermann(1, 0))
2
3 ackermann(0, 1)
ackermann(0, 2)
Luis Hernández Yáñez
2
ackermann(0, 1)
3
ackermann(0, 2)
ackermann(1, 3)
ackermann(0, ackermann(1, 2))
ackermann(0, ackermann(1, 1))
4 ackermann(0, ackermann(1, 0))
5
Luis Hernández Yáñez
2
ackermann(0, 1)
3
ackermann(0, 2)
ackermann(0, 3)
ackermann(0, 4)
func(5);
int main() {
tLista lista;
lista.cont = 0;
// Carga del array...
mostrar(lista, 0);
return 0;
}
cout << lista.elementos[pos] << endl;
mostrar(lista, pos + 1);
}
}
inverso.cpp
int main() {
tLista lista;
lista.cont = 0;
// Carga del array...
mostrar(lista, 0);
return 0;
}
mostrar(lista, pos + 1);
cout << lista.elementos[pos] << endl;
}
}
}
Cuando n es 0, el argumento de fact toma el valor 1
Al volver se le va multiplicando por los demás n (distintos)
Fundamentos de la programación: Introducción a la recursión Página 1032
Luis Hernández Yáñez
binaria.cpp
A B C
A B C
Luis Hernández Yáñez
int main() {
int n;
cout << "Número de torres: ";
cin >> n;
hanoi(n, 'A', 'C', 'B');
Luis Hernández Yáñez
return 0;
}
assert(n >= 0); assert(n >= 0);
return fact;
}
Luis Hernández Yáñez
¿Qué es preferible?
Cualquier algoritmo recursivo tiene uno iterativo equivalente
Los recursivos son menos eficientes que los iterativos:
Sobrecarga de las llamadas a subprograma
Si hay una versión iterativa sencilla, será preferible a la recursiva
En ocasiones la versión recursiva es mucho más simple
Será preferible si no hay requisitos de rendimiento
Compara las versiones recursivas del factorial o de los números
de Fibonacci con sus equivalentes iterativas
¿Y qué tal una versión iterativa para los números de Ackermann?
Luis Hernández Yáñez
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez
AP
Grado en Ingeniería Informática
Grado en Ingeniería del Software
Grado en Ingeniería de Computadores
Flujos 1051
Archivos binarios 1054
Tamaño de los datos: El operador sizeof() 1056
Apertura de archivos binarios 1059
Lectura de archivos binarios (acceso secuencial) 1061
Escritura en archivos binarios (acceso secuencial) 1066
Acceso directo o aleatorio 1070
Ejemplos de uso de archivos binarios 1078
Ordenación de los registros del archivo 1079
Búsqueda binaria 1085
Inserción en un archivo binario ordenado 1088
Carga de los registro de un archivo en una tabla 1092
Almacenamiento de una tabla en un archivo 1093
Luis Hernández Yáñez
Fundamentos de la programación: Archivos binarios
Luis Hernández Yáñez
Flujos
Canalizan la E/S entre los dispositivos y el programa
En forma de secuencias de caracteres
La entrada puede proceder de un dispositivo o de un archivo
La salida puede dirigirse a un dispositivo o a un archivo
Siempre por medio de flujos
Dispositivos/archivos
Dispositivos/archivos de salida
de entrada
Programa
Luis Hernández Yáñez
Lo que signifiquen los códigos dependerá del programa que use el archivo
Flujo binario 07 6C C1 56
Luis Hernández Yáñez
El operador sizeof()
En los archivos binarios se manejan códigos binarios (bytes)
sizeof() (palabra clave): bytes que ocupa en memoria algo
Se aplica a un dato o a un tipo char byte
const int Max = 80;
typedef char tCadena[Max];
typedef struct {
int codigo;
tCadena item;
double valor;
} tRegistro;
Luis Hernández Yáñez
... 0F03:1A3C 0A
0F03:1A3D 37
Posiciones de memoria usadas SIZE
0F03:1A3E 1C
(12)
0F03:1A3F DF
reg.val
0F03:1A40 03
(8)
0F03:1A41 92
0F03:1A44 ...
Flujo binario
00 00 00 05 0A 37 1C DF 03 92 99 0E
Biblioteca fstream
archivo.read(puntero_al_búfer, número)
búfer: variable destino de los caracteres leídos
Pasado como puntero a secuencia de caracteres
Referencia (&) a la variable destino
Molde de puntero a carácter (char *)
número: cantidad de caracteres a extraer del archivo
Operador sizeof()
Archivo abierto con los modos ios::in e ios::binary
archivo.read( (char *) ®istro, sizeof(tRegistro));
Luis Hernández Yáñez
else {
// Lectura OK
...
leer.cpp
#include <iostream>
using namespace std;
#include <fstream>
#include "registro.h"
int main() {
tRegistro registro;
fstream archivo;
archivo.open("bd.dat", ios::in | ios::binary);
archivo.read( (char *) ®istro, SIZE);
int cuantos = archivo.gcount();
while (cuantos == SIZE) {
mostrar(registro);
archivo.read( (char *) ®istro, SIZE);
cuantos = archivo.gcount();
Luis Hernández Yáñez
}
archivo.close(); ¡No olvides cerrar el archivo!
return 0;
}
El tipo tRegistro
const int Max = 80;
typedef char tCadena[Max];
typedef struct {
int codigo;
tCadena item;
double valor;
} tRegistro;
const int SIZE = sizeof(tRegistro);
¿Por qué usamos cadenas al estilo de C?
string: tamaño variable en memoria
Requieren un proceso de serialización
Luis Hernández Yáñez
escribir.cpp
#include <iostream>
using namespace std;
#include <fstream>
#include "registro.h"
int main() {
tRegistro registro;
fstream archivo;
archivo.open("bd2.dat", ios::out | ios::binary);
bool seguir = true;
while (seguir) {
cout << "Código: ";
cin.sync();
cin >> registro.codigo;
cout << "Nombre: ";
Luis Hernández Yáñez
cin.sync();
cin.getline(registro.item, Max); // Máx: 80
...
ios::beg ios::end
0 SIZE 2*SIZE 3*SIZE 4*SIZE 5*SIZE 6*SIZE
SIZE SIZE SIZE SIZE SIZE SIZE
Lecturas y escrituras
Una vez ubicado el puntero al principio de un registro,
se puede leer el registro o actualizar (escribir) el registro
Si se ubica al final, se puede añadir (escribir) un nuevo registro
// Actualización de un registro
#include <iostream>
using namespace std;
#include <fstream>
#include "registro.h"
int main() {
tRegistro registro;
fstream archivo;
int num;
cout << "Registro número? ";
cin >> num;
...
if ((num > 0) && (num <= numReg)) {
archivo.seekg((num ‐ 1) * SIZE, ios::beg);
archivo.read( (char *) ®istro, SIZE);
mostrar(registro);
cout << endl << "Cambiar nombre [S/N]? ";
char c;
cin.sync();
cin >> c;
if ((c == 's') || (c == 'S')) {
cout << "Nombre: ";
cin.sync();
cin.getline(registro.item, 80);
}
cout << endl << "Cambiar precio [S/N]? ";
cin.sync();
cin >> c;
Luis Hernández Yáñez
if ((c == 's') || (c == 'S')) {
cout << "Precio: ";
cin >> registro.valor;
}
...
Fundamentos de programación: Archivos binarios Página 1076
archivo.seekg((num ‐ 1) * SIZE, ios::beg);
archivo.write( (char *) ®istro, SIZE);
cout << endl << "Registro actualizado:" << endl;
archivo.seekg((num ‐ 1) * SIZE, ios::beg);
archivo.read( (char *) ®istro, SIZE);
mostrar(registro);
}
archivo.close();
return 0;
}
Luis Hernández Yáñez
void mostrar();
...
Luis Hernández Yáñez
void mostrar() {
fstream archivo;
tRegistro registro;
int cuantos;
archivo.open(BD, ios::in | ios::binary);
archivo.read( (char *) ®istro, SIZE);
cuantos = archivo.gcount();
while (cuantos == SIZE) {
mostrar(registro);
archivo.read( (char *) ®istro, SIZE);
cuantos = archivo.gcount();
}
archivo.close();
}
Luis Hernández Yáñez
...
fstream archivo;
archivo.open(BD, ios::in | ios::out | ios::binary);
archivo.seekg(0, ios::end);
Luis Hernández Yáñez
int pos = archivo.tellg();
int numReg = pos / SIZE;
...
// Ordenamos con el método de selección directa
tRegistro regMenor, reg;
for (int i = 0; i < numReg ‐ 1; i++) {
int menor = i;
for (int j = i + 1; j < numReg; j++) {
archivo.seekg(menor * SIZE, ios::beg);
archivo.read( (char *) ®Menor, SIZE);
archivo.seekg(j * SIZE, ios::beg);
archivo.read( (char *) ®, SIZE);
if (strcmp(reg.item, regMenor.item) < 0) {
menor = j;
}
}
... regMenor reg
menor
i j
Luis Hernández Yáñez
i
menor j
Luis Hernández Yáñez
archivo.close();
cout << endl << "Tras ordenar:" << endl << endl;
mostrar();
return 0;
}
Luis Hernández Yáñez
void mostrar();
int main() {
mostrar();
tRegistro registro;
fstream archivo;
Luis Hernández Yáñez
...
archivo.open(BD, ios::in | ios::binary);
archivo.seekg(0, ios::end);
int pos = archivo.tellg();
int numReg = pos / SIZE;
int buscado;
cout << "Código a buscar: ";
cin >> buscado;
int ini = 0, fin = numReg ‐ 1, mitad;
bool encontrado = false;
while ((ini <= fin) && !encontrado) {
mitad = (ini + fin) / 2;
archivo.seekg(mitad * SIZE, ios::beg);
archivo.read( (char *) ®istro, SIZE);
if (buscado == registro.codigo) {
encontrado = true;
}
Luis Hernández Yáñez
else if (buscado < registro.codigo) {
fin = mitad ‐ 1;
}
...
return 0;
Luis Hernández Yáñez
...
insertar.cpp
void mostrar();
int main() {
mostrar();
tRegistro nuevoRegistro = nuevo(), registro;
fstream archivo;
archivo.open(BD, ios::in | ios::out | ios::binary);
Luis Hernández Yáñez
archivo.seekg(0, ios::end);
int pos = archivo.tellg();
int numReg = pos / SIZE;
...
Fundamentos de programación: Archivos binarios Página 1088
pos = 0;
bool encontrado = false;
archivo.seekg(0, ios::beg);
while ((pos < numReg) && !encontrado) {
archivo.read( (char *) ®istro, SIZE);
if (registro.codigo > nuevoRegistro.codigo) {
encontrado = true;
}
else {
pos++;
}
}
if (pos == numReg) { // Debe ir al final
archivo.seekg(0, ios::end);
archivo.write( (char *) &nuevoRegistro, SIZE);
Luis Hernández Yáñez
}
...
else { // Hay que hacer hueco
for (int i = numReg ‐ 1; i >= pos; i‐‐) {
archivo.seekg(i * SIZE, ios::beg);
archivo.read( (char *) ®istro, SIZE);
archivo.seekg((i + 1) * SIZE, ios::beg);
archivo.write( (char *) ®istro, SIZE);
}
archivo.seekg(pos * SIZE, ios::beg);
archivo.write( (char *) &nuevoRegistro, SIZE);
}
archivo.close();
mostrar(); nuevoRegistro
return 0;
Luis Hernández Yáñez
Por el medio
Luis Hernández Yáñez
Al final
tabla.cpp
tabla.registros[tabla.cont] = registro;
tabla.cont++;
}
archivo.close();
}
}
Fundamentos de programación: Archivos binarios Página 1092
tabla.cpp
bd.cpp
#include <iostream>
using namespace std;
#include "registro.h"
#include "tabla.h"
int main() {
tTabla tabla;
tTabla ok;
cargar(tabla, ok);
if (!ok) {
cout << "Error al abrir el archivo!" << endl;
}
else {
mostrar(tabla);
insertar(tabla, nuevo(), ok);
mostrar(tabla);
Luis Hernández Yáñez
guardar(tabla);
}
return 0;
}
Reconocimiento (Attribution):
En cualquier explotación de la obra autorizada por la licencia
hará falta reconocer la autoría.
No comercial (Non commercial):
La explotación de la obra queda limitada a usos no comerciales.
Compartir igual (Share alike):
La explotación autorizada incluye la creación de obras derivadas
siempre que mantengan la misma licencia al ser divulgadas.
Luis Hernández Yáñez