Проверьте, является ли одна строка префиксом другой - PullRequest
42 голосов
/ 27 октября 2011

У меня есть две строки, которые я хотел бы сравнить: String и String:. Есть ли библиотечная функция, которая возвращала бы true, если передать эти две строки, но false, например, для String и OtherString?

Если быть точным, я хочу знать, является ли одна строка префиксом другой.

Ответы [ 12 ]

49 голосов
/ 27 октября 2011

Использование std::mismatch.Передайте более короткую строку в качестве первого диапазона итератора и длиннее в качестве второго диапазона итератора.Возвращение - это пара итераторов, первый - итератор в первом диапазоне, а второй - во второй ярости.Если первый конец первого диапазона, то вы знаете, что короткая строка является префиксом более длинной строки, например

std::string foo("foo");
std::string foobar("foobar");

auto res = std::mismatch(foo.begin(), foo.end(), foobar.begin());

if (res.first == foo.end())
{
  // foo is a prefix of foobar.
}
18 голосов
/ 27 октября 2011

Если вы знаете, какая строка короче, процедура проста, просто используйте std::equal с первой более короткой строкой. Если нет, то вроде должно работать следующее:

bool
unorderIsPrefix( std::string const& lhs, std::string const& rhs )
{
    return std::equal(
        lhs.begin(),
        lhs.begin() + std::min( lhs.size(), rhs.size() ),
        rhs.begin() );
}
15 голосов
/ 27 октября 2011

std::string(X).find(Y) - ноль, если и только если Y - префикс X

9 голосов
/ 27 октября 2011

С string :: сравни , вы сможете написать что-то вроде:

bool match = (0==s1.compare(0, min(s1.length(), s2.length()), s2,0,min(s1.length(),s2.length())));

В качестве альтернативы, если мы не хотим использовать функцию-член length():

bool isPrefix(string const& s1, string const&s2)
{
    const char*p = s1.c_str();
    const char*q = s2.c_str();
    while (*p&&*q)
        if (*p++!=*q++)
            return false;
    return true;
}
6 голосов
/ 27 февраля 2014

Это и эффективно, и удобно:

str.compare(0, pre.size(), pre) == 0

compare быстрый, потому что он использует быстрый метод traits::compare и не должен копировать какие-либо данные.

Здесь он будет сравнивать std::min(str.size(), pre.size()) символов, но если символы в двух диапазонах равны, он также проверяет длину pre и возвращает ненулевое значение, если pre длиннее этого.

См. документацию на cplusplus.com.

5 голосов
/ 27 октября 2011

Как насчет:

bool prefix(const std::string& a, const std::string& b) {
  if (a.size() > b.size()) {
    return a.substr(0,b.size()) == b;
  }
  else {
    return b.substr(0,a.size()) == a;
  }
}

C ++, а не C, безопасно, просто, эффективно.

Протестировано с:

#include <string>
#include <iostream>

bool prefix(const std::string& a, const std::string& b);

int main() {
  const std::string t1 = "test";
  const std::string t2 = "testing";
  const std::string t3 = "hello";
  const std::string t4 = "hello world";
  std::cout << prefix(t1,t2) << "," << prefix(t2,t1) << std::endl;
  std::cout << prefix(t3,t4) << "," << prefix(t4,t3) << std::endl;
  std::cout << prefix(t1,t4) << "," << prefix(t4,t1) << std::endl;
  std::cout << prefix(t1,t3) << "," << prefix(t3,t1) << std::endl;

}
5 голосов
/ 27 октября 2011

Если , вы можете разумно игнорировать любые многобайтовые кодировки (скажем, UTF-8), тогда вы можете использовать strncmp для этого:

// Yields true if the string 's' starts with the string 't'.
bool startsWith( const std::string &s, const std::string &t )
{
    return strncmp( s.c_str(), t.c_str(), t.size() ) == 0;
}

Если вы настаиваете на использовании необычной версии C ++, вы можете использовать алгоритм std::equal (с дополнительным преимуществом, что ваша функция работает и для других коллекций, а не только для строк):

// Yields true if the string 's' starts with the string 't'.
template <class T>
bool startsWith( const T &s, const T &t )
{
    return s.size() >= t.size() &&
           std::equal( t.begin(), t.end(), s.begin() );
}
3 голосов
/ 03 июня 2013

Самый простой способ - использовать substr () и сравнить () функции-члены:

string str = "Foobar";
string prefix = "Foo";

if(str.substr(0, prefix.size()).compare(prefix) == 0) cout<<"Found!";
1 голос
/ 24 июля 2018

Вы можете использовать это:

для с ++ 14 или меньше

bool has_prefix
    (const std::string& str, const std::string& prefix)  {
    return str.find(prefix, 0) == 0;
}

для с ++ 17

//it's a little faster
auto has_prefix
    (const std::string& str, const std::string_view& prefix) -> decltype(str.find(prefix) == 0) {
    return str.find(prefix, 0) == 0;
}
0 голосов
/ 27 октября 2011

Что не так с «найти» и проверить результат для позиции 0?

string a = "String";
string b = "String:";

if(b.find(a) == 0)
{
// Prefix

}
else
{
// No Prefix
}
...