Вы получили довольно много ответов уже, но я решил добавить еще один:
bool ends_with(std::string const &a, std::string const &b) {
auto len = b.length();
auto pos = a.length() - len;
if (pos < 0)
return false;
auto pos_a = &a[pos];
auto pos_b = &b[0];
while (*pos_a)
if (*pos_a++ != *pos_b++)
return false;
return true;
}
Поскольку вы получили довольно много ответов, возможно, быстрый тест и обобщение результатов было бы целесообразно:
#include <iostream>
#include <string>
#include <vector>
#include <time.h>
#include <iomanip>
bool ends_with(std::string const &a, std::string const &b) {
auto len = b.length();
auto pos = a.length() - len;
if (pos < 0)
return false;
auto pos_a = &a[pos];
auto pos_b = &b[0];
while (*pos_a)
if (*pos_a++ != *pos_b++)
return false;
return true;
}
bool ends_with_string(std::string const& str, std::string const& what) {
return what.size() <= str.size()
&& str.find(what, str.size() - what.size()) != str.npos;
}
bool has_suffix(const std::string &str, const std::string &suffix)
{
return str.size() >= suffix.size() &&
str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}
bool has_suffix2(const std::string &str, const std::string &suffix)
{
bool index = str.find(suffix, str.size() - suffix.size());
return (index != -1);
}
bool isEndsWith(const std::string& pstr, const std::string& substr)
{
int tlen = pstr.length();
int slen = substr.length();
if (slen > tlen)
return false;
const char* tdta = pstr.c_str();
const char* sdta = substr.c_str();
while (slen)
{
if (tdta[tlen] != sdta[slen])
return false;
--slen; --tlen;
}
return true;
}
bool ends_with_6502(const std::string& str, const std::string& end) {
size_t slen = str.size(), elen = end.size();
if (slen <= elen) return false;
while (elen) {
if (str[--slen] != end[--elen]) return false;
}
return true;
}
bool ends_with_rajenpandit(std::string const &file, std::string const &suffix) {
int pos = file.find(suffix);
return (pos != std::string::npos);
}
template <class F>
bool test(std::string const &label, F f) {
static const std::vector<std::pair<std::string, bool>> tests{
{ "this is some text", false },
{ "name.txt.other", false },
{ "name.txt", true }
};
bool result = true;
std::cout << "Testing: " << std::left << std::setw(20) << label;
for (auto const &s : tests)
result &= (f(s.first, ".txt") == s.second);
if (!result) {
std::cout << "Failed\n";
return false;
}
clock_t start = clock();
for (int i = 0; i < 10000000; i++)
for (auto const &s : tests)
result &= (f(s.first, ".txt") == s.second);
clock_t stop = clock();
std::cout << double(stop - start)/CLOCKS_PER_SEC << " Seconds\n";
return result;
}
int main() {
test("Jerry Coffin", ends_with);
test("Dietrich Epp", has_suffix);
test("Dietmar", ends_with_string);
test("Roman", isEndsWith);
test("6502", ends_with_6502);
test("rajenpandit", ends_with_rajenpandit);
}
Результаты с НКУ:
Testing: Jerry Coffin 3.416 Seconds
Testing: Dietrich Epp 3.461 Seconds
Testing: Dietmar 3.695 Seconds
Testing: Roman 3.333 Seconds
Testing: 6502 3.304 Seconds
Testing: rajenpandit Failed
Результаты с VC++:
Testing: Jerry Coffin 0.718 Seconds
Testing: Dietrich Epp 0.982 Seconds
Testing: Dietmar 1.087 Seconds
Testing: Roman 0.883 Seconds
Testing: 6502 0.927 Seconds
Testing: rajenpandit Failed
Да, это были работают на идентичном оборудовании, да и я побежал их несколько раз, и пробовали различные варианты оптимизации с г ++, чтобы увидеть, если я мог бы получить его, по крайней мере, приходят вроде близко к VC++. Я не мог. У меня нет прямого объяснения того, почему g ++ производит гораздо худший код для этого теста, но я уверен, что он это делает.
Я подозреваю, что ваш вопрос имеет больше общего с именами файлов, чем строки, поэтому я хотел бы предложить вам искать решения, которые извлекают расширение имени файла в переносимым способом. Многие библиотеки поддерживают это. –
Возможный дубликат [Найти, если строка заканчивается другой строкой в C++] (http://stackoverflow.com/questions/874134/find-if-string-endswith-another-string-in-c) –