C++ Funções de String
Um std::string não é só uma caixa de texto: ele vem com uma caixa de ferramentas. Com elas você procura uma palavra numa frase, recorta o dia de uma data, troca "gato" por "cachorro", apaga o "R$" de um preço e pergunta se o arquivo termina em ".pdf". Nesta aula você vai conhecer as ferramentas mais usadas, uma de cada vez, sempre com a saída real. A lista completa fica na referência std::string.
- Procurar com
finderfind, e a armadilha dostd::string::npos. - Recortar um pedaço com
substr. - Trocar, inserir e apagar pedaços com
replace,inserteerase. - Comparar textos com
==,<ecompare. - Perguntar "começa com?", "termina com?" e "contém?" com
starts_with,ends_withC++20 econtainsC++23. - Passar a string inteira para maiúsculas e inverter a ordem dos caracteres.
Todos os programas desta aula foram compilados com o g++ 15.2 na máquina fictícia da Ana, na pasta ~/cpp, com o comando padrão g++ -std=c++23 -Wall -Wextra arquivo.cpp -o programa. Lembre que as posições começam em 0 (aula Acessar Caracteres).
A ideia: uma régua embaixo do texto
Quase todas as ferramentas desta aula trabalham com posições. Imagine uma régua colada embaixo da frase, marcando o índice de cada caractere:
O gato comeu o peixe do gato
0123456789012345678901234567
1 2
Com a régua, as perguntas ficam simples. "Onde está gato?" Na posição 2. "Recorte 5 caracteres a partir da 15": peixe. Toda vez que você se perder, desenhe a régua.
1. Procurar: find e rfind
find ("achar") procura um texto (ou um caractere) e devolve a posição onde ele começa. rfind faz o mesmo de trás para a frente (o r é de reverse, "ao contrário"): acha a última ocorrência.
#include <iostream>
#include <string>
int main() {
std::string frase = "O gato comeu o peixe do gato";
std::cout << frase.find("gato") << '\n';
std::cout << frase.find("peixe") << '\n';
std::cout << frase.find('O') << '\n';
std::cout << frase.find("gato", 3) << '\n';
std::cout << frase.rfind("gato") << '\n';
std::cout << frase.find("cachorro") << '\n';
}
$ g++ -std=c++23 -Wall -Wextra find.cpp -o find $ ./find 2 15 0 24 24 18446744073709551615 « "cachorro" não existe na frase
- frase.find("gato")
- Procura do começo para o fim e devolve a posição da primeira ocorrência: 2 (olhe a régua).
- frase.find('O')
- Também procura um único
char. OOmaiúsculo é o primeiro caractere: posição 0. Atenção:finddiferencia maiúsculas de minúsculas. - frase.find("gato", 3)
- O segundo número diz de onde começar a procurar. A partir da posição 3, o primeiro
gatojá ficou para trás, e ele acha o segundo, na 24. - frase.rfind("gato")
- A última ocorrência: 24.
- frase.find("cachorro")
- Não achou. E aí ele devolve esse número gigante:
18446744073709551615. É onpos, o assunto da próxima seção.
A armadilha do std::string::npos
Quando find não acha nada, ele precisa devolver algum número. Não pode ser 0, que é uma posição válida. Então ele devolve um valor especial, std::string::npos ("no position", nenhuma posição): o maior número possível do tipo std::size_t, que na máquina da Ana (64 bits) é 18446744073709551615. Nenhuma string tem uma posição tão grande, então ele significa "não está aqui".
A forma certa de perguntar "achou?" é comparar com npos:
#include <iostream>
#include <string>
int main() {
std::string email = "ana@exemplo.com";
std::size_t pos = email.find('@');
if (pos != std::string::npos) {
std::cout << "arroba na posição " << pos << '\n';
} else {
std::cout << "e-mail sem arroba\n";
}
if (email.find('#') == std::string::npos) {
std::cout << "sem #\n";
}
}
$ g++ -std=c++23 -Wall -Wextra npos.cpp -o npos $ ./npos arroba na posição 3 sem #
- std::size_t pos = email.find('@');
- Guarda a posição num
std::size_t, o tipo que ofinddevolve (inteiro sem sinal, veja Inteiros). - pos != std::string::npos
- "A posição é diferente de nenhuma posição?" = "achou?". O
!=é "diferente" (veja Comparação). - email.find('#') == std::string::npos
- "Não achou?"
Agora o erro clássico. Parece lógico usar o resultado do find direto no if, como "achou ou não":
#include <iostream>
#include <string>
int main() {
std::string frase = "gato preto";
if (frase.find("gato")) {
std::cout << "achei gato\n";
} else {
std::cout << "não achei gato\n";
}
if (frase.find("cachorro")) {
std::cout << "achei cachorro\n";
}
int pos = frase.find("cachorro");
std::cout << "pos em int: " << pos << '\n';
}
$ g++ -std=c++23 -Wall -Wextra armadilha.cpp -o armadilha $ ./armadilha não achei gato « errado: gato está lá! achei cachorro « errado: cachorro não está! pos em int: -1
Tudo ao contrário, e o compilador não avisou nada. O if trata 0 como falso e qualquer outro número como verdadeiro (veja Booleanos). gato foi achado na posição 0, então o if entendeu "falso". cachorro não foi achado, o resultado foi npos, um número enorme, e o if entendeu "verdadeiro".
A última linha mostra outro detalhe: guardado num int, o npos "dá a volta" e vira -1. Você vai ver código antigo testando pos == -1. Funciona por acaso; o certo é std::size_t e npos.
find
Nunca use o resultado do find sozinho num if. Compare sempre com std::string::npos. Se só quer saber "tem ou não tem", use contains (seção 7), que já devolve true/false.
2. Recortar: substr
substr ("substring", um pedaço da string) devolve uma nova string com um trecho da original. Você diz onde começa e quantos caracteres quer. A original não muda.
#include <iostream>
#include <string>
int main() {
std::string data = "16/10/2026";
std::string dia = data.substr(0, 2);
std::string mes = data.substr(3, 2);
std::string ano = data.substr(6);
std::cout << dia << " | " << mes << " | " << ano << '\n';
std::string email = "ana@exemplo.com";
std::size_t arroba = email.find('@');
std::cout << "usuário: " << email.substr(0, arroba) << '\n';
std::cout << "domínio: " << email.substr(arroba + 1) << '\n';
std::cout << data.substr(6, 100) << '\n';
}
$ g++ -std=c++23 -Wall -Wextra substr.cpp -o substr $ ./substr 16 | 10 | 2026 usuário: ana domínio: exemplo.com 2026
- data.substr(0, 2)
- A partir da posição 0, pegue 2 caracteres:
16. O segundo número é a quantidade, não a posição final (uma confusão muito comum). - data.substr(3, 2)
- A partir da 3 (pulando o
16/), 2 caracteres:10. - data.substr(6)
- Sem a quantidade: daí até o fim.
2026. - email.substr(0, arroba)
- A combinação mais útil:
findacha a posição,substrrecorta. Do começo até antes da arroba: a posição da arroba (3) é exatamente a quantidade de caracteres antes dela. - email.substr(arroba + 1)
- Do caractere seguinte à arroba até o fim.
- data.substr(6, 100)
- Pedir mais caracteres do que existem não é erro: ele pega até o fim.
Já uma posição de começo além do fim é erro, e o substr lança a mesma exceção do .at():
$ cat substrerro.cpp
#include <iostream>
#include <string>
int main() {
std::string data = "16/10/2026";
std::cout << data.substr(20) << '\n';
}
$ g++ -std=c++23 -Wall -Wextra substrerro.cpp -o substrerro
$ ./substrerro
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr: __pos (which is 20) > this->size() (which is 10)
Abortado (imagem do núcleo gravada) ./substrerro
Isso acontece muito com find + substr quando o find não acha nada: s.substr(s.find('@') + 1) com um texto sem arroba. Por isso, confira o npos antes de recortar.
Missão: separe o e-mail em usuário e domínio usando find e substr (sem escrever bruno nem lojinha no código), para mostrar:
usuário: bruno domínio: lojinha.com.br
#include <iostream>
#include <string>
int main() {
std::string email = "bruno@lojinha.com.br";
// ache a arroba e recorte os dois pedaços
}
#include <iostream>
#include <string>
int main() {
std::string email = "bruno@lojinha.com.br";
std::size_t arroba = email.find('@');
std::cout << "usuário: " << email.substr(0, arroba) << '\n';
std::cout << "domínio: " << email.substr(arroba + 1) << '\n';
}
3. Trocar um pedaço: replace
replace ("substituir") apaga um trecho e coloca outro texto no lugar, na própria string. O texto novo pode ter qualquer tamanho.
#include <iostream>
#include <string>
int main() {
std::string frase = "Eu gosto de gato";
std::size_t pos = frase.find("gato");
frase.replace(pos, 4, "cachorro");
std::cout << frase << '\n';
std::string data = "16/10/2026";
data.replace(2, 1, "-");
data.replace(5, 1, "-");
std::cout << data << '\n';
}
$ g++ -std=c++23 -Wall -Wextra replace.cpp -o replace $ ./replace Eu gosto de cachorro 16-10-2026
- frase.replace(pos, 4, "cachorro")
- Três informações: onde começa o trecho (a posição de
gato), quantos caracteres apagar (4, o tamanho degato) e o que colocar no lugar. A frase cresce sozinha para cabercachorro. - data.replace(2, 1, "-")
- Troca 1 caractere na posição 2 (a primeira
/) por-.
replace troca um trecho. Para trocar todas as ocorrências, repita "procure, troque, procure de novo a partir dali" até o find devolver npos. O while ("enquanto") faz essa repetição (aula while); por enquanto, use como receita:
#include <iostream>
#include <string>
int main() {
std::string texto = "pão, leite, pão de queijo, pão doce";
std::string velho = "pão";
std::string novo = "bolo";
std::size_t pos = texto.find(velho);
while (pos != std::string::npos) {
texto.replace(pos, velho.size(), novo);
pos = texto.find(velho, pos + novo.size());
}
std::cout << texto << '\n';
}
$ g++ -std=c++23 -Wall -Wextra replacetodos.cpp -o replacetodos $ ./replacetodos bolo, leite, bolo de queijo, bolo doce
O pos + novo.size() faz a próxima busca começar depois do texto que acabou de entrar. Sem ele, trocar "a" por "aa" acharia o a recém-colocado para sempre, e o programa nunca terminaria.
4. Inserir: insert
insert ("inserir") coloca um texto antes da posição indicada, empurrando o resto para a direita.
#include <iostream>
#include <string>
int main() {
std::string nome = "Ana Souza";
nome.insert(4, "Maria ");
std::cout << nome << '\n';
nome.insert(0, "Sra. ");
std::cout << nome << '\n';
std::string cep = "50030230";
cep.insert(5, "-");
std::cout << cep << '\n';
}
$ g++ -std=c++23 -Wall -Wextra insert.cpp -o insert $ ./insert Ana Maria Souza Sra. Ana Maria Souza 50030-230
- nome.insert(4, "Maria ")
- Na posição 4 (onde está o
SdeSouza), insereMaria. OSouzavai para a direita. - nome.insert(0, "Sra. ")
- Posição 0 = no começo. É o jeito de "acrescentar na frente" sem montar uma string nova (o
+=da aula Juntar Strings só acrescenta no fim). - cep.insert(5, "-")
- Formata o CEP: o hífen entra antes do sexto dígito.
5. Apagar: erase, pop_back e clear
erase ("apagar") remove caracteres a partir de uma posição.
#include <iostream>
#include <string>
int main() {
std::string nome = "Ana Maria Souza";
nome.erase(4, 6);
std::cout << "[" << nome << "]\n";
std::string preco = "R$ 25,90";
preco.erase(0, 3);
std::cout << "[" << preco << "]\n";
std::string frase = "Bom dia!!!";
frase.erase(7);
std::cout << "[" << frase << "]\n";
std::string s = "abc";
s.pop_back();
std::cout << "[" << s << "]\n";
}
$ g++ -std=c++23 -Wall -Wextra erase.cpp -o erase $ ./erase [Ana Souza] [25,90] [Bom dia] [ab]
- nome.erase(4, 6)
- A partir da posição 4, apaga 6 caracteres:
Maria(5 letras e o espaço). - preco.erase(0, 3)
- Apaga os 3 primeiros:
R$. - frase.erase(7)
- Sem a quantidade: apaga da posição 7 até o fim. Os três
!somem. - s.pop_back()
- Apaga o último caractere ("tirar do fundo"). Numa string vazia é comportamento indefinido.
Para apagar tudo, use s.clear() (aula Strings).
6. Comparar: ==, < e compare
Strings se comparam com os mesmos operadores dos números (aula Operadores de Comparação). == pergunta "são iguais?"; < pergunta "vem antes, na ordem do dicionário?".
#include <iostream>
#include <string>
int main() {
std::string a = "banana";
std::string b = "maçã";
std::string c = "Banana";
std::cout << std::boolalpha;
std::cout << (a == "banana") << '\n';
std::cout << (a == c) << '\n';
std::cout << (a < b) << '\n';
std::cout << (c < a) << '\n';
std::cout << a.compare(b) << '\n';
std::cout << b.compare(a) << '\n';
std::cout << a.compare("banana") << '\n';
std::cout << ("10" < std::string("9")) << '\n';
}
$ g++ -std=c++23 -Wall -Wextra compare.cpp -o compare $ ./compare true « a == "banana" false « "banana" e "Banana" são diferentes true « "banana" vem antes de "maçã" true « "Banana" vem antes de "banana"! -11 11 0 true « "10" vem antes de "9"!
- a == "banana"
- Compara caractere por caractere. Funciona com um
std::stringde um lado e um literal do outro. - a == c
false: maiúsculas e minúsculas são caracteres diferentes.- a < b
- Ordem "de dicionário": compara o primeiro caractere; se for igual, o segundo; e assim por diante.
bvem antes dem. - c < a
"Banana" < "banana": a ordem é a da tabela de caracteres (ASCII, veja Caracteres), em que todas as maiúsculas vêm antes de todas as minúsculas. Para o computador,"Zebra" < "abacate".- a.compare(b)
- Responde as três perguntas de uma vez: negativo se
avem antes, zero se são iguais, positivo se vem depois. O número exato (-11é a distância entrebemna tabela) muda de uma biblioteca para outra; só o sinal importa. - "10" < std::string("9")
true, porque o caractere'1'vem antes de'9'. Textos com números são comparados como texto, não como números. Para comparar valores, converta antes (aula Texto ↔ Número).
== ou compare?
No dia a dia, use ==, !=, < e >: ficam mais legíveis. O compare aparece em código antigo e em situações em que você quer as três respostas numa conta só (como numa ordenação, em Algoritmos).
7. Começa com, termina com, contém
Três perguntas que você faz o tempo todo, com respostas true/false, sem posições nem npos:
#include <iostream>
#include <string>
int main() {
std::string arquivo = "relatorio-2026.pdf";
std::cout << std::boolalpha;
std::cout << arquivo.starts_with("relatorio") << '\n';
std::cout << arquivo.ends_with(".pdf") << '\n';
std::cout << arquivo.ends_with(".txt") << '\n';
std::cout << arquivo.starts_with('r') << '\n';
std::cout << arquivo.contains("2026") << '\n';
std::cout << arquivo.contains('#') << '\n';
}
$ g++ -std=c++23 -Wall -Wextra starts.cpp -o starts $ ./starts true true false true true false
| Função | Pergunta | Desde | Antes dela, como se fazia |
|---|---|---|---|
s.starts_with(x) | "Começa com x?" | C++20 | s.rfind(x, 0) == 0 ou s.substr(0, …) == x |
s.ends_with(x) | "Termina com x?" | C++20 | Comparar s.substr(s.size() - x.size()) (cuidado com tamanhos) |
s.contains(x) | "Tem x em algum lugar?" | C++23 | s.find(x) != std::string::npos |
Como elas são recentes, compilar com um padrão antigo dá erro. O g++ 15 usa C++17 se você não pedir outro (por isso o guia sempre usa -std=c++23):
$ g++ -std=c++17 -Wall -Wextra starts.cpp -o starts
starts.cpp: In function ‘int main()’:
starts.cpp:7:26: error: ‘std::string’ {aka ‘class std::__cxx11::basic_string<char>’} has no member named ‘starts_with’
7 | std::cout << arquivo.starts_with("relatorio") << '\n';
| ^~~~~~~~~~~
starts.cpp:8:26: error: ‘std::string’ {aka ‘class std::__cxx11::basic_string<char>’} has no member named ‘ends_with’
8 | std::cout << arquivo.ends_with(".pdf") << '\n';
| ^~~~~~~~~
starts.cpp:9:26: error: ‘std::string’ {aka ‘class std::__cxx11::basic_string<char>’} has no member named ‘ends_with’
9 | std::cout << arquivo.ends_with(".txt") << '\n';
| ^~~~~~~~~
starts.cpp:10:26: error: ‘std::string’ {aka ‘class std::__cxx11::basic_string<char>’} has no member named ‘starts_with’
10 | std::cout << arquivo.starts_with('r') << '\n';
| ^~~~~~~~~~~
starts.cpp:11:26: error: ‘std::string’ {aka ‘class std::__cxx11::basic_string<char>’} has no member named ‘contains’
11 | std::cout << arquivo.contains("2026") << '\n';
| ^~~~~~~~
starts.cpp:12:26: error: ‘std::string’ {aka ‘class std::__cxx11::basic_string<char>’} has no member named ‘contains’
12 | std::cout << arquivo.contains('#') << '\n';
| ^~~~~~~~
$ g++ -std=c++20 -Wall -Wextra starts.cpp -o starts
starts.cpp: In function ‘int main()’:
starts.cpp:11:26: error: ‘std::string’ {aka ‘class std::__cxx11::basic_string<char>’} has no member named ‘contains’
11 | std::cout << arquivo.contains("2026") << '\n';
| ^~~~~~~~
starts.cpp:12:26: error: ‘std::string’ {aka ‘class std::__cxx11::basic_string<char>’} has no member named ‘contains’
12 | std::cout << arquivo.contains('#') << '\n';
| ^~~~~~~~
"std::string não tem membro chamado starts_with". A função existe, mas não naquela versão da linguagem: com -std=c++20, só o contains (do C++23) continua faltando. Quando uma função "não existe" e você tem certeza do nome, desconfie do -std (veja Versões do C++).
8. Maiúsculas e minúsculas: toupper e tolower
O std::string não tem uma função "tudo em maiúsculas". Você faz isso caractere por caractere, com std::toupper ("para maiúscula") e std::tolower ("para minúscula"), do cabeçalho <cctype>, dentro de um laço for (char& c : s) (aula Acessar Caracteres):
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string nome = "ana souza";
for (char& c : nome) {
c = std::toupper(static_cast<unsigned char>(c));
}
std::cout << nome << '\n';
}
$ g++ -std=c++23 -Wall -Wextra maiusculas.cpp -o maiusculas $ ./maiusculas ANA SOUZA
- #include <cctype>
- Traz as funções de "tipo de caractere" (character type):
toupper,tolower,isdigit,isalpha… - for (char& c : nome)
- Passa por cada caractere, com
¶ poder mudá-lo. - static_cast<unsigned char>(c)
- Converte o caractere para "sem sinal" antes de entregar ao
toupper(veja Conversão de Tipos). Parece burocracia, mas é obrigatório: os bytes dos acentos são negativos numchar, etouppercom número negativo é comportamento indefinido. Com ounsigned char, eles viram números positivos válidos. - c = std::toupper(…)
- Guarda a versão maiúscula de volta no caractere. Espaços, números e pontuação voltam iguais.
Uma forma mais curta, que você vai encontrar muito, usa std::transform (de <algorithm>) com uma lambda, uma "função de uma linha só" (aula Lambdas). Por enquanto, use como receita:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string sigla = "Ufpe";
std::transform(sigla.begin(), sigla.end(), sigla.begin(),
[](unsigned char c) { return std::toupper(c); });
std::cout << sigla << '\n';
std::transform(sigla.begin(), sigla.end(), sigla.begin(),
[](unsigned char c) { return std::tolower(c); });
std::cout << sigla << '\n';
}
$ g++ -std=c++23 -Wall -Wextra transform.cpp -o transform $ ./transform UFPE ufpe
Leia como: "transforme de sigla.begin() (o começo) até sigla.end() (o fim), guardando a partir de sigla.begin(), aplicando toupper em cada caractere". O begin/end são iteradores, marcadores de começo e fim que você vai estudar em Iteradores.
toupper não entende acentos
"maçã" vira "MAçã": o ç e o ã ficam como estavam, porque cada um ocupa dois bytes e o toupper trabalha byte a byte. A aula Acentos e UTF-8 mostra isso e as saídas possíveis.
9. Inverter: std::reverse
Para inverter a ordem dos caracteres, use std::reverse ("inverter"), do cabeçalho <algorithm>. Ela muda a própria string.
#include <algorithm>
#include <iostream>
#include <string>
int main() {
std::string palavra = "roma";
std::reverse(palavra.begin(), palavra.end());
std::cout << palavra << '\n';
std::string p = "arara";
std::string invertida = p;
std::reverse(invertida.begin(), invertida.end());
std::cout << std::boolalpha << (p == invertida) << '\n';
}
$ g++ -std=c++23 -Wall -Wextra reverse.cpp -o reverse $ ./reverse amor true « "arara" lida de trás para a frente é igual: um palíndromo
- std::reverse(palavra.begin(), palavra.end())
- Inverte tudo do começo ao fim. Não devolve nada: a mudança fica em
palavra. - std::string invertida = p;
- Para guardar a original, faça uma cópia e inverta a cópia.
Com acentos, o std::reverse inverte os bytes e quebra as letras de dois bytes. Veja o resultado em Acentos e UTF-8.
Quando dá errado
if com find funciona ao contrário
O que significa: você escreveu if (s.find(x)). Achou na posição 0 vira "falso"; não achou (npos) vira "verdadeiro". O compilador não avisa.
Como consertar: if (s.find(x) != std::string::npos), ou if (s.contains(x)) no C++23.
18446744073709551615 (ou -1)
O que significa: você mostrou o resultado de um find que não achou nada: é o std::string::npos. Guardado num int, ele aparece como -1.
Como consertar: confira com != std::string::npos antes de usar a posição. Guarde posições em std::size_t.
what(): basic_string::substr: __pos (which is 20) > this->size() (which is 10)
O que significa: o substr (ou o erase, o insert, o replace) recebeu uma posição de começo maior que o tamanho. É um std::out_of_range. Muitas vezes a posição veio de um find que devolveu npos.
Como consertar: confira o resultado do find antes de usá-lo. Lembre que o segundo número do substr é a quantidade, não a posição final.
error: ‘std::string’ … has no member named ‘starts_with’ (ou ends_with, contains)
O que significa: a função é mais nova que o padrão com que você compilou. Sem -std, o g++ 15 usa C++17.
Como consertar: compile com -std=c++23. Se o nome estiver digitado errado (startswith, startsWith), a mensagem é a mesma: confira também a escrita.
65 em vez de A
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string nome = "ana";
for (char& c : nome) {
c = std::toupper(c);
}
std::cout << nome << '\n';
std::cout << std::toupper('a') << '\n';
}
$ g++ -std=c++23 -Wall -Wextra toupper1.cpp -o toupper1 $ ./toupper1 ANA 65
O que significa: std::toupper devolve um int (o código do caractere), não um char. Guardado num char (primeira linha), vira letra de novo. Mostrado direto com std::cout, aparece o número: 65 é o código do A.
Como consertar: guarde num char antes de mostrar, ou converta: static_cast<char>(std::toupper('a')). E, com texto que pode ter acento, não esqueça o static_cast<unsigned char> na entrada.
Referência rápida
| Função | O que faz | Exemplo (com s = "gato preto") |
|---|---|---|
s.find(x) | Posição da primeira ocorrência, ou npos | s.find("preto") → 5 |
s.find(x, ini) | O mesmo, começando em ini | s.find('o', 4) → 9 |
s.rfind(x) | Posição da última ocorrência | s.rfind('o') → 9 |
std::string::npos | "Não achou" | s.find("x") == std::string::npos |
s.substr(ini, n) | Cópia de n caracteres a partir de ini | s.substr(0, 4) → "gato" |
s.substr(ini) | Cópia de ini até o fim | s.substr(5) → "preto" |
s.replace(ini, n, x) | Troca n caracteres a partir de ini por x | s.replace(0, 4, "cão") → "cão preto" |
s.insert(ini, x) | Insere x antes da posição ini | s.insert(0, "o ") → "o gato preto" |
s.erase(ini, n) / s.erase(ini) | Apaga n caracteres / até o fim | s.erase(4) → "gato" |
s.pop_back() / s.clear() | Apaga o último / tudo | |
== != < > | Comparam (ordem da tabela de caracteres) | "Zebra" < "abacate" → true |
s.compare(x) | Negativo, zero ou positivo | s.compare("gato preto") → 0 |
s.starts_with(x) / s.ends_with(x) | Começa / termina com x C++20 | s.ends_with("to") → true |
s.contains(x) | Contém x C++23 | s.contains("ato") → true |
std::toupper(c) / std::tolower(c) | Um caractere para maiúscula / minúscula (<cctype>) | Use num laço, com unsigned char |
std::reverse(s.begin(), s.end()) | Inverte a string (<algorithm>) | "gato preto" → "oterp otag" |
Todas as outras funções (find_first_of, resize, swap, c_str…) estão na referência std::string.
Exercícios
1. Achou?
Complete a condição que pergunta se "@" existe em email:
2. Recortar
Com data = "16/10/2026", complete para pegar o ano (os 4 últimos caracteres, a partir da posição 6):
3. Termina com
Complete para perguntar se arquivo termina em .csv (C++20):
4. Com std::string s = "abacaxi";, quanto vale s.substr(2, 3)?
5. Com std::string s = "uva";, o que if (s.find("u")) { … } faz?
6. Qual destas comparações dá true?
Missão final: arrumar o nome do arquivo
Missão: o nome do arquivo veio bagunçado. Usando as ferramentas da aula: (1) ache o espaço com find e troque-o por _ com replace; (2) passe tudo para minúsculas com std::tolower num laço; (3) responda com ends_with se é um arquivo .txt. A saída deve ser:
relatorio_final.txt É texto? true
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string arquivo = "Relatorio Final.TXT";
// 1) troque o espaço por _
// 2) tudo em minúsculas
std::cout << arquivo << '\n';
// 3) mostre "É texto? " e a resposta do ends_with
}
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string arquivo = "Relatorio Final.TXT";
std::size_t espaco = arquivo.find(' ');
arquivo.replace(espaco, 1, "_");
for (char& c : arquivo) {
c = std::tolower(static_cast<unsigned char>(c));
}
std::cout << arquivo << '\n';
std::cout << std::boolalpha << "É texto? " << arquivo.ends_with(".txt") << '\n';
}
Resumo
find/rfinddevolvem a posição, oustd::string::nposquando não acham. Sempre compare comnpos; nunca use o resultado sozinho numif.substr(ini, n)recorta (o segundo número é a quantidade). Começo além do fim lançastd::out_of_range.replace(ini, n, x),insert(ini, x)eerase(ini, n)mudam a própria string.==e<comparam pela tabela de caracteres: maiúsculas antes de minúsculas,"10" < "9".comparedevolve negativo, zero ou positivo.starts_with/ends_withC++20 econtainsC++23 respondemtrue/false; exigem-std=c++20/c++23.- Maiúsculas: laço com
std::toupper(static_cast<unsigned char>(c)). Inverter:std::reverse(s.begin(), s.end()). Nenhum dos dois lida bem com acentos.