comparação std :: string (verifique se a string começa com outra string)

90

Preciso verificar se um std: string começa com "xyz". Como faço isso sem pesquisar toda a string ou criar strings temporárias com substr ().

jackhab
fonte

Respostas:

164

Eu usaria o método de comparação:

std::string s("xyzblahblah");
std::string t("xyz")

if (s.compare(0, t.length(), t) == 0)
{
// ok
}
Wacek
fonte
3
Por que você simplesmente não usa s.compare (t)?
Franck Mesirard
5
@FranckMesirard: Isso porque, por padrão, compare tentaria comparar todo o comprimento da string passada com os dados do membro e retornaria falso, enquanto fornecer o comprimento como o comprimento do parâmetro passado faria com que retornasse verdadeiro (significando std :: basic_string :: compare , quando usado com deslocamento e comprimento, pode ser usado como String.BeginsWith () em outras bibliotecas.) Sem o deslocamento e o comprimento, isso não seria verdade.
legends2k
1
Isso retorna verdadeiro se t estiver vazio.
gliderkite
14
@gliderkite Como deveria ... a string vazia é um prefixo inicial de cada string.
Jim Balter
1
Como deveria, está correto ... Se você quiser descartar strings vazias: if (! T.empty () &&! S.compare (0, t.length (), t))
ericcurtin
14

Uma abordagem que pode estar mais de acordo com o espírito da Biblioteca Padrão seria definir seu próprio algoritmo begin_with.

#include <algorithm>
using namespace std;


template<class TContainer>
bool begins_with(const TContainer& input, const TContainer& match)
{
    return input.size() >= match.size()
        && equal(match.begin(), match.end(), input.begin());
}

Isso fornece uma interface mais simples para o código do cliente e é compatível com a maioria dos contêineres da Biblioteca Padrão.

Neutrino
fonte
Legal! Isso deve ser adicionado para impulsionar!
David,
2
@David: Se boost é uma dependência permitida, consulte boost :: algorithm :: starts_with - Predicado 'Começa com'
Gabor
10

Olhe para a biblioteca String Algo do Boost , que tem uma série de funções úteis, como starts_with, istart_with (não diferencia maiúsculas de minúsculas), etc. Se você quiser usar apenas parte das bibliotecas boost em seu projeto, então você pode usar o utilitário bcp para copiar apenas arquivos necessários

Alex Ott
fonte
4

Parece que std :: string :: starts_with está dentro de C ++ 20, entretanto std :: string :: find pode ser usado

std::string s1("xyzblahblah");
std::string s2("xyz")

if (s1.find(s2) == 0)
{
   // ok, s1 starts with s2
}
Alejadro Xalabarder
fonte
1
Isso é muito melhor do que a resposta aceita usando, std::string::comparepois torna mais fácil verificar se a string começa com um literal sem repetir o próprio literal para encontrar seu tamanho. E obrigado por apontar para a solução direta C ++ 20.
Ruslan
Se s1 não começar com s2, ele ainda tentará corresponder depois, o que não é tão bom quanto compare ().
A117 de
0

Sinto que não estou entendendo totalmente sua pergunta. Parece que deveria ser trivial:

s[0]=='x' && s[1]=='y' && s[2]=='z'

Isso só olha (no máximo) os três primeiros caracteres. A generalização para uma string desconhecida em tempo de compilação exigiria que você substituísse o acima por um loop:

// look for t at the start of s
for (int i=0; i<s.length(); i++)
{
  if (s[i]!=t[i])
    return false;
}
1800 INFORMAÇÕES
fonte
Bem, eu sei como comparar strings usando funções C. Minha pergunta era sobre fazer isso de forma orientada a objetos por meio de C ++ STL.
jackhab
Não há função C sendo usada aqui. E a Biblioteca Padrão não o impede de escrever suas próprias unções.
6
e se t for menor do que s?
vidstige de
@jackhab O autor de STL diz "STL não é orientado a objetos. Acho que a orientação a objetos é quase uma farsa tanto quanto a Inteligência Artificial." - stlport.org/resources/StepanovUSA.html
Jim Balter
1
@vidstige Então o loop termina quando encontra o NUL de terminação em t.
Jim Balter