2015-03-03 2 views
-1

Мне даны две строки s1, s2 и целое число i. Я хочу проверить, является ли подстрока s1, начинающаяся с индекса i той же длины, что и s2, равна s2. Я знаю, что это тривиально реализовать с небольшим циклом, но я бы предпочел использовать библиотечный метод, если он существует.Проверка подстроки C++

+0

[ 'станд :: строка :: find'] (http://en.cppreference.com/w/cpp/string/basic_string/find) может быть хорошим началом? –

+0

** Я хочу проверить, является ли подстрока s1, начинающаяся с индекса s1 той же длины, что и s2, равна s2 **. какие??? – thang

+0

@ethang Это довольно очевидно, что это индекс 'i'. В основном 's1.substr (i, s2.size()) == s2', но в идеале без временных ;-) – stefan

ответ

1

Как обсуждалось в комментариях, вот на месте решения, используя строку :: сравнить (http://www.cplusplus.com/reference/string/string/compare/)

s1.compare(i,s2.length(),s2)==0 

Какой бы бросить зЬй :: out_of_range исключение, если (я> = s1.length()) , В противном случае он работает. Для того, чтобы избежать исключений out_of_range, просто добавить что-то короткое замыкание сравнение:

(i<s1.length()) && (s1.compare(i,s2.length(),s2)==0) 
+0

Это, вероятно, достаточно хорошо. Это, вероятно, так же эффективно, как и получается. – JT1

0
bool is_sub_string=i <= s1.size() && s1.substr(i, s2.size()) == s2; 
+0

Это создает временную строку. Это действительно то, что вы хотите сделать, когда просто наблюдаете две строки? – stefan

1

Я бы сделал это с помощью std::equal с проверкой правильного размера. Таким образом, он непосредственно работает и для векторов. Проверка размеров необходимо избегать недействительных итераторов:

if (i + s2.size() > s1.size()) 
{ 
    return false; 
} 
auto s1beg = s1.cbegin() + i; 
auto s1end = s1.cbegin() + i + s2.size(); 
return std::equal(s1beg, s1end, s2.cbegin()); 

Если вы хотите, чтобы поддерживать любые диапазоны, используйте std::advance, чтобы создать начальный и конечный итератор:

auto s1beg = s1.cbegin(); 
std::advance(s1beg, i); 
auto s2end = s1beg; 
std::advance(s2beg, s2.size()); 

Вот demo for both strings and a list. Еще дизайн решения могут также допускать различные типы контейнеров.

+0

Я не думаю, что версия 'std :: advance' такая же общая, как вы думаете: однопроходные диапазоны (т.е. итераторы вперед) могут быть расширены, но когда вы это делаете, вы теряете возможность проверять полученные вами значения над. Для цикла с дополнительными проверками для концевых итераторов поддерживается любой диапазон. – MSalters

+0

@MSalters Согласно cppreference и моей интерпретации, это шоу отлично работает с итераторами вперед: http://en.cppreference.com/w/cpp/concept/ForwardIterator Можете ли вы привести пример, в котором это не удается? – stefan

+0

Извините, мой плохой: итераторы ввода не пересылают итераторы. Представьте себе итератор над 'std :: cin'. Если вы это сделаете, вы проигнорируете ввод, который вы не можете игнорировать последним. – MSalters

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