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; }
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:
- 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.
- 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; }
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; }
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; }
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á!
Para que serve o ENDL em C++? 2 exemplos comentados
Referências
- Professional C++, de Marc Gregoire: Capítulo 2.
- C++ Primer, de Stanley B. Lipman: Capítulo 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 🙂
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.