比較したい2つの文字列があります:String
とString:
。これらの2つの文字列を渡したときにtrueを返すライブラリ関数がありますが、たとえばString
およびOtherString
に対してfalseを返しますか?
正確には、ある文字列が別の文字列のプレフィックスであるかどうかを知りたいです。
使用する - std::mismatch
。短い文字列を最初の反復子範囲として渡し、長い文字列を2番目の反復子範囲として渡します。戻り値はイテレータのペアです。最初のイテレータは最初の範囲のイテレータで、2番目は2番目の範囲のイテレータです。最初が最初の範囲の終わりであれば、短い文字列が長い文字列の接頭辞であることがわかります。
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.
}
どの文字列が短いかがわかっている場合、手順は簡単です。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() );
}
std::string(X).find(Y)
は、Y
がX
の接頭辞である場合にのみゼロです。
string :: compare を使用すると、次のような記述ができるはずです。
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;
}
これは効率的で便利です。
_str.compare(0, pre.size(), pre) == 0
_
compare
は高速な_traits::compare
_メソッドを使用し、データをコピーする必要がないため高速です。
ここでは、std::min(str.size(), pre.size())
文字を比較しますが、2つの範囲の文字が等しい場合、pre
の長さもチェックし、pre
が0でない場合、ゼロ以外の値を返します。これよりも長い。
Cplusplus.comの ドキュメント を参照してください。
単純にどうですか:
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;
}
マルチバイトエンコーディング(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() );
}
最も簡単な方法は、substr()およびcompare()メンバー関数を使用することです:
string str = "Foobar";
string prefix = "Foo";
if(str.substr(0, prefix.size()).compare(prefix) == 0) cout<<"Found!";
これを使用できます:
c ++ 14以下の場合
bool has_prefix
(const std::string& str, const std::string& prefix) {
return str.find(prefix, 0) == 0;
}
c ++ 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;
}
str1のインデックス0でstr2全体が見つかった場合、str1.find(str2)は0を返します。
#include <string>
#include <iostream>
// does str1 have str2 as prefix?
bool StartsWith(const std::string& str1, const std::string& str2)
{
return (str1.find(str2)) ? false : true;
}
// is one of the strings prefix of the another?
bool IsOnePrefixOfAnother(const std::string& str1, const std::string& str2)
{
return (str1.find(str2) && str2.find(str1)) ? false : true;
}
int main()
{
std::string str1("String");
std::string str2("String:");
std::string str3("OtherString");
if(StartsWith(str2, str1))
{
std::cout << "str2 starts with str1" << std::endl;
}
else
{
std::cout << "str2 does not start with str1" << std::endl;
}
if(StartsWith(str3, str1))
{
std::cout << "str3 starts with str1" << std::endl;
}
else
{
std::cout << "str3 does not start with str1" << std::endl;
}
if(IsOnePrefixOfAnother(str2, str1))
{
std::cout << "one is prefix of another" << std::endl;
}
else
{
std::cout << "one is not prefix of another" << std::endl;
}
if(IsOnePrefixOfAnother(str3, str1))
{
std::cout << "one is prefix of another" << std::endl;
}
else
{
std::cout << "one is not prefix of another" << std::endl;
}
return 0;
}
出力:
str2 starts with str1
str3 does not start with str1
one is prefix of another
one is not prefix of another
strncmp
が探しているものに最も近いと思います。
言い換えれば、strstr(s2,s1)==s2
を探しているかもしれませんが、これは必ずしもそれを行うための最もパフォーマンスの高い方法ではありません。しかし、あなたはn
;-)を解決したくない
わかりました、わかりました、c ++バージョンは!s1.find(s2)
になります。
さて、std::mismatch(s1.begin(),s1.end(),s2.begin()).first==s1.end()
のように、さらにc ++にすることができます。
「検索」と位置0の結果の確認の何が問題になっていますか?
string a = "String";
string b = "String:";
if(b.find(a) == 0)
{
// Prefix
}
else
{
// No Prefix
}