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


90

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

Ответы:


164

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

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

if (s.compare(0, t.length(), t) == 0)
{
// ok
}

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;
}

Я знаю, как сравнивать строки при использовании функций C. Мой вопрос заключался в том, чтобы сделать это объектно-ориентированным способом с помощью C ++ STL.
jackhab

Здесь не используется функция C. Стандартная библиотека не мешает вам писать собственные объединения.

6
а что если t короче s?
vidstige

@jackhab Автор STL говорит: «STL не объектно-ориентированный. Я думаю, что объектно-ориентированность - это почти такая же обманка, как и искусственный интеллект». - stlport.org/resources/StepanovUSA.html
Джим Балтер

1
@vidstige Затем цикл завершается, когда он встречает завершающий NUL в t.
Джим Балтер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.