проверить, начинается ли строка с другой строки: найти или сравнить? - PullRequest
14 голосов
/ 13 октября 2011

Если вы хотите знать, начинается ли строка с другой, как бы вы сделали это в C ++ / STL?В Java есть String.startsWith, в Python также есть string.startwith, у STL нет прямого метода для этого.Вместо этого есть std::string::find и std::string::compare.До сих пор я использовал оба метода, в основном в зависимости от моего текущего настроения:

if ( str1.compare( 0, str2.length(), str2 ) == 0 )
    do_something();
if ( str1.find(str2) == 0 )
    do_something();

Конечно, вы также можете сделать str.substr(0,str2.length()) == str2, может быть, есть и другие способы добиться того же.find немного удобнее, чем compare, но я видел, как все больше людей рекомендуют compare, что find.

Но какой из них предпочтителен ?Есть ли разница в производительности?Это зависит от реализации (GCC, VC ++ и т. Д.)?

Ответы [ 5 ]

14 голосов
/ 13 октября 2011

Недостаток find состоит в том, что если str1 длинный, то он будет бессмысленно искать по нему str2.Я никогда не замечал, чтобы оптимизатор был достаточно умен, чтобы понимать, что вас волнует только результат 0 или нет, и прекращать поиск после начала str1.

. Недостаток compare заключается в том, что вынужно проверить, что str2.length() не больше str1.length() (или перехватить результирующее исключение и обработать его как ложный результат).

Неутешительно, что ближе всего к тому, что вы хотите в стандартной библиотеке, это std::strncmp (и, конечно, вам нужно использовать c_str() с этим), следовательно, вам нужно boost::starts_with или ваш собственный эквивалент, который включает проверки границ.

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

boost имеет алгоритм starts_with, который реализует его довольно эффективно: http://www.boost.org/doc/libs/1_41_0/doc/html/boost/algorithm/starts_with.html

Нет никаких требований относительно того, как реализации STL должны реализовывать поиск или сравнение, кроме стандартных вещей (возвращаемых значений ...), так что это полностью зависит от реализации.

8 голосов
/ 13 октября 2011

Поскольку find() может потребоваться поиск по всему string, несмотря ни на что, вы можете обернуть compare() следующим образом, если хотите:

#include <iostream>
#include <string>
using namespace std;

bool starts_with(const string& s1, const string& s2) {
    return s2.size() <= s1.size() && s1.compare(0, s2.size(), s2) == 0;
}

int main() {
    const string s("zipzambam");
    cout << starts_with(s, "zip") << endl;
}
2 голосов
/ 13 октября 2011

find, возможно, придется искать всю строку в поисках совпадений, даже если первый символ не совпадает, поэтому я бы предложил compare, или, как упоминалось @Foo Bah, вы могли бы использовать алгоритм starts_with boost.

1 голос
/ 13 октября 2011

Вы можете попробовать std::mismatch, единственная глупость в этом алгоритме заключается в том, что вы должны убедиться, что первый диапазон меньше или равен второму диапазону.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...