2015-11-01 2 views
-4

Я хочу найти префикс в строке. Я использую это:Есть ли альтернатива strncmp C++ 11, которая также работает?

if (s.substr (0, 7) == "prefix_") 
    ... 

В то время как это работает, относительно медленнее, чем strncmp, как показано на этом тесте:

#include <iostream> 
#include <chrono> 
#include <string> 
#include <string.h> 

int main() 
{ 
    std::string s = "prefix_this is a passing test that will always match"; 

    auto t0 = std::chrono::high_resolution_clock::now(); 
    for (int i = 0; i < 1000000; i++) 
    if (s.substr (0, 7) == "prefix_") 
     ; 

    auto t1 = std::chrono::high_resolution_clock::now(); 
    for (int i = 0; i < 1000000; i++) 
    if (! s.compare (0, 7, "prefix_", 0, 7)) 
     ; 

    auto t2 = std::chrono::high_resolution_clock::now(); 
    for (int i = 0; i < 1000000; i++) 
    if (! strncmp (s.c_str(), "prefix_", 7)) 
     ; 

    auto t3 = std::chrono::high_resolution_clock::now(); 

    std::cout << "[1] s.substr (0, 7) == \"prefix_\"   " 
      << std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count() 
      << " μs\n" 
      << "[2] ! strncmp (s.c_str(), \"prefix_\", 7) " 
      << std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count() 
      << " μs\n" 
      << "[3] ! s.compare (0, 7, \"prefix_\", 0, 7) " 
      << std::chrono::duration_cast<std::chrono::microseconds>(t3 - t2).count() 
      << " μs\n"; 
    return 0; 
} 

Я вижу этот спектакль, который удивил меня:

[1] s.substr (0, 7) == "prefix_"   33022 μs 
[2] ! strncmp (s.c_str(), "prefix_", 7) 32547 μs 
[3] ! s.compare (0, 7, "prefix_", 0, 7) 12953 μs 

Я бы предпочел использовать C++ 11, не отбрасывая обратно в libc, но результаты не очень хорошие.

+4

Я уверен, что нет абсолютно никакой неуклюжий компилятор выбирает, учитывая, что в результате из этих сравнений совершенно непривычны. – Puppy

+0

Что не так с опцией №3, точно? Кажется, что вы ищете? Что касается «сюрприза», # 1 создает временную строку, а # 2 должен выполнить дополнительную проверку для '\ 0' для каждого сравнения символов. –

+3

Можете ли вы предоставить ориентиры для 'strcmp', цель, которую вы также должны бить? –

ответ

11

Да.

Вы можете избежать строковое строительства с нижеследующим, который является фактический аналог strncmp:

if (s.compare(0, 7, "prefix_") == 0) {} 

В действительности, конечно, я бы рекомендовал не жестко прописывать это значение п.

Как всегда, просто потратив пять минут на использование стандартной ссылки на библиотеку goes a long way & hellip;

+3

На самом деле я только что заметил, что вы уже использовали это в своем вопросе. Так что теперь я очень смущен тем, что вы просите.«Привет, вот самый быстрый способ в C++ сравнить префикс строки. Как сравнить строковый префикс в C++?» wtf –

+0

oooh не знал о 's.compare' :) Я предполагаю, что было бы тривиально сделать что-то, что обертывает это и принимает' str_const', или использует трюк в конструкторе str_const, где вы берете ссылку на 'const char [] 'и вывести размер строкового литерала в качестве параметра шаблона –

+0

@ChrisBeck: Yesah –

1

Если вы можете использовать бустер (обязательное предупреждение), вы можете написать это также, как

if(boost::string_ref(s).substr(0, 7) == "prefix_") 
    ... 

В самом деле, это одна из его вводных примеров. Altenatively

if(boost::string_ref(s).starts_with("prefix_")) 
    ... 

Последняя отличается, в том, что не существует неопределенное поведение, если ваша строка на самом деле имеет менее 7 символов :)

+0

Я заново изобрел именно это для одного и того же варианта использования: D –

Смежные вопросы