Menu

Strings em C++: noções de std::string, métodos e armadilhas

Como usar std::string em C++ - montar, juntar, buscar e fatiar texto com segurança, e por que você quase nunca quer um char* cru para trabalho de verdade.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

std::string: texto que se gerencia sozinho

Na página anterior você viu como ponteiros inteligentes permitem que um objeto seja dono de um recurso e o libere automaticamente. std::string é essa mesma ideia aplicada ao texto: ela possui um buffer de caracteres, faz ele crescer quando você anexa algo e o libera quando a string sai de escopo. Você nunca chama new, nunca conta bytes e nunca se preocupa com um terminador nulo faltando.

Para usá-la, inclua <string>. A classe fica no espaço de nomes std.

Esse operador + faz trabalho de verdade - ele aloca um buffer novo grande o suficiente para as duas partes e as copia para dentro. Com um char* cru você teria que recorrer a strcpy e strcat e torcer para que seu buffer fosse grande o bastante. std::string faz toda essa classe de erros desaparecer.

Montando e juntando strings

Você pode concatenar com +, mas o cavalo de batalha para fazer uma string crescer no lugar é +=. Ele anexa ao buffer existente em vez de produzir uma string totalmente nova a cada vez, o que faz diferença dentro de laços.

Uma surpresa comum: + exige que pelo menos um dos operandos já seja um std::string. Dois literais de string são apenas const char*, então "a" + "b" não compila - não existe um operator+ para dois ponteiros crus. Transforme um deles em string primeiro:

string s = "a" + "b";              // error: can't add two const char*
string s = string("a") + "b";      // fine - left side is a std::string
string s = "a"s + "b";             // fine in C++14+, the "s" literal suffix

Repare que essa última forma usa o sufixo s de <string> (using namespace std::string_literals;), que transforma um literal diretamente em um std::string.

Acessando o interior de uma string

Um std::string se comporta como um contêiner de char, então você pode indexá-lo, percorrê-lo e pedir pedaços dele.

substr(pos, len) retorna uma string totalmente nova copiada do original; ela não modifica a fonte. Cuidado com os limites: word[10] em uma string de 5 caracteres é comportamento indefinido - não vai lançar nada, apenas lê lixo. Se quiser um acesso verificado que lança std::out_of_range, use word.at(10) em vez de word[10].

Outra armadilha clássica: .size() retorna um tipo sem sinal (size_t). Escrever um laço de trás para frente como for (size_t i = word.size() - 1; i >= 0; --i) nunca termina, porque um i sem sinal nunca pode ficar abaixo de zero - ele dá a volta e vira um número enorme. Use um índice com sinal ou reestruture a condição quando precisar percorrer uma string ao contrário.

Buscando e substituindo

find localiza uma substring ou caractere e retorna o índice inicial. Quando o alvo não está presente, ele retorna a constante especial std::string::npos - sempre compare com ela em vez de presumir que find retorna -1.

Para mudar texto no lugar, replace(pos, len, text) troca um trecho por conteúdo novo (que pode ter outro tamanho), e insert/erase adicionam ou removem pedaços:

Strings e números

Texto e números não se convertem sozinhos - "42" são três caracteres, não o inteiro 42. A biblioteca padrão oferece funções de conversão nos dois sentidos. Use stoi, stod e companhia para analisar texto e transformá-lo em números, e to_string para ir na direção oposta.

Duas armadilhas aqui. Primeira, stoi("abc") lança std::invalid_argument, então proteja entrada não confiável com try/catch. Segunda, to_string(3.99) dá o 3.990000 completo - se você precisa de controle sobre precisão e formatação, isso é trabalho para string streams, que é exatamente para onde vamos a seguir.

try {
    int n = std::stoi(userInput);
} catch (const std::invalid_argument&) {
    std::cout << "That wasn't a number.\n";
}

A seguir: entrada e saída

Você vem imprimindo strings com cout esse tempo todo, mas lê-las de volta a partir do usuário tem suas próprias surpresas - cin >> name para no primeiro espaço, então uma linha inteira como "Ada Lovelace" precisa de std::getline. A próxima página cobre a entrada e saída em C++ como deve ser: operadores de stream, ler linhas inteiras e misturar >> com getline sem tropeçar em quebras de linha que sobraram.

Perguntas frequentes

Qual é a diferença entre std::string e char* em C++?

std::string é uma classe que possui e gerencia sua própria memória, cresce conforme necessário e se limpa automaticamente. Um char* é apenas um ponteiro cru para caracteres com um '\0' terminador - você gerencia o buffer, o tamanho e o tempo de vida por conta própria. Prefira std::string para quase tudo; ela elimina categorias inteiras de bugs de estouro de buffer e de ponteiro pendente.

Como obter o tamanho de uma string em C++?

Chame .size() ou seu apelido .length() em um std::string: name.size() retorna o número de caracteres como um size_t. Ambos retornam o mesmo valor; size() é o estilo mais comum porque combina com todos os outros contêineres da STL.

Como converter uma string em número em C++?

Use std::stoi para int, std::stod para double e semelhantes (stol, stof). Exemplo: int n = std::stoi("42");. Essas funções lançam std::invalid_argument se o texto não for um número, então envolva-as em um try/catch quando a entrada não for confiável.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR