std :: порівняння рядків (перевірте, чи рядок починається з іншого рядка)


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)?
Франк Месірард,

5
@FranckMesirard: Це тому, що за замовчуванням порівняти спробує порівняти всю довжину переданого рядка з даними-членами і поверне false, а якщо вказати довжину як довжина переданого параметра, це поверне істину (мається на увазі std :: basic_string :: порівняння , коли використовується зі зміщенням і довжиною, можна використовувати як String.BeginsWith () в інших бібліотеках.) Без зміщення та довжини це не було б правдою.
legends2k

1
Це повертає true, якщо t порожнє.
gliderkite

14
@gliderkite Як слід ... порожній рядок є початковим префіксом кожного рядка.
Jim Balter

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

Це забезпечує простіший інтерфейс до коду клієнта і сумісний з більшістю контейнерів Standard Library.


Класно! Це слід додати для підвищення!
Девід

2
@David: Якщо boost є дозволеною залежністю, див. Boost :: algorithm :: start_with - "Починається з" предиката
Gabor

10

Зверніться до бібліотеки String Algo Boost , яка має ряд корисних функцій, таких як 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, це все одно спробує зрівняти його згодом, що не так добре, як порівняння ().
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.
Jim Balter
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.