String em C++ – o mínimo que você precisa saber

String em C++

O string em C++ é um tipo de dado (uma classe) que serve para armazenar cadeias de caracteres, ou texto, simplesmente. O tipo string é definido pela biblioteca padrão do C++ e é declarado no header <string>.

O std::string foi criado como uma alternativa ao clássico array de caracteres em estilo C (ou C-Style array, em inglês), do tipo char*, como aquele mostrado na primeira linha do bloco de código a seguir. Note que a expressão “Hello, world!” é chamada de string literal. Na segunda linha do bloco há a mesma cadeia de caracteres, mas criada usando a classe string.

const char* hello {"Hello, world!"};
const string helloStr {"Hello, world!"};

O problema com as cadeias de caracteres representadas por const char* é que elas não podem ser modificadas, e utilizar char* (sem o const) não resolve o problema: os string literals são armazenados em uma região de memória read-only, ou seja, onde apenas a leitura é permitida, e não a escrita – tentar modificar um string literal através de um C-Style array resulta em um comportamento indefinido.

Como usar std::string em C++?

Não há nada mais fácil que criar e usar variáveis de tipo string em C++. Basta usar a palavra string seguida do nome da variável e pronto! Se uma variável de tipo string não for explicitamente inicializada (como o string d do exemplo 1), o construtor padrão da classe string será invocado, e o valor da variável será um string vazio (“”).


Exemplo 1 – Definir variáveis string em C++

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string a {"Hello"};
    string b = "World";
    string c ("!");
    string d;
    // ponteiro para string
    string* p = &d;
    // referência para string
    string& ref = d;
    
    cout << a + ", " + b + c << endl;
}

Hello, World!


No exemplo 1, vemos muitas variáveis do tipo string criadas e inicializadas, e vemos também uma variável não inicializada explicitamente, assim como uma variável de tipo ponteiro para string, e outra do tipo referência para string.

Há ainda algo que talvez tenha chamado a sua atenção: no cout eu utilizei o sinal de + para “somar”os strings, e o resultado parece ser a união dos strings envolvidos na operação em um só. O que aconteceu alí foi a concatenação dos strings. Vejamos como isso funciona na seção a seguir.


Como concatenar strings em C++

Para concatenar dois strings em C++, basta utilizar o operador + junto dos strings que se deseja unir. Só isso. Bem simples, não?

Além disso, a classe string fornece sobrecargas do operador + que aceitam string literals como um dos seus argumentos, permitindo que expressões como a da linha 17 do exemplo 1 funcionem. Nela, concatenei o string a com um string literal que contém apenas uma virgula e um espaço, e o resultado dessa operação, que é um novo string criado a partir dos dois primeiros, com o string b. No fim, concatenei esse resultado com o string c, obtendo um string que contém “Hello, World!”.


Como comparar strings em C++

Ao contrário dos tipos de dados primitivos, como ints, floats etc., comparar strings pode ser feito de mais uma maneira. Podemos utilizar os operadores de comparação <, <=, >, >=, ou podemos usar o método compare.

Utilizando os operadores de comparação, duas regras se impõem:

  1. Se todos os caracteres de uma string a forem iguais aos de uma outra string b (na mesma sequência), mas a string b tiver mais caracteres que a string a, a é menor do que b.
  2. Se os caracteres de dois strings, a e b, diferem uma posição qualquer, os caracteres em questão são comparados lexicograficamente (segundo a ordem alfabética) e a string que possuir o “menor”caractere nesta posição será menor que a outra.

Se comparamos, por exemplo, as palavras banana e banido, a comparação utilizará a regra 2 ao chegar na quarta letra das duas palavras, pois aí é o primeiro lugar onde elas diferem entre si. Como a letra a é “menor” do que a letra i, banana é menor que banido.

Comparação de string em C++ usando compare

O método compare da classe string retorna um valor inteiro que indica a relação entre as strings. Se o valor retornado for zero, as strings são iguais. Um valor negativo indica que a primeira string é lexicograficamente menor que a segunda, enquanto um valor positivo indica o contrário.

Devido a essa natureza do compare, ainda que seja tentador fazer como no bloco a seguir, perceba que o comportamento do programa estaria errado se a intenção fosse fazer algo quando as duas strings são iguais, porque o compare retorna 0 para strings iguais.

if (str1.compare(str2)) ...

Vejamos logo adiante um exemplo do uso do compare com strings em C++. Se quiser saber mais sobre o método compare, recomendo que leia o Capítulo 2 do livro C++ Profissional, de Marc Gregoire – excelente livro de modo geral, e possui uma explicação muito clara sobre os strings -, e também que visite o artigo do CppReference em seguida.


Exemplo 2 – comparar string em C++ com compare

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string a {"Hello"};
    string b {"Hallo"};
    
    cout << "a == b: " << std::boolalpha << (a == b) << endl;
    cout << "a < b: " << std::boolalpha << (a.compare(b) < 0) << endl;
    cout << "b < a: " << std::boolalpha << (b.compare(a) < 0) << endl;

}

a == b: false
a < b: false
b < a: true


Gerenciamento de memória com strings

Ao contrário do que acontecia com os C-Style arrays, ou com o gerenciamento de strings em C de modo geral, o usuário da classe string não precisa se preocupar com a alocação de memória ao utlizar strings. A classe gerencia a memória utilizada por cada variável de tipo string automaticamente.

Alocação/liberação de memória

Quando se cria e inicializa uma variável de tipo string com um valor qualquer, o construtor da classe string aloca a memória necessária para armazenar a cadeia de caracteres em questão por nós – não vemos o new e o delete porque a memória é dinâmicamente alocada por nós “por baixo dos panos”.

string str {"Hello, world!"};

Coisa semelhante acontece quando uma variável string é destruída, como acontece com variáveis locais de uma função no fim da execução da função, por exemplo. A memória que havia sido dinâmicamente alocada pela classe string é então liberada, e aqui também tudo acontece sem que vejamos. A experência do usuário da classe string é muito “suave”.

Expansão de memória

Em alguns casos, quando como concatenamos duas strings e armazenamos o resultado da operação de volta em uma das duas, é preciso que a memória que havia sido originalmente atribuída àquela string seja redimensionada, para pode conter a nova string.Felizmente, a classe string também faz isso para nós, e nós podemos simplesmente usar o operador de atribuição = sem nos preocupar com nada disso.

O exemplo a seguir mostra uma operação na qual a memória destinada à variável hello precisa ser expandida para armazenar a nova string, que é maior do que a primeira.


Exemplo 3 – Expansão de string em C++

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string hello {"Hello"};
    hello += ", World!";
    cout << hello << endl;
}

Hello, World!


Verificar se um string está vazio – empty()

Às vezes nos é útil saber se um string é vazio, como para verificar se um argumento de uma função é válido antes de realizar uma operação sobre ele (como buscar um valor no string ou convertê-lo em um tipo numérico, por exemplo). Como podemos, portanto, determinar se um string em C++ está vazio? Mais uma vez, a classe string nos ajuda: ela fornece um método chamado empty que faz precisamente isso.

O método empty recebe nenhum parâmetro de entrada e retorna true se o string sobre o qual ele foi chamado estiver vazio, e false caso contrário.

Vejamos um exemplo do uso do empty no exemplo a seguir. Note que uma variável string não inicializada é vazia por padrão.

Exemplo 4 – verificando se um string em C++ é vazio com empty()

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string hello;
    if (hello.empty()) {
        cout << "O string hello está vazio: " << hello << endl;
        hello = "Hello";
    }
    hello += ", World!";
    cout << "Agora não está mais: " << hello << endl;
}

O string hello está vazio:
Agora não está mais: Hello, World!


Próximos passos

Agora que conhecemos a classe string em C++, e sabemos como utilizá-la para lidar com sequências de caracteres, é hora de passar aos assuntos relacionados ao string: como converter diferentes tipos em string (e a operação inversa), como encontrar um substring em um string, e como substituir uma porção de um string. Vejo vocês nos próximos artigos acerca do tipo string. Até lá!

Referências

  1. Professional C++, de Marc Gregoire: Capítulo 2.
  2. C++ Primer, de Stanley B. Lipman: Capítulo 3.
  3. A Tour of C++, de Bjarne Stroustrup: Capítulo 10.

Gostou do artigo? Então inscreva-se na nossa newsletter para não perder nenhum dos nossos artigos 🙂

Foto de perfil de Emanoel

Sou apaixonado por tecnologia, literatura e também filosofia. O cultivo dessas paixões ao longo da minha trajetória me inspiraram a compartilhar aquilo que aprendo com os outros da maneira mais clara que eu possa. Sou formado em Engenharia Elétrica no Brasil, e também sou engenheiro formado na França. Trabalho atualmente como programador C++ em uma multinacional francesa, uma das maiores empresas de TI do mundo.

Leave a Reply

Your email address will not be published. Required fields are marked *