String

Introducción

El objeto string nos sirve para poder encapsular toda la información que hace referencia a una cadena de caracteres. Anteriormente, nosotros hubiésemos utilizado un array de caracteres (Ej: const char cArray[10]) con unas funciones por separado para operar con este array de caracteres (Ej: strcpy(…), strcmp(…), etc. ).

El objeto string nos permite operar de una forma más simple y más ordenada, también nos ofrece mayor seguridad en nuestras operaciones esquivando desbordamientos de buffer y en general mayor velocidad a la hora de generar código.

Concretamente este objeto string encapsula caracteres simples, es decir, el rango de los caracteres va desde 0 hasta 255. Si queremos una string que encapsule caracteres mas anchos será necesario mirar otro objeto que se llama wstring.

Declaración

Para declarar en nuestro código una string y poder utilizarla será necesario incluir en nuestro código el include <string>. Una vez declarado este include, ya podemos declarar nuestra string como si de un objeto normal se tratara.

#include <string>
 
void main()
{
    std::string sStr;
}

Los objetos strings pertenecen al namespace std, esto implica que cada una de los objetos strings deberá ser precedido en su declaración por el prefijo std:: para indicar que es de ese namespace.

Si queremos simplificar este aspecto, solo tenemos que añadir una línea después de los includes de nuestro código como podemos ver a continuación.

#include <string>
 
using namespace std;
 
void main()
{
    string sStr;
}

Esa línea nos indica que nuestro código ya conoce el namespace std y que por ello ya no es necesario preceder a los objetos de dicho espacio con su nombre.

Gracias a los constructores del objeto string, podemos declarar un objeto string de muchas maneras, muchas de las cuales nos simplifican la vida. Miremos a continuación unos ejemplos.

#include <string>
 
using namespace std;
 
void main()
{
    string sStr1 ="String1";
    string sStr2 = string("String2");
    string sStr3 = sStr1 + sStr2;
}

Comparación

El objeto string tiene sobrecargado el operador ==, lo cual nos ayuda a la hora de operar con estos objetos para poder comparar valores de forma fácil y rápida.

if(sStr1 == "Hola")
{
    //...hacer algo
}
 
if(sStr1 == sStr2)
{
    //...hacer algo
}

Aparte del operador ==, también tienen sobrecargados los operadores !=,<=,>=, etc.
El funcionamiento de estos operadores es el mismo que el que podríamos esperar de instrucciones aplicadas directamente a arrays de caracteres.

Tamaño

A la hora de conseguir el tamaño de una string ya no hace falta invocar a una función que cuente los caracteres que tiene dicha string. Para eso utilizaremos la función lenght() de las string, la cual nos devuelve un numero que representa la cantidad de caracteres que tiene dicha string.

unsigned int iSize = sStr1.lenght();

Acceso a los caracteres

Como en los arrays de caracteres, los caracteres de una string también pueden ser indexados. La indexación de los caracteres se lleva a cabo con el operador [] con el cual podemos acceder mediante un índice a un caracteres en concreto de la string.

sStr1[2] = 'd';

Iterators de las string

Normalmente en un array de caracteres nosotros podemos acceder a los caracteres mediante un índice, también lo podemos hacer mediante un puntero que apunte a una casilla de este array.

Cuando utilizamos un objeto string, para poder apuntar a un carácter mediante un puntero, necesitamos utilizar los iteradores, que básicamente son unos punteros con algunas características añadidas.

Fijémonos en el siguiente ejemplo, es un bucle en el que accedemos a todos los caracteres de una string y los cambiamos por el carácter ‘a’.

for(unsigned int i = 0; i < sStr1.length(); i++)
{
    sStr1[i] = 'a';
}

En el siguiente ejemplo haremos lo mismo pero utilizando una variable de tipo iterator para poder apuntar a las casillas. Aparte de esto, también es bueno comentar de que las string tienen dos funciones begin() y end() que nos devuelven los iteradores que apuntan al principio y al final de la string.

La función begin() apunta al primer carácter de la string
La función end() apunta al elemento ‘fantasma’ después del último elemento de la string.

Sabiendo estas dos premisas, nosotros podremos visitar todos los caracteres desde el primero hasta el último siempre y cuando nuestro iterador no sea igual al devuelto por la función end().

for(string::iterator iTer = sStr1.begin(); iTer != sStr1.end(); iTer++)
{
    (*iTer) = 'a';
}

En el ejemplo anterior podemos observar como hemos definido una variable de tipo iterator mediante string::iterator iTer. Esta variable la inicializamos al mismo valor que el devuelto por la función begin(). Iremos incrementando esta varible mientras no sea igual al valor devuelto por end().

Fijémonos que una de las características de los iterators es que se pueden incrementar (++) y esto hace que el propio iterator apunte al siguiente elemento al que estaba apuntando.

Haciendo el contenido del iterator, como si de un puntero normal se tratara, podemos acceder al elemento apuntado y tratarlo como deseemos.

NOTA: Muchas de las funciones que cambian o alteran la string producen como resultado la invalidación de los iterators que tuviésemos apuntando a esta string. Por lo tanto debemos ir con cuidado de utilizar iterators que estuvieran apuntando a nuestra string después de cambiarla. Pasa lo mismo con un puntero normal y corriente apuntando a un array, si esta array cambia de dirección al ser modificado, el puntero que lo estaba apuntando probocara un error de acceso.

Buscar en la string

Para poder buscar un o un conjunto de caracteres dentro de la string utilizaremos unas funciones muy interesantes que nos proporcionan las propias strings.

Estas funciones se llaman find(…) y rfind(…) y su uso es muy sencillo

find(…)

La función find(…) se describe como:

int find(string str, int iPos);

Esta función busca desde la posición del carácter iPos la primera string str que se encuentre en nuestra string.

Nos devuelve la posición donde se ha encontrado la string o por lo contrario, si no se ha encontrado nos devuelve el valor string::npos, que es equivalente a -1.

En el ejemplo siguiente podemos observar un uso práctico:

sStr1 = "Esto es un ejemplo";
 
int iFound = sStr1.find("un",0);

Este ejemplo nos devuelve en iFound el numero 8, pues “un” empieza en la posicion 8 de la string.

rfind(…)

La función rfind(…) se describe como:

int rfind(string str, int iPos);

Esta función actua de igual modo que la función find(…) a excepción de que empieza a buscar por la cola de la string y nos devuelve la primera coincidencia. En este caso no es necesario indicar desde que posición iPos se debe empezar.

Nos devuelve la posición donde se ha encontrado la string o por lo contrario, si no se ha encontrado nos devuelve el valor string::npos, que es equivalente a -1.

En el ejemplo siguiente podemos observar un uso práctico:

sStr1 = "Esto es un ejemplo";
 
int iFound = sStr1.rfind("es");

El codigo anterior nos devuelve en iFound el numero 5, pues des de la cola de la string, la primera coincidencia de “es” se encuentra en la posicion 5.

Otras funciones

find_firs_of(…) Nos devuelve la primera coincidencia des de el principio de la string

find_first_not_of(…) Nos devuelve la posicion del primer carácter que no coincida con la string que le pasamos des de el principio de la string

find_last_of(…) Nos devuelve la ultima coincidencia des de el principio de la string

find_last_no_of(…) Nos devuelve la posicion del primer carácter

Substrings

El objeto string nos permite crear sub-strings a partir de un ‘trozo’ de string. Esto se hace indicando desde donde empezamos la sub-string y que longitud tiene.

La función para poder obtener la sub-string es la siguiente:

string substr(int iPos, int iLen);

En el siguiente código podemos observar cómo hacemos uso de ella para poder obtener una nueva string que es una parte de la string mas larga.

string sStr = "Hola esto es un ejemplo";
string sStr2 = sStr.substr(5,4);

En la string sStr2 obtenemos la string “esto”, pues hemos cogido la sub-string que empieza en la posición 5 y que tiene 4 caracteres de longitud.

Insertar y Borrar

Otra opción muy interesante de las strings es la capacidad de insertar strings en posiciones específicas de la string actual o borrar grupos de caracteres de dicha string.

Insertar

Para poder insertar una string en nuestra string actual, usaremos la función insert(…). Esta función es de la siguiente forma:

insert(int iPos, string str);

Es decir, le pasamos la posición donde queremos insertar la string y por supuesto, le pasamos la string que queremos insertar.

string sStr = "Hola esto es un ejemplo";
sStr.insert(5, "AAAA");

En el codigo anterior, obtenemos como resultado "Hola AAAAesto es un ejemplo".

Borrar

Algo parecido pasa con el borrado de caracteres en las string. Para ello usaremos una función que se llama erase(…) y que es de la siguiente forma:

erase(int iPos, int iLen);

Esta función borra los caracteres des de iPos hasta iPos + iLen, es decir, necesitamos indicarle posición y cantidad de caracteres a borrar.

string sStr = "Hola esto es un ejemplo";
string sStr2 = sStr.erase(5,5);

Este código da como resultado la cadena "Hola es un ejemplo".

Reemplazar

Otra de las opciones que nos permiten las string es el hecho de reemplazar caracteres de la propia string por otros según nuestra decisión.

Para reemplazar caracteres, será necesario utilizar la función replace(…) la cual es de la siguiente forma:

replace(int iPos, int iCount, string sChars);

Esta función reemplazara una cantidad de caracteres igual a iCount empezando en iPos. Los caracteres que usara en el reemplazo están en la cadena sChars. Veamos un ejemplo:

sStr1 = "Esto es un ejemplo";
sStr1.replace(0,4,"Hola");

Esto nos da como resultado la cadena "Hola es un ejemplo".

Aunque funcione bien, a veces necesitamos algo más sofisticado como podría ser el caso de reemplazar todos los caracteres X de una cadena por el carácter Y. Si esto lo realizamos con la función que hemos mencionado, necesitaremos hacer una serie de búsquedas y varios replace(…).

Las STL nos proporcionan una función que no es miembro de las strings pero que trabaja con ellas. Esta función se llama igualmente replace(…) pero usa otro tipo de parámetros:

std::replace(string::iterator, string::iterator, char cChar1, char cChar2);

Con esta función podemos reemplazar todos los caracteres cChar1 por el carácter cChar2 desde el inicio marcado por el primer iterator y hasta el segundo iterator.

Normalmente si queremos decirle que mire toda la cadena, usaremos begin() y end() como iteradores para marcarle el rango.

Aparte de todo esto que hemos comentado, es necesario añadir el include <algorithm>, pues esta función replace(…) está considerada como un algoritmo externo a las string, sino no lo podremos usar.

Veamos un ejemplo:

#include <string>
#include <algorithm>
 
using namespace std;
 
void main()
{
string sStr1 = "Esto es un ejemplo";
    std::replace(sStr1.begin(), sStr1.end(), ‘e’, ’b);
}

Este ejemplo da como resultado la cadena "Esto bs un bjbmplo".

Conversiones

Muy a menudo nos es necesario hacer conversiones de datos mientras jugamos con las strings, es decir, podemos necesitar pasar un numero lógico a formato string o al contrario, pasar una string que contenga un numero escrito a su formato lógico.

Inicial Final
“4.3256” -> 4.3256
4.3256 -> “4.3256”

Para realizar estas conversiones entre strings y formatos lógicos es necesario utilizar un objeto nuevo hasta ahora. Este objeto se llama stringstream y para poder declararlo en nuestro código necesitaremos incluir la librería <sstream>.

El objeto stringstream nos permitirá hacer el cambio de formato de, por ejemplo, float a string o al revés.

Fijemonos en el siguiente ejemplo

#include <string>
#include <sstream>
 
using namespace std;
 
void main()
{
    stringstream strr;
    float ft = 4.3265f;
 
    strr << ft;
    sStr1 = strr.str(); 
}

El código anterior nos dejará en la string sStr1 la cadena “4.3265”.

String to Int

Para realizar una conversión de un número en una cadena y pasarlo al formato int deberemos hacerlo de la siguiente manera:

#include <string>
#include <sstream>
 
using namespace std;
 
void main()
{
    stringstream strr;
    string sStr1 = "100";
    int a;
 
    strr << sStr1;
    strr >> a; 
}

Este código nos deja en la variable a el valor lógico de 100

String to float

Para realizar esta conversión, necesitaremos el código siguiente:

#include <string>
#include <sstream>
 
using namespace std;
 
void main()
{
    stringstream strr;
    string sStr1 = "100";
    float a;
 
    strr << sStr1;
    strr >> a; 
}

Este código nos deja en la variable a el valor lógico de 100.0

String to wstring

Una wstring es una string como las que hemos visto hasta ahora pero con la peculiaridad de que utiliza un formato de carácter ancho.

El formato de carácter ancho es usado para poder tener más valores que los típicos 255 de la tabla ASCII, por ejemplo, para representar caracteres del alfabeto chino, etc.

Una wstring necesita el include <wstring> y si asignamos una cadena statica en el código, necesita ir precedida con la letra ‘L’ que indica que los caracteres son anchos.

Para realizar una conversión de una string a una wstring, NO vale con hacer una asignación con el operador ‘=’.

Como podremos observar en el siguiente código, utilizamos la función de asignación de la propia string para pasar cada uno de los caracteres de la string a caracteres de la wstring.

#include <string>
#include <wstring>
 
using namespace std;
 
void main()
{
    string sStr1 = L"Hola, soy una wstring";
    wstring wStr1;
 
    wStr1.assign(sStr1.begin(),sStr1.end()); 
}

En el código anterior podemos observar como la propia función de asignación de la wstring es capaz de coger los caracteres de la string y pasarlos a caracteres de wstring. Para ello debemos pasarle el ‘rango’ de donde a donde se hará la conversión. Normalmente será de begin() a end().

NOTA: Este algoritmo solo es válido si los alfabetos, es decir, la posición de los caracteres en el formato string y wstring están en la misma posición numérica. Sino la conversión puede dar como resultado un galimatías.

Int to string

Para realizar una conversión de un int a una cadena deberemos hacerlo de la siguiente manera:

#include <string>
#include <sstream>
 
using namespace std;
 
void main()
{
    stringstream strr;
    string sStr1;
    int a = 80;
 
    strr << a;
    sStr1 = strr.str(); 
}

En el código anterior lo que hacemos es introducir en el stream la variable ‘a’ con un valor lógico de 80 y en la siguiente línea recuperamos la string resultante y asignándola allá donde queramos.

Float to string

Para realizar una conversión de un float a una cadena deberemos hacerlo de la siguiente manera:

#include <string>
#include <sstream>
 
using namespace std;
 
void main()
{
    stringstream strr;
    string sStr1;
    float ft = 4.356;
 
    strr << ft;
    sStr1 = strr.str(); 
}

Este código es muy similar al anterior para los int’s, como podemos observar tenemos un float lógico y lo pasamos a cadena, dando como resultado una cadena con los caracteres “4.356”.

wstring to string

Pasar de una wstring a una string es igual de sencillo como anteriormente hemos comentado pero al revés, usando la función de asignación y usando también los iterators para delimitar el rango de conversión.

#include <string>
#include <wstring>
 
using namespace std;
 
void main()
{
    wstring wStr1 = L"Hola, soy una wstring";
    string sStr1;
 
    sStr1.assign(wStr1.begin(),wStr1.end()); 
}

NOTA: Este algoritmo solo es válido si los alfabetos, es decir, la posición de los caracteres en el formato string y wstring están en la misma posición numérica. Sino la conversión puede dar como resultado un galimatías.

Transformaciones

Por transformaciones entendemos el hecho de cambiar la información que alverga una string en su interior. A continuación podemos ver algunas transformaciones de utilidad

To Uppercase

Esta transformación nos cambia todos los caracteres del rango que nosotros especifiquemos a letras mayúsculas.

Fijemonos en el ejemplo siguiente:

#include <string>
#include <algorithm>
 
using namespace std;
 
void main()
{
    string sStr2 = string("StRiNg CoN SaLtOs");
 
    std::transform(sStr2.begin(), sStr2.end(), sStr2.begin(), toupper);
}

En el ejemplo anterior podemos observar cómo hacemos uso de una función que se encuentra en la librería <algorithm>. Esta función recibe como parámetros el rango de transformación (inicio hasta fin en este caso), el tercer parámetro es el iterador donde se aplicara la transformación, es decir, si queremos que sea la propia string la que queremos modificar, entonces tendrá de coincidir con el inicio de esta, por ultimo le pasamos el parámetro que indica que modificación sufrirá la cadena, es decir, todos los caracteres a mayúsculas.

El resultado es la cadena “STRING CON SALTOS”

To Lowercase

Esta transformación nos cambia todos los caracteres del rango que nosotros especifiquemos a letras minúsculas.

Fijemonos en el ejemplo siguiente:

#include <string>
#include <algorithm>
 
using namespace std;
 
void main()
{
    string sStr2 = string("StRiNg CoN SaLtOs");
 
    std::transform(sStr2.begin(), sStr2.end(), sStr2.begin(), tolower);
}

Este ejemplo es igual que el anterior pero en minúsculas.

El resultado es la cadena “string con saltos”

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License