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

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


person jackhab    schedule 31.05.2009    source источник


Ответы (5)


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

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

if (s.compare(0, t.length(), t) == 0)
{
// ok
}
person Wacek    schedule 31.05.2009
comment
Я забыл про сравнение - это лучший метод, но нет необходимости использовать c_str(0, чтобы получить строку символов - person ; 31.05.2009
comment
Вы также можете сделать строку s(xyz) == xyz. :) - person Skurmedel; 31.05.2009
comment
Нил, ты абсолютно прав, я отредактировал ответ и удалил вызов c_str() - person Wacek; 31.05.2009
comment
Почему бы вам просто не использовать s.compare(t)? - person Franck Mesirard; 24.06.2009
comment
@FranckMesirard: это потому, что по умолчанию compare попытается сравнить всю длину переданной строки с данными члена и вернет false, а указание длины в качестве длины переданного параметра заставит его вернуть true ( означает, что std::basic_string::compare при использовании со смещением и длиной можно использовать как String.BeginsWith() в других библиотеках.) Без смещения и длины это не было бы истинный. - person legends2k; 04.11.2011
comment
Это возвращает true, если t пуст. - person gliderkite; 06.07.2012
comment
@gliderkite Как и должно быть ... пустая строка является начальным префиксом каждой строки. - person Jim Balter; 06.11.2014
comment
Как и должно быть правильно... Если вы хотите исключить пустые строки: if (!t.empty() && !s.compare(0, t.length(), t)) - person ericcurtin; 20.06.2018

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

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

person Neutrino    schedule 15.05.2013
comment
Прохладный! Это должно быть добавлено, чтобы повысить! - person David; 25.04.2014
comment
@David: если boost является разрешенной зависимостью, см. boost::algorithm::starts_with — предикат 'Начинается с' - person Gabor; 08.10.2017

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

person Alex Ott    schedule 31.05.2009

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

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

if (s1.find(s2) == 0)
{
   // ok, s1 starts with s2
}
person Alejadro Xalabarder    schedule 04.07.2018
comment
Это намного лучше, чем принятый ответ с использованием std::string::compare, поскольку позволяет легко проверить, начинается ли строка с литерала, не повторяя сам литерал, чтобы найти его размер. И спасибо за указание на прямое решение C++20. - person Ruslan; 10.09.2019
comment
Если s1 не начинается с s2, это все равно попытается сопоставить его впоследствии, что не так хорошо, как compare(). - person A117; 26.11.2019

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

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;
}
person 1800 INFORMATION    schedule 31.05.2009
comment
Ну, я знаю, как сравнивать строки с помощью функций C. Мой вопрос заключался в том, чтобы сделать это объектно-ориентированным способом с помощью C++ STL. - person jackhab; 31.05.2009
comment
Здесь не используется функция C. И Стандартная библиотека не запрещает вам писать свои собственные помазания. - person ; 31.05.2009
comment
а что, если t короче s? - person vidstige; 22.01.2013
comment
@jackhab Автор STL говорит, что STL не является объектно-ориентированным. Я думаю, что объектно-ориентированность — почти такой же обман, как и искусственный интеллект. -- stlport.org/resources/StepanovUSA.html - person Jim Balter; 06.11.2014
comment
@vidstige Затем цикл завершается, когда он встречает завершающий NUL в t. - person Jim Balter; 06.11.2014
comment
@JimBalter Это, наверное, самая глупая вещь, которую когда-либо говорил Стефанов. OOD/OOP преобладали в разработке систем в течение последних 20 лет благодаря своей беспрецедентной способности управлять сложностью. Общее программирование также стало повсеместным в то время, но оно, скорее всего, будет использоваться для внутренней реализации, а не для высокоуровневых компонентов и клиентских интерфейсов. Мы научились использовать их вместе. - person Neutrino; 16.02.2018
comment
@Neutrino Проблема не в том, прав Степанов или нет в отношении OO, а в том, является ли STL OO. (Это не так, конечно.) - person Jim Balter; 17.02.2018
comment
@JimBalter Я думаю, это спорно. Классы STL раскрывают свою функциональность через интерфейс, за которым они скрывают частную реализацию, и их можно составлять и создавать подклассы, как и другие типы ОО. Будучи универсальным, их интерфейс не полностью изолирует клиента от их реализации в той степени, в какой это было бы в случае неуниверсальной реализации, но я не думаю, что это означает, что они вообще не являются объектно-ориентированными. - person Neutrino; 19.02.2018
comment
Это не подлежит сомнению, когда его создатель говорит, что STL не является объектно-ориентированным... и когда приведенный выше аргумент - полная чепуха; тот факт, что контейнеры STL реализованы как классы C++, не делает STL OO. - person Jim Balter; 20.02.2018