std :: string сравнение (проверьте, начинается ли строка с другой строки)

90

Мне нужно проверить, начинается ли строка std: с «xyz». Как мне это сделать, не перебирая всю строку и не создавая временные строки с помощью substr ().

дакхаб
источник

Ответы:

164

Я бы использовал метод сравнения:

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

if (s.compare(0, t.length(), t) == 0)
{
// ok
}
Wacek
источник
3
Почему бы вам просто не использовать s.compare (t)?
Franck Mesirard
5
@FranckMesirard: Это потому, что по умолчанию compare будет пытаться сравнить всю длину переданной строки с данными члена и вернет false, в то время как указав длину как длину переданного параметра, он вернет true (что означает std :: basic_string :: compare , при использовании со смещением и длиной, можно использовать как String.BeginsWith () в других библиотеках.) Без смещения и длины это было бы неверно.
legends2k
1
Это возвращает истину, если t пусто.
gliderkite 06
14
@gliderkite Как и должно быть ... пустая строка является начальным префиксом каждой строки.
Джим Балтер
1
Как и должно быть, правильно ... Если вы хотите исключить пустые строки: if (! T.empty () &&! S.compare (0, t.length (), t))
ericcurtin
14

Подход, который мог бы больше соответствовать духу Стандартной библиотеки, заключался бы в определении вашего собственного алгоритма 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());
}

Это обеспечивает более простой интерфейс для клиентского кода и совместимо с большинством контейнеров стандартной библиотеки.

Нейтрино
источник
Круто! Это нужно добавить в буст!
Дэвид
2
@David: Если boost является допустимой зависимостью, см. Boost :: algorithm :: start_with - предикат 'Начинается с'
Габор
10

Обратите внимание на библиотеку Boost String Algo , которая имеет ряд полезных функций, таких как start_with, istart_with (без учета регистра) и т. Д. Если вы хотите использовать только часть Boost-библиотек в своем проекте, вы можете использовать утилиту bcp для копирования только необходимые файлы

Алекс Отт
источник
4

Кажется, что std :: string :: start_with находится внутри C ++ 20, между тем std :: string :: find можно использовать

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

if (s1.find(s2) == 0)
{
   // ok, s1 starts with s2
}
Алехадро Халабардер
источник
1
Это намного лучше, чем принятый ответ с использованием, std::string::compareпотому что он позволяет легко проверить, начинается ли строка с литерала, не повторяя сам литерал, чтобы определить его размер. И спасибо, что указали на прямое решение C ++ 20.
Руслан
Если s1 не начинается с s2, он все равно будет пытаться сопоставить его впоследствии, что не так хорошо, как compare ().
A117
0

Мне кажется, я не совсем понимаю ваш вопрос. Похоже, это должно быть тривиально:

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

Это смотрит только (максимум) на первые три символа. Обобщение для строки, которая неизвестна во время компиляции, потребует, чтобы вы заменили приведенное выше циклом:

// look for t at the start of s
for (int i=0; i<s.length(); i++)
{
  if (s[i]!=t[i])
    return false;
}
1800 ИНФОРМАЦИЯ
источник
Я знаю, как сравнивать строки при использовании функций C. Мой вопрос заключался в том, чтобы сделать это объектно-ориентированным способом с помощью C ++ STL.
jackhab
Здесь не используется функция C. Стандартная библиотека не мешает вам писать собственные объединения.
6
а что если t короче s?
vidstige
@jackhab Автор STL говорит: «STL не объектно-ориентированный. Я думаю, что объектно-ориентированность - это почти такая же обманка, как и искусственный интеллект». - stlport.org/resources/StepanovUSA.html
Джим Балтер
1
@vidstige Затем цикл завершается, когда он встречает завершающий NUL в t.
Джим Балтер