Source

PensarEnC++ / V2-C03.xml

The branch 'PensarEnC++' does not exist.
Full commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
<?xml version="1.0" encoding="UTF-8"?>
<!-- -*- sgml -*- -->
<!--
  Editor:              Emacs 21/PSGML
  Traducción original: Ferran Ferri
  Formateado DocBook:

  Documento original: http://arco.inf-cr.uclm.es/~david.villa/pensar_en_C++/TICv2/html/TicV2.html#_Toc53985657
-->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">

<chapter
  xmlns:xi="http://www.w3.org/2001/XInclude"
  id="C3">

  <!-- Strings in depth -->
  <title>Las cadenas a fondo</title>

  <!--
  String processing with character arrays is one of the biggest
  time?wasters in C. Character arrays require the programmer to keep track
  of the difference between static quoted strings and arrays created on
  the stack and the heap, and the fact that sometimes you're passing
  around a char* and sometimes you must copy the whole array.
  -->

  <highlights>
    <para>
      El procesamiento de cadenas de caracteres en C es una de las
      mayores pérdidas de tiempo. Las cadenas de caracteres requieren
      que el programador tenga en cuenta las diferencias entre cadenas
      estáticas y las cadenas creadas en la pila y en el montón,
      además del hecho que a veces pasa como argumento un
      <type>char*</type> y a veces hay que copiar el arreglo entero.
    </para>
  </highlights>

  <!--
  Especially because string manipulation is so common, character arrays
  are a great source of misunderstandings and bugs. Despite this, creating
  string classes remained a common exercise for beginning C++ programmers
  for many years. The Standard C++ library string class solves the problem
  of character array manipulation once and for all, keeping track of
  memory even during assignments and copy-constructions. You simply don't
  need to think about it.
  -->

  <para>
    Precisamente porque la manipulación de cadenas es muy común, las
    cadenas de caracteres son una gran fuente de confusiones y
    errores. Es por ello que la creación de clases de cadenas sigue
    siendo desde hace años un ejercicio común para programadores
    novatos. La clase <classname>string</classname> de la biblioteca
    estándar de C++ resuelve el problema de la manipulación de
    caracteres de una vez por todas, gestionando la memoria incluso
    durante las asignaciones y las construcciones de
    copia. Simplemente no tiene que preocuparse por ello.
  </para>

  <!--
  This chapter[31] examines the Standard C++ string class, beginning with
  a look at what constitutes a C++ string and how the C++ version differs
  from a traditional C character array. You'll learn about operations and
  manipulations using string objects, and you'll see how C++ strings
  accommodate variation in character sets and string data conversion.
  -->

  <para>
    Este capítulo<footnote><para>Algunos materiales de este capítulo
    fueron creados originalmente por
    <author><firstname>Nancy</firstname> <surname>
    Nicolaisen</surname></author></para></footnote> examina la clase
    <classname>string</classname> del Estándar C++; empieza con un
    vistazo a la composición de las <classname>string</classname> de
    C++ y como la versión de C++ difiere del tradicional arreglo de
    caracteres de C. Aprenderá sobre las operaciones y la manipulación
    usando objetos <classname>string</classname>, y verá como éstas se
    FIXME[acomodan a la variación] de conjuntos de caracteres y
    conversión de datos.
  </para>

  <!--
  Handling text is one of the oldest programming applications, so it's
  not surprising that the C++ string draws heavily on the ideas and
  terminology that have long been used in C and other languages. As you
  begin to acquaint yourself with C++ strings, this fact should be
  reassuring. No matter which programming idiom you choose, there are
  three common things you want to do with a string:
  -->

  <para>
    Manipular texto es una de las aplicaciones más antiguas de la
    programación, por eso no resulta sorprendente que las
    <classname>string</classname> de C++ estén fuertemente inspiradas
    en las ideas y la terminología que ha usado continuamente en C y
    otros lenguajes. Conforme vaya aprendiendo sobre los
    <classname>string</classname> de C++, este hecho se debería ir
    viendo más claramente. Da igual el lenguaje de programación que
    escoja, hay tres cosas comunes que querrá hacer con las cadenas:
  </para>

  <!--
  · Create or modify the sequence of characters stored in the string.
  · Detect the presence or absence of elements within the string.
  · Translate between various schemes for representing string characters.
  -->

  <para>
    <itemizedlist>
      <listitem>
        <para>Crear o modificar secuencias de caracteres almacenados en una
        cadena</para>
      </listitem>
      <listitem>
        <para>Detectar la presencia o ausencia de elementos dentro de la
        cadena</para>
      </listitem>
      <listitem>
        <para>Traducir entre diversos esquemas para representar cadenas de
	  caracteres</para>
      </listitem>
    </itemizedlist>
  </para>

  <!--
  You'll see how each of these jobs is accomplished using C++ string
  objects.
  -->

  <para>
    Verá como cada una de estas tareas se resuelve usando objetos
    <classname>string</classname> en C++.
  </para>

  <sect1>
    <!-- : What's in a string? -->
    <title>¿Qué es un <classname>string</classname>?</title>

    <!--
    In C, a string is simply an array of characters that always includes a
    binary zero (often called the null terminator) as its final array
    element. There are significant differences between C++ strings and their
    C progenitors. First, and most important, C++ strings hide the physical
    representation of the sequence of characters they contain. You don't
    need to be concerned about array dimensions or null terminators. A
    string also contains certain ??housekeeping?? information about the size
    and storage location of its data. Specifically, a C++ string object
    knows its starting location in memory, its content, its length in
    characters, and the length in characters to which it can grow before the
    string object must resize its internal data buffer. C++ strings thus
    greatly reduce the likelihood of making three of the most common and
    destructive C programming errors: overwriting array bounds, trying to
    access arrays through uninitialized or incorrectly valued pointers, and
    leaving pointers ??dangling?? after an array ceases to occupy the
    storage that was once allocated to it.
    -->

    <para>
      En C, una cadena es simplemente un arreglo de caracteres que
      siempre incluye un 0 binario (frecuentemente llamado terminador
      nulo) como elemento final del arreglo. Existen diferencias
      significativas entre los <classname>string</classname> de C++ y
      sus progenitoras en C. Primero, y más importante, los
      <classname>string</classname> de C++ esconden la implementación
      física de la secuencia de caracteres que contiene. No debe
      preocuparse de las dimensiones del arreglo o del terminador
      nulo. Un <classname>string</classname> también contiene cierta
      información para uso interno sobre el tamaño y la localización
      en memoria de los datos.  Específicamente, un objeto
      <classname>string</classname> de C++ conoce su localización en
      memoria, su contenido, su longitud en caracteres, y la cantidad
      de caracteres que puede crecer antes de que el objeto
      <classname>string</classname> deba redimensionar su buffer
      interno de datos.  Las <classname>string</classname> de C++, por
      tanto, reducen enormemente las probabilidades de cometer uno de
      los tres errores de programación en C más comunes y
      destructivos: sobrescribir los límites del arreglo, intentar
      acceder a un arreglo no inicializado o con valores de puntero
      incorrectos, y dejar punteros colgando después de que el arreglo
      deje de ocupar el espacio que estaba ocupando.
    </para>


<!-- Revisando: David Villa -->

    <!--
    The exact implementation of memory layout for the string class
    is not defined by the C++ Standard. This architecture is intended to
    be flexible enough to allow differing implementations by compiler
    vendors, yet guarantee predictable behavior for users. In
    particular, the exact conditions under which storage is allocated to
    hold data for a string object are not defined. String allocation
    rules were formulated to allow but not require a reference-counted
    implementation, but whether or not the implementation uses reference
    counting, the semantics must be the same. To put this a bit
    differently, in C, every char array occupies a unique physical
    region of memory. In C++, individual string objects may or may not
    occupy unique physical regions of memory, but if reference counting
    avoids storing duplicate copies of data, the individual objects must
    look and act as though they exclusively own unique regions of
    storage. For example: -->

    <para>
      La implementación exacta del esquema en memoria para una clase
      string no esta definida en el estándar C++. Esta arquitectura
      esta pensada para ser suficientemente flexible para permitir
      diferentes implementaciones de los fabricantes de compiladores,
      garantizando igualmente un comportamiento predecible por los
      usuarios. En particular, las condiciones exactas de cómo situar
      el almacenamiento para alojar los datos para un objeto
      <classname>string</classname> no están definidas. FIXME: Las
      reglas de alojamiento de un <classname>string</classname> fueron
      formuladas para permitir, pero no requerir, una implementación
      con referencias múltiples, pero dependiendo de la implementación
      usar referencias múltiples sin variar la semántica. Por decirlo
      de otra manera, en C, todos los arreglos de char ocupan una
      única región física de memoria. En C++, los objetos
      <classname>string</classname> individuales pueden o no ocupar
      regiones físicas únicas de memoria, pero si su conjunto de
      referencias evita almacenar copias duplicadas de datos, los
      objetos individuales deben parecer y actuar como si tuvieran sus
      propias regiones únicas de almacenamiento.
    </para>


//: V2C03:StringStorage.h


    <!-- We say that an implementation that only makes unique
    copies when a string is modified uses a copy-on-write strategy. This
    approach saves time and space when strings are used only as value
    parameters or in other read-only situations. -->

    <para>
      Decimos que cuando una implementación  solo hace una sola copia
      al modificar el  <classname>string</classname> usa una
      estrategia de copiar  al escribir.  Esta  aproximación ahorra
      tiempo y  espacio cuando  usamos <classname>string</classname>
      como  parámetros por valor o en otras situaciones de solo
      lectura.
    </para>

    <!-- Whether a library implementation uses reference counting or not
    should be transparent to users of the string class. Unfortunately,
    this is not always the case. In multithreaded programs, it is
    practically impossible to use a reference-counting implementation
    safely.[32] -->

    <para>
      El uso de referencias múltiples en la implementación de una
      librería debería ser transparente al usuario de la clase
      string. Desgraciadamente, esto no es siempre el caso. En
      programas multihilo, es prácticamente imposible usar
      implementaciones con múltiples referencias de forma
      segura[32].<footnote> <para>Es dificil hacer implementaciones
      con multiples referencias para trabajar de manera segura en
      multihilo. (Ver <citation>More Exceptional C++,
      pp.104-14</citation>). Ver Capitulo 10 para más información
      sobre multiples hilos</para> </footnote>
    </para>
  </sect1>

  <sect1>
    <!-- : Operating on strings -->
    <title>Operaciones con cadenas</title>

    <!--
    If you've programmed in C, you are accustomed to the family of
    functions that write, search, modify, and copy char arrays. There are
    two unfortunate aspects of the Standard C library functions for handling
    char arrays. First, there are two loosely organized families of them:
    the ??plain?? group, and the ones that require you to supply a count of
    the number of characters to be considered in the operation at hand. The
    roster of functions in the C char array library shocks the unsuspecting
    user with a long list of cryptic, mostly unpronounceable names. Although
    the type and number of arguments to the functions are somewhat
    consistent, to use them properly you must be attentive to details of
    function naming and parameter passing.
    -->

    <para>
      Si ha programado en C, estará acostumbrado a la familia de
      funciones que leen, escriben, modifican y copian
      cadenas. Existen dos aspectos poco afortunados en la funciones
      de la librería estándar de C para manipular cadenas. Primero,
      hay dos familias pobremente organizadas: el grupo plano, y
      aquellos que requieren que se les suministre el número de
      caracteres para ser consideradas en la operación a mano. La
      lista de funciones en la librería de cadenas de C sorprende al
      usuario desprevenido con una larga lista de nombres crípticos y
      mayoritariamente impronunciables. Aunque el tipo y número de
      argumentos es algo consistente, para usarlas adecuadamente debe
      estar atento a los detalles de nombres de la función y a los
      parámetros que le pasas.
    </para>

    <!--
    The second inherent trap of the standard C char array tools is that they
    all rely explicitly on the assumption that the character array includes
    a null terminator. If by oversight or error the null is omitted or
    overwritten, there's little to keep the C char array functions from
    manipulating the memory beyond the limits of the allocated space,
    sometimes with disastrous results.
    -->

    <para>
      La segunda trampa inherente a las herramientas para cadenas del
      estándar de C es que todas ellas explícitamente confían en la
      asunción de que cada cadena incluye un terminador nulo. Si por
      confusión o error el terminador nulo es omitido o sobrescrito,
      poco se puede hacer para impedir que las funciones de cadena de
      C manipulen la memoria más allá de los límites del espacio de
      alojamiento, a veces con resultados desastrosos.
    </para>

    <!--
    C++ provides a vast improvement in the convenience and safety of string
    objects. For purposes of actual string handling operations, there are
    about the same number of distinct member function names in the string
    class as there are functions in the C library, but because of
    overloading the functionality is much greater. Coupled with sensible
    naming practices and the judicious use of default arguments, these
    features combine to make the string class much easier to use than the C
    library char array functions.
    -->

    <para>
      C++ aporta una vasta mejora en cuanto a conveniencia y seguridad
      de los objetos <classname>string</classname>. Para los
      propósitos de las actuales operaciones de manipulación, existe
      el mismo número de funciones que la librería de C, pero gracias
      a la sobrecarga, la funcionalidad es mucho mayor. Además, con
      una nomenclatura más sensata y un acertado uso de los argumentos
      por defecto, estas características se combinan para hacer de la
      clase <classname>string</classname> mucho más fácil de usar que
      la biblioteca de funciones de cadena de C.
    </para>
    <sect2>
      <!-- : Appending, inserting, and concatenating strings -->
      <title>Añadiendo, insertando y concatenando cadenas</title>

      <!--
      One of the most valuable and convenient aspects of C++ strings is that
      they grow as needed, without intervention on the part of the
      programmer. Not only does this make string-handling code inherently more
      trustworthy, it also almost entirely eliminates a tedious ??housekeeping??
      chore?keeping track of the bounds of the storage where your strings
      live. For example, if you create a string object and initialize it with
      a string of 50 copies of ??X', and later store in it 50 copies of
      ??Zowie??, the object itself will reallocate sufficient storage to
      accommodate the growth of the data. Perhaps nowhere is this property
      more appreciated than when the strings manipulated in your code change
      size and you don't know how big the change is. The string member
      functions append( ) and insert( ) transparently reallocate storage when
      a string grows:
      -->

      <para>
	Uno de los aspectos más valiosos y convenientes de los
	<classname>string</classname> en C++ es que crecen cuando lo
	necesitan, sin intervención por parte del programador. No solo
	hace el código de manejo del <classname>string</classname> sea
	inherentemente mas confiable, además elimina por completo las
	tediosas funciones "caseras" para controlar los limites del
	almacenamiento en donde nuestra cadena reside.  Por ejemplo,
	si	crea un objeto <classname>string</classname> e
	inicializa este	<classname>string</classname> con 50 copias de
	"X", y después	copia en el 50 copias de "Zowie", el objeto,
	por sí mismo,	readecua suficiente almacenamiento para
	acomodar el crecimiento	de los datos. Quizás en ningún otro
	lugar es más apreciada esta	propiedad que cuando las
	cadenas manipuladas por su	código	cambian de tamaño y no
	sabe cuan grande puede ser este	cambio. La función miembro
	<function>append()</function> e <function>insert()</function>
	de <classname>string</classname>	reubican de manera
	transparente el almacenamiento cuando un
	<classname>string</classname> crece:
      </para>


//: V2C03:StrSize.cpp


      <!-- Here is the output from one particular compiler: -->
      <para>
	Aquí la salida desde un compilador cualquiera:
      </para>

      <!--
      I saw Elvis in a UFO.
      Size = 22
      Capacity = 31
      I thought I saw Elvis in a UFO.
      Size = 32
      Capacity = 47
      I thought I saw Elvis in a UFO. I've been
      working too hard.
      Size = 59
      Capacity = 511
      -->

<screen>
I saw Elvis in a UFO.
Size = 22
Capacity = 31
I thought I saw Elvis in a UFO.
Size = 32
Capacity = 47
I thought I saw Elvis in a UFO. I've been
working too hard.
Size = 59
Capacity = 511
</screen>



      <!--
      This example demonstrates that even though you can safely relinquish
      much of the responsibility for allocating and managing the memory your
      strings occupy, C++ strings provide you with several tools to monitor
      and manage their size. Notice the ease with which we changed the size of
      the storage allocated to the string. The size( ) function returns the
      number of characters currently stored in the string and is identical to
      the length( ) member function. The capacity( ) function returns the size
      of the current underlying allocation, meaning the number of characters
      the string can hold without requesting more storage. The reserve( )
      function is an optimization mechanism that indicates your intention to
      specify a certain amount of storage for future use; capacity( ) always
      returns a value at least as large as the most recent call to reserve(
      ). A resize( ) function appends spaces if the new size is greater than
      the current string size or truncates the string otherwise. (An overload
      of resize( ) can specify a different character to append.)
      -->

      <para>
	Este ejemplo demuestra que aunque puede ignorar con seguridad
	muchas de las responsabilidades de reserva y gestión de la
	memoria que tus  <classname>string</classname> ocupan, C++
	provee a los <classname>string</classname> con varias
	herramientas para monitorizar y  gestionar su tamaño. Nótese
	la facilidad con la que hemos cambiado el tamaño de la memoria
	reservada para los <classname>string</classname>. La función
	<function>size()</function> retorna el numero de caracteres
	actualmente almacenados en el <classname>string</classname> y
	es idéntico a la función miembro
	<function>lenght()</function>. La función
	<function>capacity()</function> retorna el tamaño de la
	memoria subyacente actual, es decir, el número de caracteres
	que el <classname>string</classname> puede almacenar sin tener
	que reservar más memoria. La función
	<function>reserve()</function> es una optimización del
	mecanismo que indica su intención de especificar cierta
	cantidad de memoria para un futuro uso;
	<function>capacity()</function> siempre retorna un valor al
	menos tan largo como la ultima llamada a
	<function>reserve()</function>. La función
	<function>resize()</function> añade espacio si el nuevo tamaño
	es mayor que el tamaño actual del
	<classname>string</classname>; sino trunca el
	<classname>string</classname>. (Una sobrecarga de
	<function>resize()</function> puede especificar una adición
	diferente de caracteres).
      </para>

      <!--
      The exact fashion that the string member functions allocate space for
      your data depends on the implementation of the library. When we tested
      one implementation with the previous example, it appeared that
      reallocations occurred on even word (that is, full-integer) boundaries,
      with one byte held back. The architects of the string class have
      endeavored to make it possible to mix the use of C char arrays and C++
      string objects, so it is likely that figures reported by StrSize.cpp for
      capacity reflect that, in this particular implementation, a byte is set
      aside to easily accommodate the insertion of a null terminator.
      -->
      <para>
	La manera exacta en que las funciones miembro de
	<classname>string</classname> reservan espacio para sus datos
	depende de la implementación de la librería. Cuando testeamos
	una implementación con el ejemplo anterior, parece que se
	hacia una reserva de una palabra de memoria (esto es, un
	entero) dejando un byte en blanco entre cada una de ellas. Los
	arquitectos de la clase string se esforzaron para poder
	mezclar el uso de las cadenas de caracteres de C y los objetos
	<classname>string</classname>, por lo que es probable por lo
	que se puede observar en <emphasis>StrSize.cpp</emphasis>, en
	esta implementación en particular, el byte esté añadido para
	acomodar fácilmente la inserción de un terminador nulo.
      </para>

    </sect2>
    <sect2>
      <!-- : Replacing string characters -->
      <title>Reemplazar caracteres en cadenas </title>

      <!--
      The insert( ) function is particularly nice because it absolves you from
      making sure the insertion of characters in a string won't overrun the
      storage space or overwrite the characters immediately following the
      insertion point. Space grows, and existing characters politely move over
      to accommodate the new elements. Sometimes this might not be what you
      want. If you want the size of the string to remain unchanged, use the
      replace( ) function to overwrite characters. There are a number of
      overloaded versions of replace( ), but the simplest one takes three
      arguments: an integer indicating where to start in the string, an
      integer indicating how many characters to eliminate from the original
      string, and the replacement string (which can be a different number of
      characters than the eliminated quantity). Here's a simple example:
      -->
      <para>
	La función <function>insert()</function> es particularmente
	útil por que te evita el tener que estar seguro de que la
	inserción de caracteres en un <classname>string</classname> no
	sobrepasa el espacio reservado o sobrescribe los caracteres
	que inmediatamente siguientes al punto de inserción. El
	espacio crece y los caracteres existentes se mueven
	graciosamente para acomodar a los nuevos elementos. A veces,
	puede que no sea esto exactamente lo que quiere. Si quiere que
	el tamaño del <classname>string</classname> permanezca sin
	cambios, use la función <function>replace()</function> para
	sobrescribir los caracteres. Existe un número de versiones
	sobrecargadas de <function>replace()</function>, pero la más
	simple toma tres argumentos: un entero indicando donde empezar
	en el <classname>string</classname>, un entero indicando
	cuantos caracteres para eliminar del
	<classname>string</classname> original, y el
	<classname>string</classname> con el que reemplazaremos (que
	puede ser diferente en numero de caracteres que la cantidad
	eliminada). Aquí un ejemplo simple:
      </para>


//: V2C03:StringReplace.cpp


      <!--
      The tag is first inserted into s (notice that the insert happens before
      the value indicating the insert point and that an extra space was added
      after tag), and then it is found and replaced.
      -->
      <para>
	<varname>Tag</varname> es insertada en <varname>s</varname>
	(notese que la inserción ocurre <emphasis>antes</emphasis> de
	que el valor indicando el punto de inserción y de que el
	espacio extra haya sido añadido despues de
	<varname>Tag</varname>), y entonces es encontrada y
	reemplazada.
      </para>

      <!--
      You should check to see if you've found anything before you perform a
      replace( ). The previous example replaces with a char*, but there's an
      overloaded version that replaces with a string. Here's a more complete
      demonstration replace( ):
      -->
      <para>
	Debería cerciorarse de que ha encontrado algo antes de
	realizar el <function>replace()</function>. En los ejemplos
	anteriores se reemplaza con un <type>char*</type>, pero existe
	una versión sobrecargada que reemplaza con un
	<classname>string</classname>. Aqui hay un ejempl más completo
	de demostración de <function>replace()</function>:
      </para>


//: V2C03:Replace.cpp


      <!--
      If replace doesn't find the search string, it returns string::npos. The
      npos data member is a static constant member of the string class that
      represents a nonexistent character position.[33]
      -->
      <para>
	Si <function>replace()</function> no encuentra la cadena
	buscada, retorna un
	<classname>string::</classname><varname>npos</varname>. El
	dato miembro <varname>npos</varname> es una constante estatica
	de la clase <classname>string</classname> que representa una
	posición de carácter que no existe[33].
	<footnote>
	  <para>
	    Es una abrviación de <foreignphrase>"no
	    position"</foreignphrase>, y su valor más alto puede ser
	    representado por el ubicador de
	    <classname>string</classname> <varname>size_type</varname>
	    (<varname>std::size_t</varname> por defecto).
	  </para>
	</footnote>
      </para>

      <!--
      Unlike insert( ), replace( ) won't grow the string's storage space if
      you copy new characters into the middle of an existing series of array
      elements. However, it will grow the storage space if needed, for
      example, when you make a ??replacement?? that would expand the original
      string beyond the end of the current allocation. Here's an example:
      -->
      <para>
	A diferencia de <function>insert()</function>,
	<function>replace()</function> no aumentará el espacio de
	alamcenamiento de <classname>string</classname> si copia
	nuevos caracteres en el medio de una serie de elementos de
	array existentes. Sin embargo, sí que cerecerá su espacio si
	es necesario, por ejemplo, cuando hace un
	<emphasis>"reemplazamiento"</emphasis> que pueda expandir el
	<classname>string</classname> más allá del final de la memoria
	reservada actual. Aquí un ejemplo:
      </para>


//: V2C03:ReplaceAndGrow.cpp


      <!--
      The call to replace( ) begins ??replacing?? beyond the end of the
      existing array, which is equivalent to an append operation. Notice that
      in this example replace( ) expands the array accordingly.
      -->
      <para>
	La llamada a <function>replace()</function> empieza
	<emphasis>"reemplazando"</emphasis> más allá del final del
	array existente, que es equivalente a la operación
	<function>append()</function>. Nótese que en este ejemplo
	<function>replace()</function> expande el array
	coherentemente.
      </para>

      <!--
      You may have been hunting through this chapter trying to do something
      relatively simple such as replace all the instances of one character
      with a different character. Upon finding the previous material on
      replacing, you thought you found the answer, but then you started seeing
      groups of characters and counts and other things that looked a bit too
      complex. Doesn't string have a way to just replace one character with
      another everywhere?
      -->
      <para>
	Puede que haya estado buscando a través del capítulo;
	intentando hacer algo relativamente fácil como reemplazar
	todas las ocurrencias de un carácter con diferentes
	caracteres. Al buscar el material previo sobre reemplazar,
	puede que haya encontrado la respuesta, pero entonces ha
	empezaro viendo grupos de caracteres y contadores y otras
	cosas que parecen un poco demasiado complejas. ¿No tiene
	<classname>string</classname> una manera para reemplazar un
	carácter con otro simplemente?
      </para>

      <!--
      You can easily write such a function using the find( ) and replace( )
      member functions as follows:
      -->
      <para>
	Puede escribir fácilmente cada funcin usando las funciones
	miembro <function>find()</function> y
	<function>replace()</function> como se muestra acontinuacion.
      </para>

//: V2C03:ReplaceAll.h


//: V2C03:ReplaceAll.cpp {O}


      <!--
      The version of find( ) used here takes as a second argument the position
      to start looking in and returns string::npos if it doesn't find it. It
      is important to advance the position held in the variable lookHere past
      the replacement string, in case from is a substring of to. The following
      program tests the replaceAll function:
      -->
      <para>
	La versión de <function>find()</function> usada aquí toma como
	segundo argumento la posición donde empezar a buscar y retorna
	<classname>string::</classname><varname>npos</varname> si no
	lo encuentra. Es importante avanzar en la posición contenida
	por la variable <varname>lookHere</varname> pasada como
	subcadena, en caso de que <varname>from</varname> es una
	subcadena de <varname>to</varname>. El siguiente programa
	comprueba la funcion <function>replaceAll()</function>:
      </para>


//: V2C03:ReplaceAllTest.cpp


      <!--
      As you can see, the string class by itself doesn't solve all possible
      problems. Many solutions have been left to the algorithms in the
      Standard library[34] because the string class can look just like an STL
      sequence (by virtue of the iterators discussed earlier). All the generic
      algorithms work on a ??range?? of elements within a container. Usually
      that range is just ??from the beginning of the container to the end.?? A
      string object looks like a container of characters: to get the beginning
      of the range you use string::begin( ), and to get the end of the range
      you use string::end( ). The following example shows the use of the
      replace( ) algorithm to replace all the instances of the single
      character ??X' with ??Y':
      -->
      <para>
	Como puede comprobar, la clase <classname>string</classname>
	por ella sola no resuelve todos los posibles problemas. Muchas
	soluciones se han dejado en los algoritmos de la librería
	estándar<footnote><para> Descrito en profundidad en el
	Capítulo 6.</para></footnote> por que la clase
	<classname>string</classname> puede parece justamente como una
	secuencia STL(gracias a los iteradores descritos antes). Todos
	los algoritmos genéricos funcionan en un
	<emphasis>"rango"</emphasis> de elementos dentro de un
	contenedor. Generalmente este rango es justamente desde el
	principio del contenedor hasta el final. Un objeto
	<classname>string</classname> se parece a un contenedor de
	caracteres: para obtener el principio de este rango use
	<classname>string::</classname><function>begin()</function>, y
	para obtener el final del rango use
	<classname>string::</classname><function>end()</function>. El
	siguiente ejemplomuestra el uso del algoritmo
	<function>replace()</function> para reemplazar todas las
	instancias de un determinado carácter <emphasis>"X"</emphasis>
	con <emphasis>"Y"</emphasis>
      </para>


//: V2C03:StringCharReplace.cpp


      <!--
      Notice that this replace( ) is not called as a member function of
      string. Also, unlike the string::replace( ) functions that only perform
      one replacement, the replace( ) algorithm replaces all instances of one
      character with another.
      -->
      <para>
	Nótese que esta función <function>replace()</function> no es
	llamada como función miembro de
	<classname>string</classname>. Además, a diferencia de la
	función
	<classname>string::</classname><function>replace()</function>,
	que solo realiza un reemplazo, el algoritmo
	<function>replace()</function> reemplaza todas las instancias
	de un carácter con otro.
      </para>

      <!--
      The replace( ) algorithm only works with single objects (in this case,
      char objects) and will not replace quoted char arrays or string
      objects. Since a string behaves like an STL sequence, a number of other
      algorithms can be applied to it, which might solve other problems that
      are not directly addressed by the string member functions.
      -->
      <para>
	El algoritmo <function>replace()</function> solo funciona con
	objetos individuales (en este caso, objetos <type>char</type>)
	y no reemplazará arreglos constantes o objetos
	<classname>string</classname>. Desde que un
	<classname>string</classname> se copmporta como una secuencia
	STL, un conjunto de algoritmos pueden serle aplicados, que
	resolverán otros problemas que las funciones miembro de
	<classname>string</classname> no resuelven.
      </para>

    </sect2>
    <sect2>
      <!-- : Concatenation using nonmember overloaded operators -->
      <title>Concatenación usando operadores no-miembro sobrecargados</title>

      <!--
      One of the most delightful discoveries awaiting a C programmer learning
      about C++ string handling is how simply strings can be combined and
      appended using operator+ and operator+=. These operators make combining
      strings syntactically similar to adding numeric data:
      -->
      <para>
	Uno de los descubrimientos más deliciosos que esperan al
	programador de C que está aprendiendo sobre el manejo de
	cadenas en C++, es lo simple que es combinar y añadir
	<classname>string</classname> usando los operadores
	<function>operator+</function> y
	<function>operator+=</function>. Estos operadores hacen
	combinaciones de cadenas sintacticamente parecidas a la suma
	de datos numéricos:
      </para>


//: V2C03:AddStrings.cpp


      <!--
      Using the operator+ and operator+= operators is a flexible and
      convenient way to combine string data. On the right side of the
      statement, you can use almost any type that evaluates to a group of one
      or more characters.
      -->
      <para>
	Usar los operadores <function>operator+</function> y
	<function>operator+=</function> es una manera flexible y
	conveniente de combinar los datos de las cadenas. En la parte
	derecha de la sentencia, puede usar casi cualquier tipo que
	evalúe a un grupo de uno o más caracteres.
      </para>

    </sect2>
  </sect1>
  <sect1>
    <!-- : Searching in strings -->
    <title>Buscar en cadenas</title>

    <!--
    The find family of string member functions locates a character or group
    of characters within a given string. Here are the members of the find
    family and their general usage :
    -->
    <para>
      La familia de funciones miembro de <classname>string</classname>
      <function>find</function> localiza un carácter o grupo de
      caracteres en una cadena dada. Aquí los miembros de la familia
      <function>find()</function> y su uso general:
    </para>

    <!-- Esto hay que meterlo en una tabla-->
	<!-- string find member function -->
    <para>
      Función miembro de búsqueda en un <classname>string</classname>
    </para>

    <!-- What/how it finds -->
    <para>
      ¿Qué/Cómo lo encuentra?
    </para>

    <!-- find( ) -->
    <para>
      <function>find()</function>
    </para>

    <!--
    TBD: Aqui se mete una tabla???? Parece lo correcto
    -->
    <!--
    Searches a string for a specified character or group of characters and
    returns the starting position of the first occurrence found or npos if
    no match is found.
    -->
    <para>
      Busca en un <classname>string</classname> un carácter
      determinado o un grupo de caracteres y retorna la posición de
      inicio de la primera ocurrencia o <varname>npos</varname> si ha
      sido encontrado.
    </para>

    <!-- find_first_of( ) -->
    <para>
      <function>find_first_of()</function>
    </para>

    <!--
    Searches a target string and returns the position of the first match of
    any character in a specified group. If no match is found, it returns
    npos.
    -->
    <para>
      Busca en un <classname>string</classname> y retorna la posición
      de la primera ocurrencia de cualquier carácter en un grupo
      especifico. Si no encuentra ocurrencias, retorna
      <varname>npos</varname>.
    </para>

    <!-- find_last_of( ) -->
    <para>
      <function>find_last_of()</function>
    </para>

    <!--
    Searches a target string and returns the position of the last match of
    any character in a specified group. If no match is found, it returns
    npos.
    -->
    <para>
      Busca en un <classname>string</classname> y retorna la posición
      de la última ocurrencia de cualquier carácter en un grupo
      específico. Si no encuentra ocurrencias, retorna
      <varname>npos</varname>.
    </para>

    <!-- find_first_not_of( ) -->
    <para>
      <function>find_first_not_of( )</function>
    </para>

    <!--
    Searches a target string and returns the position of the first element
    that doesn't match any character in a specified group. If no such
    element is found, it returns npos.
    -->
    <para>
      Busca en un <classname>string</classname> y retorna la posición
      de la primera ocurrencia que no pertenece a un grupo
      específico. Si no encontramos ningún elemento, retorna un
      <varname>npos</varname>
    </para>

    <!-- find_last_not_of( ) -->
    <para>
      <function>find_last_not_of( )</function>
    </para>

    <!--
    Searches a target string and returns the position of the element with
    the largest subscript that doesn't match any character in a specified
    group. If no such element is found, it returns npos.
    -->
    <para>
      Busca en un <classname>string</classname> y retorna la posición
      del elemento con el indice mayor que no pertenece a un grupo
      específico. Si no encontramos ningún elemento, retorna un
      <varname>npos</varname>
    </para>

    <!-- rfind( ) -->
    <para>
      <function>rfind()</function>
    </para>

    <!--
    Searches a string from end to beginning for a specified character or
    group of characters and returns the starting position of the match if
    one is found. If no match is found, it returns npos.
    -->
    <para>
      Busca en un <classname>string</classname>, desde el final hasta
      el origen, un carácter o grupo de caracteres y retorna la
      posición inicial de la ocurrencia si se ha encontrado alguna. Si
      no encuentra ocurrencias, retorna <varname>npos</varname>.
    </para>

    <!--
    The simplest use of find( ) searches for one or more characters in a
    string. This overloaded version of find( ) takes a parameter that
    specifies the character(s) for which to search and optionally a
    parameter that tells it where in the string to begin searching for the
    occurrence of a substring. (The default position at which to begin
    searching is 0.) By setting the call to find inside a loop, you can
    easily move through a string, repeating a search to find all the
    occurrences of a given character or group of characters within the
    string.
    -->
    <para>
      El uso más simple de <function>find()</function>, busca uno o
      más caracteres en un <classname>string</classname>. La versión
      sobrecargada de <function>find()</function> toma un parámetro
      que especifica el/los carácter(es) que buscar y opcionalmente un
      parámetro que dice donde empezar a buscar en el
      <classname>string</classname> la primera ocurrencia. (Por
      defecto la posición de incio es 0). Insertando la llamada a la
      función <function>find()</function> dentro de un bucle puede
      buscar fácilmente todas las ocurrencias de un carácter dado o un
      grupo de caracteres dentro de un <classname>string</classname>.
    </para>

    <!--
    The following program uses the method of The Sieve of Eratosthenes to
    find prime numbers less than 50. This method starts with the number 2,
    marks all subsequent multiples of 2 as not prime, and repeats the
    process for the next prime candidate. The SieveTest constructor
    initializes sieveChars by setting the initial size of the character
    array and writing the value ??P' to each of its members.
    -->
    <para>
      El siguiente programa usa el método del Tamiz de Eratostenes
      para hallar los números primos menores de 50. Este método
      empieza con el número 2, marca todos los subsecuentes múltiplos
      de 2 ya que no son primos, y repite el proceso para el siguiente
      candidato a primo. El constructor de sieveTest inicializa
      sieveChars poniendo el tamaño inicial del arreglo de carácter y
      escribiendo el valor <emphasis>'P'</emphasis> para cada miembro.
    </para>


//: V2C03:Sieve.h


//: V2C03:Sieve.cpp


    <!--
    The find( ) function can walk forward through a string, detecting
    multiple occurrences of a character or a group of characters, and
    find_first_not_of( ) finds other characters or substrings.
    -->
    <para>
      La función <function>find()</function> puede recorrer el
      <classname>string</classname>, detectando múltiples ocurrencias
      de un carácter o un grupo de caracteres, y
      <function>find_first_not_of()</function> encuentra otros
      caracteres o subcadenas.
    </para>

    <!--
    There are no functions in the string class to change the case of a
    string, but you can easily create these functions using the Standard C
    library functions toupper( ) and tolower( ), which change the case of
    one character at a time. The following example illustrates a
    case-insensitive search:
    -->
    <para>
      No existen funciones en la clase <classname>string</classname>
      para cambiar entre mayúsculas/minúsculas en una cadena, pero
      puede crear esa función fácilmente usando la función de la
      libreria estándar de C <function>toupper()</function> y
      <function>tolower()</function>, que cambian los caracteres entre
      mayúsculas/minúsculas de uno en uno. El ejemplo siguiente
      ilustra una búsqueda sensible a mayúsculas/minúsculas.
    </para>


//: V2C03:Find.h


//: V2C03:Find.cpp


    <!--
    Both the upperCase( ) and lowerCase( ) functions follow the same form:
    they make a copy of the argument string and change the case. The
    Find.cpp program isn't the best solution to the case-sensitivity
    problem, so we'll revisit it when we examine string comparisons.
    -->
    <para>
      Tanto las funciones <function>upperCase()</function> como
      <function>lowerCase()</function> siguen la misma forma: hacen
      una copia de la cadena argumento y cambian entre
      mayúsculas/minúsculas. El programa Find.cpp no es la mejor
      solución para el problema para las mayúsculas/minúsculas, por lo
      que lo revisitaremos cuando examinemos la comparación entre
      cadenas.
    </para>

    <sect2>
      <!-- : Finding in reverse -->
      <title>Busqueda inversa</title>

      <!--
      If you need to search through a string from end to beginning (to find
      the data in ??last in / first out?? order), you can use the string
      member function rfind( ):
      -->
      <para>
	Si necesita buscar en una cadena desde el final hasta el
	principio (para encontrar datos en orden <emphasis>"último
	entra / primero sale"</emphasis>), puede usar la función
	miembro de <classname>string</classname>
	<function>rfind()</function>.
      </para>


//: V2C03:Rparse.h



//: V2C03:Rparse.cpp


      <!--
      The string member function rfind( ) backs through the string looking for
      tokens and reports the array index of matching characters or
      string::npos if it is unsuccessful.
      -->
      <para>
	La función miembro de <classname>string</classname>
	<function>rfind()</function> vuelve por la cadena buscando
	elementos y reporta el indice del arreglo de las coincidencias
	de caracteres o
	<classname>string::</classname><varname>npos</varname> si no
	tiene éxito.
      </para>

    </sect2>
    <sect2>
      <!-- : Finding first/last of a set of characters -->
      <title>Encontrar el primero/último de un conjunto de caracteres</title>

      <!--
      The find_first_of( ) and find_last_of( ) member functions can be
      conveniently put to work to create a little utility that will strip
      whitespace characters from both ends of a string. Notice that it doesn'
      t touch the original string, but instead returns a new string:
      -->
      <para>
	La función miembro <function>find_first_of( )</function> y
	<function>find_last_of( )</function> pueden ser
	convenientemente usadas para crear una pequeña utilidad the
	ayude a deshechar los espacion en blanco del final e inicio de
	la cadena. Nótese que no se toca el
	<classname>string</classname> originar sino que se devuelve
	una nuevo <classname>string</classname>:
      </para>


//: V2C03:Trim.h


      <!--
      The first test checks for an empty string; in that case, no tests are
      made, and a copy is returned. Notice that once the end points are found,
      the string constructor builds a new string from the old one, giving the
      starting count and the length.
      -->
      <para>
	La primera prueba checkea si el string esta vacío; en ese
	caso, ya no se realizan más test, y se retorna una
	copia. Nótese que una vez los puntos del final son
	encontrados, el constructor de <classname>string</classname>
	construye un nuevo <classname>string</classname> desde el
	viejo, dándole  el contador incial y la longitud.
      </para>

      <!-- Testing such a general-purpose tool needs to be thorough: -->
      <para>
	Las pruebas de una herramienta tan general den ser cuidadosas
      </para>


//: V2C03:TrimTest.h



//: V2C03:TrimTest.cpp {O}



//: V2C03:TrimTestMain.cpp


      <!--
      In the array of strings, you can see that the character arrays are
      automatically converted to string objects. This array provides cases to
      check the removal of spaces and tabs from both ends, as well as ensuring
      that spaces and tabs are not removed from the middle of a string.
      -->
      <para>
	En el arrglo de <classname>string</classname>, puede ver que
	los arreglos de carácter son automáticamente convertidos a
	objetos <classname>string</classname>. Este arreglo provee
	casos para checkear el borrado de espacios en blanco y
	tabuladores en los extremos, además de asegurar que los
	espacios y tabuladores no son borrados de la mitad de un
	<classname>string</classname>.
      </para>

    </sect2>
    <sect2>
      <!-- : Removing characters from strings -->
      <title>Borrar caracteres de cadenas </title>

      <!--
      Removing characters is easy and efficient with the erase( ) member
      function, which takes two arguments: where to start removing characters
      (which defaults to 0), and how many to remove (which defaults to
      string::npos). If you specify more characters than remain in the string,
      the remaining characters are all erased anyway (so calling erase( )
      without any arguments removes all characters from a string). Sometimes
      it's useful to take an HTML file and strip its tags and special
      characters so that you have something approximating the text that would
      be displayed in the Web browser, only as a plain text file. The
      following example uses erase( ) to do the job:
      -->
      <para>
	Borrar caracteres es fácil y eficiente con la función miembro
	<function>erase()</function>, que toma dos argumentos: donde
	empezar a borrar caracteres (que por defecto es 0), y cuantos
	caracteres borrar (que por defecto es
	<classname>string::</classname><varname>npos</varname>). Si
	especifica más caracteres que los que quedan en el string, los
	caracteres restantes se borran igualmente (llamando
	<function>erase()</function> sin argumentos borra todos los
	caracteres del <classname>string</classname>). A veces es útil
	abrir un fichero HTML y borrar sus etiquetas y caracteres
	especiales de manera que tengamos algo aproximadamente igual
	al texto que obtendríamos en el navegador Web, sólo como un
	fichero de texto plano. El siguiente ejemplo usa
	<function>erase()</function> para hacer el trabajo:
      </para>


//: V2C03:HTMLStripper.cpp


      <!--
      This example will even strip HTML tags that span multiple lines.[35]
      This is accomplished with the static flag, inTag, which is true whenever
      the start of a tag is found, but the accompanying tag end is not found
      in the same line. All forms of erase( ) appear in the stripHTMLFlags( )
      function.[36] The version of getline( ) we use here is a (global)
      function declared in the <string> header and is handy because it stores
      an arbitrarily long line in its string argument. You don't need to
      worry about the dimension of a character array as you do with
      istream::getline( ). Notice that this program uses the replaceAll( )
      function from earlier in this chapter. In the next chapter, we'll use
      string streams to create a more elegant solution.
      -->
      <para>
	Este ejemplo borrará incluso las etiquetas HTML que se
	extienden a lo largo de varias líneas.<footnote>
	<para>Para mantener la exposición simple, esta version no
	maneja etiquetas anidadas, como los
	comentarios.</para></footnote> Esto se cumple gracias a la
	bandera estática <varname>inTag</varname>, que evalúa a cierto
	si el principio de una etiqueta es encontrada, pero la
	etiqueta de finalización correspondiente no es encontrada en
	la misma línea. Todas la formas de
	<function>erase()</function> aparecen en la función
	<function>stripHTMLFlags()</function>.<footnote>
	<para>Es tentador usar aquí las matemáticas para evitar
	algunas llamadas a <function>erase()</function>, pero como en
	algunos casos uno de los operandos es
	<classname>string::</classname><varname>npos</varname> (el
	entero sin signo más grande posible), ocurre un desbordamiento
	del entero y se cuelga el algoritmo.</para></footnote> La
	versión de <function>getline()</function> que usamos aquí es
	una función (global) declarada en la cabecera de
	<classname>string</classname> y es útil porque guarda una
	línea arbitrariamente larga en su argumento
	<classname>string</classname>. No necesita preocuparse de las
	dimensiones de un arreglo cuando trabaja con
	<classname>istream::</classname><function>getline()</function>. Nótese
	que este programa usa la función
	<function>replaceAll()</function> vista antes en este
	capítulo. En el póximo capitulo, usaremos los flujos de cadena
	para crear una solución más elegante.
      </para>

    </sect2>
    <sect2>
      <!-- : Comparing strings -->
      <title>Comparar cadenas </title>

      <!--
      Comparing strings is inherently different from comparing
      numbers. Numbers have constant, universally meaningful values. To
      evaluate the relationship between the magnitudes of two strings, you
      must make a lexical comparison. Lexical comparison means that when you
      test a character to see if it is ??greater than?? or ??less than??
      another character, you are actually comparing the numeric representation
      of those characters as specified in the collating sequence of the
      character set being used. Most often this will be the ASCII collating
      sequence, which assigns the printable characters for the English
      language numbers in the range 32 through 127 decimal. In the ASCII
      collating sequence, the first ??character?? in the list is the space,
      followed by several common punctuation marks, and then uppercase and
      lowercase letters. With respect to the alphabet, this means that the
      letters nearer the front have lower ASCII values than those nearer the
      end. With these details in mind, it becomes easier to remember that when
      a lexical comparison that reports s1 is ??greater than?? s2, it simply
      means that when the two were compared, the first differing character in
      s1 came later in the alphabet than the character in that same position
      in s2.
      -->
      <para>
	Comparar cadenas es inherentemente diferente a comparar
	enteros. Los nombres tienen un significado universal y
	constante. Para evaluar la relación entre las magnitudes de
	dos cadenas, se necesita hacer una comparación léxica. Una
	comparación léxica significa que cuando se comprueba un
	carácter para saber si es <emphasis>"mayor que"</emphasis> o
	<emphasis>"menor que"</emphasis> otro carácter, está en
	realidad comparando la representación numérica de aquellos
	caracteres tal como están especificados en el orden del
	conjunto de caracteres que está siendo usado. La ordenación
	más habitual suele ser la secuencia ASCII, que asigna a los
	caracteres imprimibles para el lenguaje inglés números en un
	rango del 32 al 127 decimal. En la codificación ASCII, el
	primer <emphasis>"carácter"</emphasis> en la lista es el
	espacio, seguido de diversas marcas de puntuación común, y
	después las letras mayúsculas y minúsculas. Respecto al
	alfabeto, esto significa que las letras cercanas al principio
	tienen un valor ASCII menor a aquellos más cercanos al
	final. Con estos detalles en mente, se vuelve más fácil
	recordar que cuando una comparació léxica reporta que
	<varname>s1</varname> es <emphasis>"mayor que"</emphasis>
	<varname>s2</varname>, simplemente significa que cuando fueron
	comparados, el primer carácter diferente en
	<varname>s1</varname> estaba atrás en el alfabeto que el
	carácter en la misma posición en <varname>s2</varname>.
      </para>

      <!--
      C++ provides several ways to compare strings, and each has
      advantages. The simplest to use are the nonmember, overloaded operator
      functions: operator ==, operator != operator >, operator <, operator >=,
      and operator <=.
      -->
      <para>
	C++ provee varias maneras de comparar cadenas, y cada una
	tiene ventajas. La más simple de usar son las funciones
	no-miembro sobrecargadas de operador:
	<function>operator==</function>,
	<function>operator!=</function>
	<function>operator&gt;</function>,
	<function>operator&lt;</function>,
	<function>operator&gt;=</function> y
	<function>operator&lt;=</function>.
      </para>


//: V2C03:CompStr.h


//: V2C03:CompStr.cpp


      <!--
      The overloaded comparison operators are useful for comparing both full
      strings and individual string character elements.
      -->
      <para>
	Los operadores de comaración sobrecargados son útiles para
	comparar dos cadenas completas y elementos individuales de una
	cadena de caracteres.
      </para>

      <!--
      Notice in the following example the flexibility of argument types on
      both the left and right side of the comparison operators. For
      efficiency, the string class provides overloaded operators for the
      direct comparison of string objects, quoted literals, and pointers to
      C-style strings without having to create temporary string objects.
      -->
      <para>
	Nótese en el siguiente ejemplo la flexibilidad de los tipos de
	argumento ambos lados de los operadores de comparación. Por
	eficiencia, la clase <classname>string</classname> provee
	operadores sobrecargados para la comparación directa de
	objetos <classname>string</classname>, literales de cadena, y
	punteros a cadenas estilo C sin tener que crear objetos
	<classname>string</classname> temporales.
      </para>


//: V2C03:Equivalence.cpp


      <!--
      The c_str( ) function returns a const char* that points to a C-style, null-terminated string equivalent to the contents of the string object. This comes in handy when you want to pass a string to a standard C function, such as atoi( ) or any of the functions defined in the <cstring> header. It is an error to use the value returned by c_str( ) as non-const argument to any function.
      -->
      <para>
	La función <function>c_str()</function> retorna un <type>const
	char*</type> que apunta a una cadena estilo C terminada en
	nulo, equivalente en contenidos al objeto
	<classname>string</classname>. Esto se vuelve muy útil cuando
	se quiere pasar un strin a una función C, como atoi() o
	cualquiera de las funciones definidas en la cabecera
	<emphasis>cstring</emphasis>. Es un error usar el valor
	retornado por <varname>c_str()</varname> como un argumento
	constante en cualquier función.
      </para>

      <!--
      You won't find the logical not (!) or the logical comparison operators
      (&& and ||) among operators for a string. (Neither will you find
      overloaded versions of the bitwise C operators &, |, ^, or ~.) The
      overloaded nonmember comparison operators for the string class are
      limited to the subset that has clear, unambiguous application to single
      characters or groups of characters.
      -->
      <para>
	No encontrará el operador <emphasis>not</emphasis>
	(<function>!</function>) o los operadores de comparación
	lógicos (<function>&amp;&amp;</function> y
	<function>||</function>) entre los operadore para
	<classname>string</classname>. (No encontrará ninguna versión
	sobrecargada de los operadores de bits de C: &amp;, |, ^, o
	~.) Los operadores de conversión no miembros sobrecargados
	para la clases <classname>string</classname> están limitados a
	un subconjunto que tiene una aplicación clara y no ambigua
	para caracteres individuales o grupos de caracteres.
      </para>

      <!--
      The compare( ) member function offers you a great deal more
      sophisticated and precise comparison than the nonmember operator set. It
      provides overloaded versions to compare:
      -->
      <para>
	La función miembro <function>compare()</function> le ofrece un
	gran modo de comparación más sofisticado y preciso que el
	conjunto de operadores nomiembro. Provee versiones
	sobrecargadas para comparar:
      </para>

      <para>
	<itemizedlist>
	  <listitem>
	    <para>Dos <classname>string</classname> completos</para>
	  </listitem>

	  <listitem>
	    <para>Parte de un <classname>string</classname> con un <classname>string</classname> completo</para>
	  </listitem>

	  <listitem>
	    <para>Partes de dos <classname>string</classname></para>
	  </listitem>
	</itemizedlist>
      </para>



//: V2C03:Compare.cpp


      <!--
      The swap( ) function in this example does what its name implies: it
      exchanges the contents of its object and argument. To compare a subset
      of the characters in one or both strings, you add arguments that define
      where to start the comparison and how many characters to consider. For
      example, we can use the following overloaded version of compare( ):
      -->
    <para>
      La función <function>swap()</function> en este ejemplo hace lo
      que su nombre implica: cambia el contenido del objeto por el del
      parámetro. Para comparar un subconjunto de caracteres en un o
      ambos <classname>string</classname>, añada argumentos que
      definen donde empezar y cuantos caracteres considerar. Por
      ejemplo, puede usar las siguientes versiones sobrecargadas de
      <function>compare()</function>:
    </para>

      <!-- s1.compare(s1StartPos, s1NumberChars, s2, s2StartPos, s2NumberChars); -->
      <para>
      <code>s1.compare(s1StartPos, s1NumberChars, s2, s2StartPos,
      s2NumberChars);</code>
    </para>

    <!-- Here's an example: -->
    <para>
      Aqui un ejemplo:
    </para>


    //: V2C03:Compare2.cpp


    <!--
    In the examples so far, we have used C-style array indexing syntax to
    refer to an individual character in a string. C++ strings provide an
    alternative to the s[n] notation: the at( ) member. These two indexing
    mechanisms produce the same result in C++ if all goes well:
    -->
    <para>
      Hasta ahora, en los ejemplos, hemos usado la sintaxis de
      indexación de arrays estilo C para referirnos a un carácter
      individual en un <classname>string</classname>. C++ provee de
      una alternativa a la notación <code>s[n]</code>: el miembro
      <function>at()</function>. Estos dos mecanismos de indexación
      producen los mismos resultados si todo va bien:
    </para>


//: V2C03:StringIndexing.cpp


    <!--
    There is one important difference, however, between [ ] and at( ). When
    you try to reference an array element that is out of bounds, at( ) will
    do you the kindness of throwing an exception, while ordinary [ ]
    subscripting syntax will leave you to your own devices:
    -->
    <para>
      Sin embargo, existe una importante diferencia entre <function>[
	]</function> y <function>at() </function>. Cuando usted intenta
      referenciar el elemento de un arreglo que esta fuera de sus
      límites, <function>at()</function> tiene la delicadeza de lanzar
      una excepción, mientras que ordinariamente <function>[
	]</function> le dejará a su suerte.
    </para>


//: V2C03:BadStringIndexing.cpp


    <!--
    Responsible programmers will not use errant indexes, but should you want
    to benefits of automatic index checking, using at( ) in place of [ ]
    will give you a chance to gracefully recover from references to array
    elements that don't exist. Execution of this program on one of our test
    compilers gave the following output: invalid string position
    -->
    <para>
      Los programadores responsables no usarán índices erráticos, pero
      puede que quiera beneficiarse de la comprobación automática de
      indices, usando<function>at()</function> en el lugar de
      <function>[ ]</function> le da la oportunidad de recuperar
      diligentemente de las referencias a elementos de un arreglo que
      no existen. La ejecución de sobre uno de nuestros compiladores
      le da la siguiente salida: <foreignphrase>"invalid string
      position"</foreignphrase>
    </para>

    <!--
    The at( ) member throws an object of class out_of_range, which derives
      (ultimately) from std::exception. By catching this object in an
    exception handler, you can take appropriate remedial actions such as
    recalculating the offending subscript or growing the array. Using
    string::operator[ ]( ) gives no such protection and is as dangerous as
    char array processing in C.[37]
    -->

	<!-- For the safety reasons mentioned, the C++ Standards
	Committee is considering a proposal to redefine
	string::operator[] to behave identically to string::at( ) for
	C++0x.-->

    <para>
      La función miembro <function>at()</function> lanza un objeto de
      clase <classname>out_of_class</classname>, que deriva finalmente
      de<classname> std::exception</classname>. Capturando este objeto
      en un manejador de excepciones, puede tomar las medidas
      adecuadas como recalcular el índice incorrecto o hacer crecer el
      arreglo. Usar
      <classname>string::</classname><function>operator[](
	)</function>  no proporciona ningún tipo de protección y es tan
      peligroso como el procesado de arreglos de caracteres en C.[37]
      <footnote><para>Por las razones de seguridad mencionadas, el
	  <foreignphrase>C++ Standards Committee</foreignphrase> está
	  considerando una propuesta de redefinición del
	  <classname>string::</classname><function>operator[]</function>
	  para comportarse de manera idéntica al
	  <classname>string::</classname><function>at()</function>
	  para C++0x.
	</para>
      </footnote>
    </para>

    </sect2>
    <sect2>
      <!-- : Strings and character traits -->
      <title>Cadenas y rasgos de caracteres</title>

      <!--
      The program Find.cpp earlier in this chapter leads us to ask the obvious
      question: Why isn't case-insensitive comparison part of the standard
      string class? The answer provides interesting background on the true
      nature of C++ string objects.
      -->
      <para>
	El programa <emphasis>Find.cpp</emphasis> anterior en este
	capítulo nos lleva a hacernos la pregunta obvia: ¿por que la
	comparación sensible a mayúsculas/minúsculas no es parte de la
	clase estándar <classname>string</classname>? La respuesta nos
	brinda un interesante transfondo sobre la verdadera naturaleza
	de los objetos <classname>string</classname> en C++.
      </para>

      <!--
      Consider what it means for a character to have ??case.?? Written Hebrew,
      Farsi, and Kanji don't use the concept of upper- and lowercase, so for
      those languages this idea has no meaning. It would seem that if there
      were a way to designate some languages as ??all uppercase?? or ??all
      lowercase,?? we could design a generalized solution. However, some
      languages that employ the concept of ??case?? also change the meaning of
      particular characters with diacritical marks, for example: the cedilla
      in Spanish, the circumflex in French, and the umlaut in German. For this
      reason, any case-sensitive collating scheme that attempts to be
      comprehensive will be nightmarishly complex to use.
      -->
      <para>
	Considere qué significa para un carácter tener
	"mayúscula/minúscula". El Hebreo escrito, el Farsi, y el Kanji
	no usan el concepto de "mayúscula/minúscula", con lo que para
	esas lenguas esta idea carece de significado. Esto daria a
	entender que si existiera una manera de designar algunos
	lenguages como "todo mayúsculas" o "todo minúsculas",
	podriamos diseñar una solución generalizada. Sin embargo,
	algunos leguajes que emplean el concepto de
	"mayúscula/minúscula", tambien cambian el significado de
	caracteres particulares con acentos diacríticos, por ejemplo
	la cedilla del Español, el circumflexo en Francés y la
	diéresis en Alemán. Por esta razón, cualquier codificación
	sensible a mayúsculas que intenta ser comprensiva acaba siendo
	una pesadilla en su uso.
      </para>

      <!--
      Although we usually treat the C++ string as a class, this is really not
      the case. The string type is a specialization of a more general
      constituent, the basic_string< > template. Observe how string is
      declared in the Standard C++ header file:[38]
      -->
      <para>
	Aunque tratamos habitualmente el <classname>string</classname>
	de C++ como una clase, esto no es del todo cierto. El tipo
	<classname>string</classname> es una especialización de algo
	más general, la plantilla <classname>basic_string&lt;
	&gt;</classname>. Observe como está declarada
	<classname>string</classname> en el fichero de cabecera de C++
	estándar.
      </para>

      <!-- typedef basic_string<char> string; -->
      <para>
	<code>typedef basic_string&lt;char&gt; string;</code>
      </para>

      <!--
      To understand the nature of the string class, look at the basic_string<
      > template:
      -->
      <para>
	Para comprender la naturaleza de la clase
	<classname>string</classname>, mire la plantilla
	<classname>basic_string&lt; &gt;</classname>

      </para>

      <!--
      template<class charT, class traits = char_traits<charT>,
      class allocator = allocator<charT> > class basic_string;
      -->
      <para>
	<code>
	  template&lt;class charT, class traits = char_traits&lt;charT&gt;,
	  class allocator = allocator&lt;charT&gt; &gt; class basic_string;
	</code>
      </para>

      <!--
      In Chapter 5, we examine templates in great detail (much more than in
      Chapter 16 of Volume 1). For now, just notice that the string type is
      created when the basic_string template is instantiated with char. Inside
      the basic_string< > template declaration, the line:
      -->
      <para>
	En el Capítulo 5, examinamos las plantillas con gran detalle
	(mucho más que en el Capítulo 16 del volúmen  1). Por ahora
	nótese que el tipo <classname>string</classname> es creada
	cuando instanciamos la plantilla
	<classname>basic_string</classname> con
	<type>char</type>. Dentro de la declaración plantilla
	<classname>basic_string&lt; &gt;</classname> la línea:
      </para>

      <!-- class traits = char_traits<charT>, -->
      <para>
			<code>class traits = char_traits&lt;charT&lt;</code>,
      </para>

      <!--
      tells us that the behavior of the class made from the basic_string< >
      template is specified by a class based on the template char_traits<
      >. Thus, the basic_string< > template produces string-oriented classes
      that manipulate types other than char (wide characters, for example). To
      do this, the char_traits< > template controls the content and collating
      behaviors of a variety of character sets using the character comparison
      functions eq( ) (equal), ne( ) (not equal), and lt( ) (less than). The
      basic_string< > string comparison functions rely on these.
      -->
      <para>
	nos dice que el comportamiento de la clase hecha a partir de
	<classname>basic_string&lt; &gt;</classname> es defineida por
	una clase basada en la plantilla <classname>char_traits&lt;
	&gt;</classname>. Así, la plantilla
	<classname>basic_string&lt; &gt;</classname> produce clases
	orientadas a <classname>string</classname> que manipulan otros
	tipos que <type>char</type> (caracteres anchos, por
	ejemplo). Para hacer esto, la plantilla
	<classname>char_traits&lt; &gt;</classname> controla el
	contenido y el comportamiento de la ordenación de una variedad
	de conjuntos de caracteres usando las funciones de comparación
	<function>eq()</function>
	(<foreignphrase>equal</foreignphrase>),
	<function>ne()</function> (<foreignphrase>not
	equal</foreignphrase>), y <function>lt()</function>
	(<foreignphrase>less than</foreignphrase>). Las funciones de
	comparación de <classname>basic_string&lt; &gt;</classname>
	confian en esto.
      </para>

      <!--
      This is why the string class doesn't include case-insensitive member
      functions: that's not in its job description. To change the way the
      string class treats character comparison, you must supply a different
      char_traits< > template because that defines the behavior of the
      individual character comparison member functions.
      -->
      <para>
	Es por esto por lo que la clase string no incluye funciones
	miembro sensibles a mayúsculas/minúsculas: eso no esta en la
	descripción de su trabajo. Para cambiar la forma en que la
	clase string trata la comparación de caracteres, tiene que
	suministrar una plantilla <classname>char_traits&lt;
	&gt;</classname> diferente ya que define el comportamiento
	individual de las funciones miembro de comparación carácteres.
      </para>

      <!--
      You can use this information to make a new type of string class that
      ignores case. First, we'll define a new case-insensitive char_traits< >
      template that inherits from the existing template. Next, we'll override
      only the members we need to change to make character-by-character
      comparison case insensitive. (In addition to the three lexical character
      comparison members mentioned earlier, we'll also supply a new
      implementation for the char_traits functions find( ) and compare( ))
      . Finally, we'll typedef a new class based on basic_string, but using
      the case-insensitive ichar_traits template for its second argument:
      -->
      <para>
	Puede usar esta información para hacer un nuevo tipo de
	<classname>string</classname> que ignora las
	mayúsculas/minúsculas. Primero, definiremos una nueva
	plantilla no sensible a mayúsculas/minúsculas de
	<classname>char_traits&lt; &gt;</classname> que hereda de una
	plantilla existente. Luego, sobrescribiremos sólo los miembros
	que necesitamos cambiar para hacer la comparación carácter por
	carácter. (Además de los tres miembros de comparación léxica
	mencionados antes, daremos una nueva implementación para
	laspara las funciones de <classname>char_traits</classname>
	<classname>find()</classname> y
	<classname>compare()</classname>). Finalmente, haremos un
	<code>typedef</code> de una nueva clase basada en
	<classname>basic_string</classname>, pero usando nuestra
	plantilla insensible a mayúsculas/minúsculas,
	<classname>ichar_traits</classname>, como segundo argumento:
      </para>


//: V2C03:ichar_traits.h



      <!--
      We provide a typedef named istring so that our class will act like an
      ordinary string in every way, except that it will make all comparisons
      without respect to case. For convenience, we've also provided an
      overloaded operator<<( ) so that you can print istrings. Here's an
      example:
      -->
      <para>
	Proporcionamos un <code>typedef</code> llamado
	<classname>istring</classname> ya que nuestra clase actuará
	como un <classname>string</classname> ordinario en todas sus
	formas, excepto que realizará todas las comparaciones sin
	respetar las mayúsculas/minúsculas. Por conveniencia, damos un
	operador sobrecargado <function>operator&lt;&lt;()</function>
	para que pueda imprimir los
	<classname>istring</classname>. Aque hay un ejemplo:
      </para>


//: V2C03:ICompare.cpp


      <!--
      This is just a toy example. To make istring fully equivalent to string,
      we'd have to create the other functions necessary to support the new
      istring type.
      -->
      <para>
	Este es solo un ejemplo de prueba. Para hacer
	<classname>istring</classname> completamente equivalente a un
	<classname>string</classname>, deberiamos haber creado las
	otras funciones necesarias para soportar el nuevo tipo
	<classname>istring</classname>.
      </para>

      <!--
      The <string> header provides a wide string class via the following
      typedef:
      -->
      <para>
	La cabecera <emphasis>&lt;string&gt;</emphasis> provee de un
	<classname>string</classname> ancho <footnote> <para>(N.del
	T.) Se refiere a <classname>string</classname> amplio puesto
	que esta formado por caracteres anchos <type>wchar_t</type>
	que deben soportar la codificación mas grande que soporte el
	compilador. Casi siempre esta codificación es
	<emphasis>Unicode</emphasis>, por lo que casi siempre el ancho
	de <type>wchar_t</type> es 2 bytes</para></footnote> gracias
	al siguiente <code>typedef</code>:
      </para>

      <!-- typedef basic_string<wchar_t> wstring; -->
      <para>
	<code>typedef basic_string&lt;wchar_t&gt; wstring;</code>
      </para>

      <!--
      Wide string support also reveals itself in wide streams (wostream in
      place of ostream, also defined in <iostream>) and in the header
      wchar_t specialization of char_traits in the standard library allows us
      to do a wide-character version of ichar_traits:
      -->
      <para>
	El soporte para <classname>string</classname> ancho se revela
	tambien en los <classname>streams</classname> anchos
	(<classname>wostream</classname> en lugar de
	<classname>ostream</classname>, tambien definido en
	<code>&lt;iostream&gt;</code>) y en la especialización de
	<type>wchar_t</type> de los <classname>char_traits</classname>
	en la libreria estándar le da la posibilidad de hacer una
	version de carácter ancho de
	<classname>ichar_traits</classname>
      </para>


//: V2C03:iwchar_traits.h


      <!--
      As you can see, this is mostly an exercise in placing a ??w' in the
      appropriate place in the source code. The test program looks like this:
      -->
      <para>
	Como puede ver, esto es principalmente un ejercicio de poner
	<emphasis>'w'</emphasis> en el lugar adecuado del código
	fuente. El programa de prueba podria ser asi:
      </para>


//: V2C03:IWCompare.cpp


      <!--
      Unfortunately, some compilers still do not provide robust support for
      wide characters.
      -->
      <para>
	Desgraciadamente, todavia algunos compiladores siguen sin
	ofrecer un soporte robusto para caracteres anchos.
      </para>

    </sect2>
  </sect1>
  <sect1>
    <!-- : A string application -->
    <title>Una aplicación con cadenas</title>

    <!--
    If you've looked at the sample code in this book closely, you've
    noticed that certain tokens in the comments surround the code. These are
    used by a Python program that Bruce wrote to extract the code into files
    and set up makefiles for building the code. For example, a double-slash
    followed by a colon at the beginning of a line denotes the first line of
    a source file. The rest of the line contains information describing the
    file's name and location and whether it should be only compiled rather
    than fully built into an executable file. For example, the first line in
    the previous program above contains the string C03:IWCompare.cpp,
    indicating that the file IWCompare.cpp should be extracted into the
    directory C03.
    -->
    <para>
      Si ha observado atentamente los códigos de ejemplo de este
      libro, habrá observado que ciertos elementos en los comentarios
      envuelven el código. Son usados por un programa en Python que
      escribió Bruce para extraer el código en ficheros y configurar
      makefiles para construir el código. Por ejemplo, una doble barra
      segida de dos puntos en el comienzo de una línea denota la
      primera línea de un fichero de código . El resto de la línea
      contiene información describiendo el nombre del fichero y su
      locaización y cuando deberia ser solo compilado en vez
      constituir un fichero ejecutable. Por ejemplo, la primera línea
      del programa anterior contiene la cadena
      <emphasis>C03:IWCompare.cpp</emphasis>, indicando que el fichero
      <emphasis>IWCompare.cpp</emphasis> deberia ser extraido en el
      directorio C03.
    </para>

    <!--
    The last line of a source file contains a triple-slash followed by a
    colon and a tilde. If the first line has an exclamation point
    immediately after the colon, the first and last lines of the source code
    are not to be output to the file (this is for data-only files). (If you'
    re wondering why we're avoiding showing you these tokens, it's because
    we don't want to break the code extractor when applied to the text of
    the book!)
    -->
    <para>
      La última línea del fichero fuente contiene una triple barra
      seguida de dos puntos y un signo "~". Es la primera línea tiene
      una exclamación inmediatamente después de los dos puntos, la
      primera y la última línea del código fuente no son para ser
      extraídas en un fichero (solo es para ficheros solo de
      datos). (Si se está preguntando por que evitamos mostrar estos
      elementos, es por que no queremos romper el extractor de código
      cuando lo aplicamos al texto del libro!).
    </para>

    <!--
    Bruce's Python program does a lot more than just extract code. If the
    token ??{O}?? follows the file name, its makefile entry will only be set
    up to compile the file and not to link it into an executable. (The Test
    Framework in Chapter 2 is built this way.) To link such a file with
    another source example, the target executable's source file will
    contain an ??{L}?? directive, as in:
    -->
    <para>
      El programa en Python de Bruce hace muchas más cosas que
      simplemente extraer el código. Si el elemento
      <emphasis>"{O}"</emphasis> sigue al nombre del fichero, su
      entrada en el makefile solo será configurada para compilar y no
      para enlazarla en un ejecutable. (El Test Framework en el
      Capítulo 2 está contruida de esta manera). Para enlazar un
      fichero con otro fuente de ejemplo, el fichero fuente del
      ejecutable objetivo contendrá una directiva
      <emphasis>"{L}"</emphasis>, como aquí:
    </para>

    <!-- //{L} ../TestSuite/Test -->
    <para>
      <code>//{L} ../TestSuite/Test</code>
    </para>

    <!--
    This section will present a program to just extract all the code so that
    you can compile and inspect it manually. You can use this program to
    extract all the code in this book by saving the document file as a text
    file[39] (let's call it TICV2.txt) and by executing something like the
    following on a shell command line: C:> extractCode TICV2.txt /TheCode
    -->
    <!--
    Beware that some versions of Microsoft Word erroneously replace
    single quote characters with an extended ASCII character when you
    save a document as text, which causes a compile error. We have no
    idea why this happens. Just replace the character manually with an
    apostrophe.
    -->
    <para>
      Esta sección le presentará un programa para extraer todo el
      código para que pueda compilarlo e inspeccionarlo
      manualmente. Puede usar este programa para extraer todo el
      codigo de este libro salvando el fichero como un fichero de
      texto<footnote> <para>Esté alerta porque algunas versiones de
      Microsoft Word que substituyen erroneamente los caracteres con
      comilla simple con un carácter ASCII cuando salva el documento
      como texto, causan un error de compilación. No tenemos idea de
      porqué pasa esto. Simplemente reemplace el carácter manualmente
      con un apóstrofe.</para></footnote> (llamémosle TICV2.txt)y
      ejecutando algo como la siguiente línea de comandos: <code>C:>
      extractCode TICV2.txt /TheCode</code>
    </para>

    <!--
    This command reads the text file TICV2.txt and writes all the source
    code files in subdirectories under the top-level directory /TheCode. The
    directory tree will look like the following:
    -->
    <para>
      Este comando lee el fichero de texto TICV2.txt y escribe todos
      los archivos de código fuente en subdirectorios bajo el definido
      <emphasis>/TheCode</emphasis>. El arbol de directorios se
      mostrará como sigue:
    </para>

    <!--
    TheCode/
    C0B/
    C01/
    C02/
    C03/
    C04/
    C05/
    C06/
    C07/
    C08/
    C09/
    C10/
    C11/
    TestSuite/
    -->
    <para>
    <code>TheCode/
    C0B/
    C01/
    C02/
    C03/
    C04/
    C05/
    C06/
    C07/
    C08/
    C09/
    C10/
    C11/
    TestSuite/</code>
    </para>

    <!--
    The source files containing the examples from each chapter will be in
    the corresponding directory.
    -->
    <para>
      Los ficheros de código fuente que contienen los ejemplos de cada
      capítulo estarán en el correspondiente directorio.
    </para>

    <!-- Here's the program: -->
    <para>
      Aquí está el programa:
    </para>


//: V2C03:ExtractCode.cpp


    <!--
    First, you'll notice some conditional compilation directives. The
    mkdir( ) function, which creates a directory in the file system, is
    defined by the POSIX[40] standard in the header
    (<direct.h>). The respective signatures for mkdir( ) also differ: POSIX
    specifies two arguments, the older versions just one. For this reason,
    there is more conditional compilation later in the program to choose the
    right call to mkdir( ). We normally don't use conditional compilation
    in the examples in this book, but this particular program is too useful
    not to put a little extra work into, since you can use it to extract all
    the code with it.
    -->
    <!--
    POSIX, an IEEE standard, stands for “Portable Operating System
    Interface” and is a generalization of many of the low–level
    system calls found in UNIX systems.
    -->
    <para>
      Primero observará algunas directivas de compilación
      condicionales. La función <function>mkdir()</function>, que crea
      un directorio en el sistema de ficheros, se define por el
      estándar POSIX<footnote> <para>POSIX, un estándar IEEE, es un
      <foreignphrase>"Portable Operating System
      Interface"</foreignphrase> (Interficie de Sistema Operativo
      Portable) y es una generalización de muchas de las llamadas a
      sistema de bajo nivel encontradas en los sistemas UNIX.</para>
      </footnote> en la cabecera (&lt;direct.h&gt;). La respectiva
      signatura de <function>mkdir()</function> también difiere: POSIX
      especifica dos argumentos, las viejas versiones sólo uno. Por
      esta razón, existe más de una directiva de compilación
      condicional después en el programa para elegir la llamada
      correcta a <function>mkdir()</function>. Normalmente no usamos
      compilaciones condicionales en los ejemplos de este libro, pero
      en este programa en particular es demasiado útil para no poner
      un poco de trabajo extra dentro, ya que puede usarse para
      extraer todo el código con él.
    </para>

    <!--
    The exists( ) function in ExtractCode.cpp tests whether a directory
    exists by opening a temporary file in it. If the open fails, the
    directory doesn't exist. You remove a file by sending its name as a
    char* to std::remove( ).
    -->
    <para>
      La función <function>exists()</function> en
      <emphasis>ExtractCode.cpp</emphasis> prueba que un directorio
      existe abriendo un fiechero temporal en él. Si la obertura
      falla, el directorio no existe. Borre el fichero enviando su
      nombre como un<type>char*</type> a
      <function>std::remove()</function>.
    </para>

    <!--
    The main program validates the command-line arguments and then reads the
    input file a line at a time, looking for the special source code
    delimiters. The Boolean flag inCode indicates that the program is in the
    middle of a source file, so lines should be output. The printDelims flag
    will be true if the opening token is not followed by an exclamation
    point; otherwise the first and last lines are not written. It is
    important to check for the closing delimiter first, because the start
    token is a subset, and searching for the start token first would return
    a successful find for both cases. If we encounter the closing token, we
    verify that we are in the middle of processing a source file; otherwise,
    something is wrong with the way the delimiters are laid out in the text
    file. If inCode is true, all is well, and we (optionally) write the last
    line and close the file. When the opening token is found, we parse the
    directory and file name components and open the file. The following
    string-related functions were used in this example: length( ), append(
    ), getline( ), find( ) (two versions), find_first_not_of( ), substr( ),
    find_first_of( ), c_str( ), and, of course, operator<<( ).
    -->
    <para>
      El programa principal valida los argumentos de la línea de
      comandos y después lee el fichero de entrada línea por línea,
      mirando por los delimitadores especiales de código fuente. La
      bandera booleana <varname>inCode</varname> indica que el
      programa esta en el medio de un fichero fuente, así que las
      lineas deben ser extraídas. La bandera
      <varname>printDelims</varname> será verdadero si el elemento de
      obertura no está seguido de un signo de exclamanción; si no la
      primera y la última línea no son escritas. Es importante
      comprobar el último delimitador primero, por que el elemnto
      inicial es un subconjuntom  y buscando  por el elemento inicial
      debería retornar cierto en ambos casos. Si encontramos el
      elemento final, verificamos que estamos en el medio del
      procesamiento de un fichero fuente; sino, algo va mal con la
      manera en que los delimitadores han sido colocados en el fichero
      de texto. Si <varname>inCode</varname> es verdadero, todo está
      bien, y escribiremos (opcionalmente) la última linea y
      cerraremos el fichero. Cuando el elemento de obertura se
      encuentra, procesamos el directorio y el nombre del fichero y
      abrimos el fichero. Las siguientes funciones relacionadas con
      <classname>string</classname> fueron usadas en este ejemplo:
      <function>length( )</function>, <function>append( )</function>,
      <function>getline( )</function>, <function>find( )</function>
      (dos versiones), <function>find_first_not_of( )</function>,
      <function>substr( )</function>,<function>find_first_of(
      )</function>,<function> c_str( )</function>, y, por supuesto,
      <function>operator&lt;&lt;( )</function>
    </para>

  </sect1>
  <sect1>
    <!-- : Summary -->
    <title>Resumen</title>

    <!--
    C++ string objects provide developers with a number of great advantages
    over their C counterparts. For the most part, the string class makes
    referring to strings with character pointers unnecessary. This
    eliminates an entire class of software defects that arise from the use
    of uninitialized and incorrectly valued pointers.
    -->
    <para>
      Los objetos <classname>string</classname> proporcionan a los
      desarrolladores un gran número de ventajas sobre sus
      contrapartidas en C. La mayoria de veces, la clase
      <classname>string</classname> hacen a las cadenas con punteros a
      caracteres innecesarios. Esto elimina por completo una clase de
      defectos de software que radican en el uso de punteros no
      inicializados o con valores incorrectos.
    </para>

    <!--
    C++ strings dynamically and transparently grow their internal data
    storage space to accommodate increases in the size of the string
    data. When the data in a string grows beyond the limits of the memory
    initially allocated to it, the string object will make the memory
    management calls that take space from and return space to the
    heap. Consistent allocation schemes prevent memory leaks and have the
    potential to be much more efficient than ??roll your own?? memory
    management.
    -->
    <para>
    FIXME:
      Los <classname>string</classname> de C++, de manera transparente
      y dinámica, hacen crecer el espacio de alamcenamiento para
      acomodar los cambios de tamaño de los datos de la cadena. Cuando
      los datos en n <classname>string</classname> crece por encima de
      los límites de la memoria asignada inicialmente para ello, el
      objeto <classname>string</classname> hará las llamadas para la
      gestión de la memoria para obtener el espacio y retornar el
      espacio al montón. La gestión consistente de la memoria
      previente lagunas de memoria y tiene el potencial de ser mucho
      más eficiente que un <emphasis>"hágalo usted mismo"</emphasis>.
    </para>

    <!--
    The string class member functions provide a fairly comprehensive set of
    tools for creating, modifying, and searching in strings. String
    comparisons are always case sensitive, but you can work around this by
    copying string data to C-style null-terminated strings and using
    case-insensitive string comparison functions, temporarily converting the
    data held in string objects to a single case, or by creating a
    case-insensitive string class that overrides the character traits used
    to create the basic_string object.
    -->
    <para>
      Las funciones de la clase <classname>string</classname>
      proporcionan un sencillo y comprensivo conjunto de herramientas
      para crear, modificar y buscar en cadenas. Las comparaciones
      entre <classname>string</classname> siempre son sensibles a
      mayúsculas/minúsculas, pero usted puede solucionar el problema
      copiando los datos a una cadena estilo C acabada en nulo y
      usando funciones no sensibles a mayúsculas/minúsculas,
      convirtiendo temporalmente los datos contenidos a  mayúsculas o
      minúsculas, o creando una clase <classname>string</classname>
      sensible que sobreescribe los rasgos de carácter usados para
      crear un objeto <classname>basic_string</classname>
    </para>

  </sect1>
  <sect1>
    <!-- : Exercises -->
    <title>Ejercicios</title>
    <!-- FIXME: ¿Es el mismo texto que en el volumen 1? -->
    <xi:include parse="xml" href="./ejercicios.xml"/>

    <orderedlist>
      <listitem>
    <!--
    1.  Write and test a function that reverses the order of the characters
    in a string.
    -->
    <para>
      Escriba y pruebe una función que invierta el orden de los
      caracteres en una cadena.
    </para>
     </listitem>
      <listitem>
    <!--
    2.  A palindrome is a word or group of words that read the same forward
    and backward. For example ??madam?? or ??wow.?? Write a program that
    takes a string argument from the command line and, using the function
    from the previous exercise, prints whether the string was a palindrome
    or not.
    -->
	<para>
	  2. Un palindromo es una palabra o grupo de palabras que
	  tanto hacia delante hacia atrás se leen igual. Por ejemplo
	  <emphasis>"madam"</emphasis> o
	  <emphasis>"wow"</emphasis>. Escriba un programa que tome un
	  string como argumento desde la línea de comandos y, usando
	  la función del ejercicio anterior, escriba si el string es
	  un palíndromo o no.
	</para>
     </listitem>
      <listitem>
    <!--
    3.  Make your program from Exercise 2 return true even if symmetric
    letters differ in case. For example, ??Civic?? would still return true
    although the first letter is capitalized.
    -->
	<para>
	  3. Haga que el programa del Ejercicio 2 retorne verdadero
	  incluso si las letras simetricas difieren en
	  mayúsculas/minúsculas. Por ejemplo,
	  <foreignphrase>"Civic"</foreignphrase> debería retornar
	  verdadero aunque la primera letra sea mayúscula.
	</para>
     </listitem>
      <listitem>
    <!--
    4.  Change your program from Exercise 3 to ignore punctuation and spaces
    as well. For example ??Able was I, ere I saw Elba.?? would report true.
    -->
	<para>
	  4. Cambie el programa del Ejercicio 3 para ignorar la
	  puntuación y los espacios también. Por ejemplo
	  <foreignphrase>"Able was I, ere I saw Elba."</foreignphrase>
	  debería retornar verdadero.
	</para>
     </listitem>
      <listitem>
    <!--
    5.  Using the following string declarations and only chars (no string
    literals or magic numbers):
    -->
	<para>
	  5. Usando las siguientes declaraciones de string y solo char
	  (no literales de cadena o números mágicos):
	</para>
    <!--
    string one("I walked down the canyon with the moving mountain bikers.");
    string two("The bikers passed by me too close for comfort.");
    string three("I went hiking instead.");
    -->
	<para>
	  <code>string one("I walked down the canyon with the moving
	    mountain bikers."); string two("The bikers passed by me too close
	    for comfort."); string three("I went hiking instead.");</code>
	</para>

    <!-- produce the following sentence: -->
	<para>
	  produzca la siguiente frase:
	</para>
    <!--
    I moved down the canyon with the mountain bikers. The mountain bikers
    passed by me too close for comfort. So I went hiking instead.
    -->
	<para>
	  <foreignphrase>I moved down the canyon with the mountain
	    bikers. The mountain bikers passed by me too close for
	    comfort. So I went hiking instead.
	  </foreignphrase>
	</para>
     </listitem>
      <listitem>
    <!--
    6.  Write a program named replace that takes three command-line
    arguments representing an input text file, a string to replace (call it
    from), and a replacement string (call it to). The program should write a
    new file to standard output with all occurrences of from replaced by to.
    -->
	<para>
	  6. Escriba un programa llamado "reemplazo" que tome tres
	  argumentos de la línea de comandos representando un fichero
	  de texto de entrada, una frase para reemplazar (llámela
	  <varname>from</varname>), y una cadena de reemplazo (llámela
	  <varname>to</varname>). El programa debería escribir un
	  nuevo fichero en la salida estandar con todas las
	  ocurrencias de <varname>from</varname> reemplazadas por
	  <varname>to</varname>.
	</para>
     </listitem>
      <listitem>
    <!--
    7.  Repeat the previous exercise but replace all instances of from
    regardless of case.
    -->
	<para>
	  7. Repetir el ejercicio anterior pero reemplazando todas las
	  instancias pero ignorando las mayúsculas/minúsculas.
	</para>
     </listitem>
      <listitem>
    <!--
    8.  Make your program from Exercise 3 take a filename from the
    command-line, and then display all words that are palindromes (ignoring
    case) in the file. Do not display duplicates (even if their case
    differs). Do not try to look for palindromes that are larger than a word
    (unlike in Exercise 4).
    -->
	<para>
	  8. Haga su programa a partir del Ejercicio 3 tomando un
	  nombre de fichero de la linea de comandos, y despues
	  mostrando todas las palabras que son palíndromos (ignorando
	  las mayúsculas/minúsculas) en el fichero. No intente buscar
	  palabras para palíndromos que son mas largos que una palabra
	  (a diferencia del ejercicio 4).
	</para>
     </listitem>
      <listitem>
    <!--
    9.  Modify HTMLStripper.cpp so that when it encounters a tag, it
    displays the tag's name, then displays the file's contents between the
    tag and the file's ending tag. Assume no nesting of tags, and that all
    tags have ending tags (denoted with </TAGNAME>).
    -->
	<para>
	  9. Modifique <emphasis>HTMLStripper.cpp</emphasis> para que
	  cuando encuentre una etiqueta, muestre el nombre de la
	  etiqueta, entonces muestre el contenido del fichero entre la
	  etiqueta y la etiqueta de finalización de fichero. Asuma que
	  no existen etiquetas anidadas, y que todas las etiquetas
	  tienen etiquetas de finalizacion (denotadas con
	  &lt;/TAGNAME&gt;).
	</para>
     </listitem>
      <listitem>
    <!--
    10.  Write a program that takes three command-line arguments (a filename
    and two strings) and displays to the console all lines in the file that
    have both strings in the line, either string, only one string, or
    neither string, based on user input at the beginning of the program (the
    user will choose which matching mode to use). For all but the ??neither
    string?? option, highlight the input string(s) by placing an asterisk
    (*) at the beginning and end of each string's occurrence when it is
    displayed.
    -->
	<para>
	  10. Escriba un programa que tome tres argumentos de la línea
	  de comandos (un nombre de fichero y dos cadenas) y muestre
	  en la consola todas la líneas en el fichero que tengan las
	  dos cadenas en la línea, alguna cadena, solo una cadena o
	  ninguna de ellas, basándose en la entreada de un usuario al
	  principio del programa (el usuario elegirá que modo de
	  búsqueda usar). Para todo excepto para la opción "ninguna
	  cadena", destaque la cadena(s) de entrada colocando un
	  asterisco (*) al principio y al final de cada cadena que
	  coincida cuando sea mostrada.
	</para>
     </listitem>
      <listitem>
    <!--
    11.  Write a program that takes two command-line arguments (a filename
    and a string) and counts the number of times the string occurs in the
    file, even as a substring (but ignoring overlaps). For example, an input
    string of ??ba?? would match twice in the word ??basketball,?? but an
    input string of ??ana?? would match only once in the word ??banana.??
    Display to the console the number of times the string is matched in the
    file, as well as the average length of the words where the string
    occurred. (If the string occurs more than once in a word, only count the
    word once in figuring the average.)
    -->
	<para>
	  11. Escriba un programa que tome dos argumentos de la linea
	  de comandos (un nombre de fichero y una cadena) y cuente el
	  numero de veces que la cadena esta en el fichero, incluso si
	  es una subcadena (pero ignorando los solapamientos). Por
	  ejemplo, una cadena de entrada de <emphasis>"ba"</emphasis>
	  debería coincidir dos veces en la palabra
	  <foreignphrase>"basquetball"</foreignphrase>, pero la cadena
	  de entrada <emphasis>"ana"</emphasis> solo deberia coincidir
	  una vez en <foreignphrase>"banana"</foreignphrase>. Muestre
	  por la consola el número de veces que la cadena coincide en
	  el fichero, igual que la longitud media de las palabras
	  donde la cadena coincide. (Si la cadena coincide más de una
	  vez en una palabra, cuente solamente la palabra una vez en
	  el cálculo de la media).
	</para>
     </listitem>
      <listitem>
    <!--
    12.  Write a program that takes a filename from the command line and
    profiles the character usage, including punctuation and spaces (all
    character values of 0x21 [33] through 0x7E [126], as well as the space
    character). That is, count the number of occurrences of each character
    in the file, then display the results sorted either sequentially (space,
    then !, ", #, etc.) or by ascending or descending frequency based on
    user input at the beginning of the program. For space, display the word
    ??Space?? instead of the character ' '. A sample run might look
    something like this:
    -->
	<para>
	  12. Escriba un programa que tome un nombre de fichero de la
	  línea de comandos y perfile el uso del carácter, incluyendo
	  la puntuación y los espacios (todos los valores de
	  caracteres desde el 0x21 [33] hasta el 0x7E [126], además
	  del carácter de espacio). Esto es, cuente el numero de
	  ocurrencias para cada carácter en el fichero, después
	  muestre los resultados ordenados secuencialmente (espacio,
	  despues !, ", #, etc.) o por frecuencia descendente o
	  ascendente basado en una entrada de usuario al principio del
	  programa. Para el espacio, muestre la palabra "espacio" en
	  vez del carácter ' '. Una ejecución de ejemplo debe
	  mostrarse como esto:
	</para>
    <!--
    Format sequentially, ascending, or descending (S/A/D): D
    t: 526
    r: 490
    etc.
    -->
	<para>
    Formato secuencial, ascendente o descendente (S/A/D): D
    t: 526
    r: 490
    etc.
	</para>
     </listitem>
      <listitem>
    <!--
    13.  Using find( ) and rfind( ), write a program that takes two
    command-line arguments (a filename and a string) and displays the first
    and last words (and their indexes) not matching the string, as well as
    the indexes of the first and last instances of the string. Display ??Not
    Found?? if any of the searches fail.
    -->
	<para>
	  13. Usando <function>find()</function> y
	  <function>rfind()</function>, escriba un programa que tome
	  dos argumentos de lánea de comandos (un nombre de fichero y
	  una cadena) y muestre la primera y la última palapra (y sus
	  indices) que no coinciden con la cadena, asi como los indice
	  de la primera y la última instancia de la cadena. Muestre
	  <emphasis>"No Encontrado"</emphasis> si alguna de las
	  busquedas fallan.
	</para>
     </listitem>
      <listitem>
    <!--
    14.  Using the find_first_of ??family?? of functions (but not
    exclusively), write a program that will remove all non-alphanumeric
    characters except spaces and periods from a file, then capitalize the
    first letter following a period.
    -->
	<para>
	  14. Usando la familia de fuciones
	  <function>find_first_of</function> (pero no exclusivamente),
	  escriba un programa que borrará todos los caracteres no
	  alfanuméricos excepto los espacios y los puntos de un
	  fichero. Despues convierta a mayúsculas la primera letra que
	  siga a un punto.
	</para>
     </listitem>
      <listitem>
    <!--
    15.  Again using the find_first_of ??family?? of functions, write a
    program that accepts a filename as a command-line argument and then
    formats all numbers in the file to currency. Ignore decimal points after
    the first until a non-numeric character is found, and round to the
    nearest hundredth. For example, the string 12.399abc29.00.6a would be
    formatted (in the USA) to $12.40abc$29.01a.
	-->
	<para>
	  15. Otra vez, usando la familia de funciones
	  <function>find_first_of</function>, escriba un programa que
	  acepte un nombre de fichero como argumentod elinea de
	  comandos y después formatee todos los números en un fichero
	  de moneda. Ignore los puntos decimales después del primero
	  despues de un carácter no mumérico, e redondee al
	</para>
     </listitem>
      <listitem>
    <!--
    16.  Write a program that accepts two command-line arguments (a filename
    and a number) and scrambles each word in the file by randomly switching
    two of its letters the number of times specified in the second
    argument. (That is, if 0 is passed into your program from the
    command-line, the words should not be scrambled; if 1 is passed in, one
    pair of randomly-chosen letters should be swapped, for an input of 2,
    two random pairs should be swapped, etc.).
    -->
	<para>
	  16. Escriba un programa que acepte dos argumentos por línea
	  de comandos (un nombre de fichero y un numero) y mezcle cada
	  paralabra en el fichero cambiando aleatoriamente dos de sus
	  letras el número de veces especificado en el segundo
	  parametro. (Esto es, si le pasamos 0 a su programa desde la
	  línea de comandos, las palabras no serán mezcladas; si le
	  pasamos un 1, un par de letras aleatoriamente elegidas deben
	  ser cambiadas, para una entrada de 2, dos parejas aleatorias
	  deben ser intercambiadas, etc.).
	</para>
     </listitem>
      <listitem>
    <!--
    17.  Write a program that accepts a filename from the command line and
    displays the number of sentences (defined as the number of periods in
    the file), average number of characters per sentence, and the total
    number of characters in the file.
    -->
	<para>
	  17.  Escriba un  programa que  acepte un  nombre  de fichero
	  desde la  línea de  comandos y muestre  el numero  de frases
	  (definido como el numero de puntos en el fichero), el número
	  medio  de  caracteres  por  frase,  y  el  número  total  de
	  caracteres en el fichero.
	</para>
     </listitem>
    </orderedlist>
  </sect1>
</chapter>