Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO Pensar en C++ (Volumen 1) - Grupo ARCO
✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 56 — #94 ✐ Capítulo 2. Construir y usar objetos Una de las cosas agradables de poner el fichero entero en una cadena es que la clase string proporciona funciones para la búsqueda y manipulación que le permiten modificar el fichero como si fuera una simple línea. Sin embargo, tiene sus limitaciones. Por un lado, a menudo, es conveniente tratar un fichero como una colección de líneas en vez de un gran bloque de texto. Por ejemplo, si quiere añadir numeración de líneas es mucho más fácil si tiene un objeto string distinto para cada línea. Para realizarlo, necesitamos otro concepto. 2.7. Introducción a los vectores Con cadenas, podemos rellenar un objeto string sin saber cuanta memoria se va a necesitar. El problema de introducir líneas de un fichero en objetos string es que se sabe cuántas cadenas habrá - solamente lo sabemos cuando ya hemos leido el fichero entero. Para resolver este problema necesitamos un nuevo tipo de datos que pueda crecer automáticamente para contener las cadenas que le vayamos introduciendo. De hecho, ¿por qué limitarnos a manejar objetos string Parece que este tipo de problema - no saber la cantidad de cosas a manejar mientras está escribiendo el problema - ocurre a menudo. Y este objeto «contenedor» podría resultar más útil si pudiera manejar cualquier clase de objeto. Afortunadamente, la Librería Estándar de C++ tiene una solución: las clases contenedor (container). Las clases contenedor son uno de los puntos fuertes del Estándar C++. A menudo existe un poco de confusión entre los contenedores y los algoritmos en la librería Estándar de C++, y la STL. La Standard Template Library fue el nombre que usó Alex Stepanov (que en aquella época estaba trabajando en Hewlett-Packard) cuando presentó su librería al Comité del Estándar C++ en el encuentro en San Diego, California, en la primavera de 1994. El nombre sobrevivió, especialmente después de que HP decidiera dejarlo disponible para la descarga pública. Posteriormente el comité integró las STL en la Librería Estándar de C++ haciendo un gran número de cambios. El desarrollo de las STL continúa en Silicon Graphics (SGI; ver www.sgi.com/Technology/STL). Las SGI STL divergen de la Librería Estándar de C++ en muchos detalles sutiles. Aunque es una creencia ampliamente generalizada, el C++ Estándar no "incluye" las STL. Puede ser confuso debido a que los contenedores y los algoritmos en el C++ Estándar tienen la misma raíz (y a menudo el mismo nombre) que en el SGI STL. En este libro, intentaré decir «la librería Estándar de C++» o «Librería Estándar de contenedores», o algo similar y eludiré usar el término STL. A pesar de que la implementación de los contenedores y algoritmos de la Librería Estándar de C++ usa algunos conceptos avanzados, que se cubren ampliamente en dos largos capítulos en el segundo volumen de este libro, esta librería también puede ser potente sin saber mucho sobre ella. Es tan útil que el más básico de los contenedores estándar, el vector, se introduce en este capítulo y se usará a lo largo de todo el libro. Verá que puede hacer muchas cosas con el vector y no saber cómo está implementado (de nuevo, uno de los objetivos de la POO). Los programas que usan vector en estos primeros capítulos del libro no son exactamente como los haría un programador experimentado, como comprobará en el volumen 2. Aún así, encontrará que en la mayoría de los casos el uso que se hace es adecuado. La clase vector es una plantilla, lo que significa que se puede aplicar a tipos de datos diferentes. Es decir, se puede crear un vector de figuras, un vector de gatos, un vector de strings, etc. Básicamente, con una plantilla se puede crear un vector de «cualquier clase». Para decirle al compilador con qué clase trabajará 56 ✐ ✐ ✐ ✐
✐ ✐ ✐ “Volumen1” — 2012/1/12 — 13:52 — page 57 — #95 ✐ 2.7. Introducción a los vectores (en este caso que va a manejar el vector), hay que poner el nombre del tipo deseado entre «llaves angulares». Por lo que un vector de string se denota como vector. Con eso, se crea un vector a medida que solamente contendrá objetos string, y recibirá un mensaje de error del compilador si intenta poner otra cosa en él. Como el vector expresa el concepto de «contenedor», debe existir una manera de meter cosas en él y sacar cosas de él. Para añadir un nuevo elemento al final del vector, se una el método push_back(). Recuerde que, como es un método, hay que usar un ’.’ para invocarlo desde un objeto particular. La razón de que el nombre de la función parezca un poco verboso - push_back() en vez de algo más simple como put - es porque existen otros contenedores y otros métodos para poner nuevos elementos en los contenedores. Por ejemplo, hay un insert() para poner algo en medio de un contenedor. vector la soporta pero su uso es más complicado y no necesitamos explorarla hasta el segundo volumen del libro. También hay un push- _front() (que no es parte de vector) para poner cosas al principio. Hay muchas más funciones miembro en vector y muchos más contenedores en la Librería Estándar, pero le sorprenderá ver la de cosas que se pueden hacer con sólo un par de características básicas. Así que se pueden introducir elementos en un vector con push_back() pero ¿cómo puede sacar esos elementos La solución es inteligente y elegante: se usa la sobrecarga de operadores para que el vector se parezca a un array. El array (que será descrito de forma más completa en el siguiente capítulo) es un tipo de datos que está disponible prácticamente en cualquier lenguaje de programación por lo que debería estar familiarizado con él. Los arrays son agregados lo que significa que consisten en un número de elementos agrupados. La característica distintiva de un array es que estos elementos tienen el mismo tamaño y están organizados uno junto a otro. Y todavía más importante, que se pueden seleccionar mediante un índice, lo que significa que puede decir: «Quiero el elemento número n» y el elemento será producido, normalmente de forma rápida. A pesar de que existen excepciones en los lenguajes de programación, normalmente se indica la «indexación» mediante corchetes, de tal forma que si se tiene un array a y quiere obtener el quinto elemento, sólo tiene que escribir a[4] (fíjese en que la indexación siempre empieza en cero). Esta forma compacta y poderosa de notación indexada se ha incorporado al vector mediante la sobrecarga de operadores como el > de los iostreams. De nuevo, no hay que saber cómo se ha implementado la sobrecarga de operadores - lo dejamos para un capítulo posterior - pero es útil que sea consciente que hay algo de magia detrás de todo esto para conseguir que los corchetes funcionen con el vector. Con todo esto en mente, ya puede ver un programa que usa la clase vector. Para usar un vector, hay que incluir el fichero de cabecera : //: C02:Fillvector.cpp // Copy an entire file into a vector of string #include #include #include #include using namespace std; int main() { vector v; ifstream in("Fillvector.cpp"); string line; 57 ✐ ✐ ✐ ✐
- Page 43 and 44: ✐ ✐ ✐ “Volumen1” — 2012
- Page 45 and 46: ✐ ✐ ✐ “Volumen1” — 2012
- Page 47 and 48: ✐ ✐ ✐ “Volumen1” — 2012
- Page 49 and 50: ✐ ✐ ✐ “Volumen1” — 2012
- Page 51 and 52: ✐ ✐ ✐ “Volumen1” — 2012
- Page 53 and 54: ✐ ✐ ✐ “Volumen1” — 2012
- Page 55 and 56: ✐ ✐ ✐ “Volumen1” — 2012
- Page 57 and 58: ✐ ✐ ✐ “Volumen1” — 2012
- Page 59 and 60: ✐ ✐ ✐ “Volumen1” — 2012
- Page 61 and 62: ✐ ✐ ✐ “Volumen1” — 2012
- Page 63 and 64: ✐ ✐ ✐ “Volumen1” — 2012
- Page 65 and 66: ✐ ✐ ✐ “Volumen1” — 2012
- Page 67 and 68: ✐ ✐ ✐ “Volumen1” — 2012
- Page 69 and 70: ✐ ✐ ✐ “Volumen1” — 2012
- Page 71 and 72: ✐ ✐ ✐ “Volumen1” — 2012
- Page 73 and 74: ✐ ✐ ✐ “Volumen1” — 2012
- Page 75 and 76: ✐ ✐ ✐ “Volumen1” — 2012
- Page 77 and 78: ✐ ✐ ✐ “Volumen1” — 2012
- Page 79 and 80: ✐ ✐ ✐ “Volumen1” — 2012
- Page 81 and 82: ✐ ✐ ✐ “Volumen1” — 2012
- Page 83 and 84: ✐ ✐ ✐ “Volumen1” — 2012
- Page 85 and 86: ✐ ✐ ✐ “Volumen1” — 2012
- Page 87 and 88: ✐ ✐ ✐ “Volumen1” — 2012
- Page 89 and 90: ✐ ✐ ✐ “Volumen1” — 2012
- Page 91 and 92: ✐ ✐ ✐ “Volumen1” — 2012
- Page 93: ✐ ✐ ✐ “Volumen1” — 2012
- Page 97 and 98: ✐ ✐ ✐ “Volumen1” — 2012
- Page 99 and 100: ✐ ✐ ✐ “Volumen1” — 2012
- Page 101 and 102: ✐ ✐ ✐ “Volumen1” — 2012
- Page 103 and 104: ✐ ✐ ✐ “Volumen1” — 2012
- Page 105 and 106: ✐ ✐ ✐ “Volumen1” — 2012
- Page 107 and 108: ✐ ✐ ✐ “Volumen1” — 2012
- Page 109 and 110: ✐ ✐ ✐ “Volumen1” — 2012
- Page 111 and 112: ✐ ✐ ✐ “Volumen1” — 2012
- Page 113 and 114: ✐ ✐ ✐ “Volumen1” — 2012
- Page 115 and 116: ✐ ✐ ✐ “Volumen1” — 2012
- Page 117 and 118: ✐ ✐ ✐ “Volumen1” — 2012
- Page 119 and 120: ✐ ✐ ✐ “Volumen1” — 2012
- Page 121 and 122: ✐ ✐ ✐ “Volumen1” — 2012
- Page 123 and 124: ✐ ✐ ✐ “Volumen1” — 2012
- Page 125 and 126: ✐ ✐ ✐ “Volumen1” — 2012
- Page 127 and 128: ✐ ✐ ✐ “Volumen1” — 2012
- Page 129 and 130: ✐ ✐ ✐ “Volumen1” — 2012
- Page 131 and 132: ✐ ✐ ✐ “Volumen1” — 2012
- Page 133 and 134: ✐ ✐ ✐ “Volumen1” — 2012
- Page 135 and 136: ✐ ✐ ✐ “Volumen1” — 2012
- Page 137 and 138: ✐ ✐ ✐ “Volumen1” — 2012
- Page 139 and 140: ✐ ✐ ✐ “Volumen1” — 2012
- Page 141 and 142: ✐ ✐ ✐ “Volumen1” — 2012
- Page 143 and 144: ✐ ✐ ✐ “Volumen1” — 2012
✐<br />
✐<br />
✐<br />
“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 56 — #94<br />
✐<br />
Capítulo 2. Construir y usar objetos<br />
Una de las cosas agradables de poner el fichero <strong>en</strong>tero <strong>en</strong> una cad<strong>en</strong>a es que la<br />
clase string proporciona funciones para la búsqueda y manipulación que le permit<strong>en</strong><br />
modificar el fichero como si fuera una simple línea. Sin embargo, ti<strong>en</strong>e sus<br />
limitaciones. Por un lado, a m<strong>en</strong>udo, es conv<strong>en</strong>i<strong>en</strong>te tratar un fichero como una colección<br />
de líneas <strong>en</strong> vez de un gran bloque de texto. Por ejemplo, si quiere añadir<br />
numeración de líneas es mucho más fácil si ti<strong>en</strong>e un objeto string distinto para<br />
cada línea. Para realizarlo, necesitamos otro concepto.<br />
2.7. Introducción a los vectores<br />
Con cad<strong>en</strong>as, podemos rell<strong>en</strong>ar un objeto string sin saber cuanta memoria se<br />
va a necesitar. El problema de introducir líneas de un fichero <strong>en</strong> objetos string<br />
es que se sabe cuántas cad<strong>en</strong>as habrá - solam<strong>en</strong>te lo sabemos cuando ya hemos<br />
leido el fichero <strong>en</strong>tero. Para resolver este problema necesitamos un nuevo tipo de<br />
datos que pueda crecer automáticam<strong>en</strong>te para cont<strong>en</strong>er las cad<strong>en</strong>as que le vayamos<br />
introduci<strong>en</strong>do.<br />
De hecho, ¿por qué limitarnos a manejar objetos string Parece que este tipo<br />
de problema - no saber la cantidad de cosas a manejar mi<strong>en</strong>tras está escribi<strong>en</strong>do el<br />
problema - ocurre a m<strong>en</strong>udo. Y este objeto «cont<strong>en</strong>edor» podría resultar más útil si<br />
pudiera manejar cualquier clase de objeto. Afortunadam<strong>en</strong>te, la Librería Estándar de<br />
<strong>C++</strong> ti<strong>en</strong>e una solución: las clases cont<strong>en</strong>edor (container). Las clases cont<strong>en</strong>edor son<br />
uno de los puntos fuertes del Estándar <strong>C++</strong>.<br />
A m<strong>en</strong>udo existe un poco de confusión <strong>en</strong>tre los cont<strong>en</strong>edores y los algoritmos<br />
<strong>en</strong> la librería Estándar de <strong>C++</strong>, y la STL. La Standard Template Library fue el nombre<br />
que usó Alex Stepanov (que <strong>en</strong> aquella época estaba trabajando <strong>en</strong> Hewlett-Packard)<br />
cuando pres<strong>en</strong>tó su librería al Comité del Estándar <strong>C++</strong> <strong>en</strong> el <strong>en</strong>cu<strong>en</strong>tro <strong>en</strong> San Diego,<br />
California, <strong>en</strong> la primavera de 1994. El nombre sobrevivió, especialm<strong>en</strong>te después<br />
de que HP decidiera dejarlo disponible para la descarga pública. Posteriorm<strong>en</strong>te<br />
el comité integró las STL <strong>en</strong> la Librería Estándar de <strong>C++</strong> haci<strong>en</strong>do un gran<br />
número de cambios. El desarrollo de las STL continúa <strong>en</strong> Silicon Graphics (SGI; ver<br />
www.sgi.com/Technology/STL). Las SGI STL diverg<strong>en</strong> de la Librería Estándar de<br />
<strong>C++</strong> <strong>en</strong> muchos detalles sutiles. Aunque es una cre<strong>en</strong>cia ampliam<strong>en</strong>te g<strong>en</strong>eralizada,<br />
el <strong>C++</strong> Estándar no "incluye" las STL. Puede ser confuso debido a que los cont<strong>en</strong>edores<br />
y los algoritmos <strong>en</strong> el <strong>C++</strong> Estándar ti<strong>en</strong><strong>en</strong> la misma raíz (y a m<strong>en</strong>udo el mismo<br />
nombre) que <strong>en</strong> el SGI STL. En este libro, int<strong>en</strong>taré decir «la librería Estándar de<br />
<strong>C++</strong>» o «Librería Estándar de cont<strong>en</strong>edores», o algo similar y eludiré usar el término<br />
STL.<br />
A pesar de que la implem<strong>en</strong>tación de los cont<strong>en</strong>edores y algoritmos de la Librería<br />
Estándar de <strong>C++</strong> usa algunos conceptos avanzados, que se cubr<strong>en</strong> ampliam<strong>en</strong>te<br />
<strong>en</strong> dos largos capítulos <strong>en</strong> el segundo volum<strong>en</strong> de este libro, esta librería también<br />
puede ser pot<strong>en</strong>te sin saber mucho sobre ella. Es tan útil que el más básico de los<br />
cont<strong>en</strong>edores estándar, el vector, se introduce <strong>en</strong> este capítulo y se usará a lo largo<br />
de todo el libro. Verá que puede hacer muchas cosas con el vector y no saber cómo<br />
está implem<strong>en</strong>tado (de nuevo, uno de los objetivos de la POO). Los programas<br />
que usan vector <strong>en</strong> estos primeros capítulos del libro no son exactam<strong>en</strong>te como los<br />
haría un programador experim<strong>en</strong>tado, como comprobará <strong>en</strong> el volum<strong>en</strong> 2. Aún así,<br />
<strong>en</strong>contrará que <strong>en</strong> la mayoría de los casos el uso que se hace es adecuado.<br />
La clase vector es una plantilla, lo que significa que se puede aplicar a tipos de<br />
datos difer<strong>en</strong>tes. Es decir, se puede crear un vector de figuras, un vector de<br />
gatos, un vector de strings, etc. Básicam<strong>en</strong>te, con una plantilla se puede crear<br />
un vector de «cualquier clase». Para decirle al compilador con qué clase trabajará<br />
56<br />
✐<br />
✐<br />
✐<br />
✐