2016-04-08 14 views
6

をケース。検索文字列は、私は</p> <pre><code>std::vector<std::string> vec; std::string myString; </code></pre> <p>を持っていると私は<code>myString</code>が<strong>大文字小文字を区別しない</strong> comaprisonsを使用して<code>vec</code>であるかどうかを確認する必要が鈍感なC++

は、私が質問に答えるために

find(vec.begin(), vec.end(), myString) != vec.end()) 

を使用することができます知っている "VECにMYSTRINGですか?"大文字と小文字を区別した比較を行います。大文字と小文字を区別しない比較が必要です。

位置は重要ではありません。myStringがvecであるかどうかを知りたいだけです。

+0

は、このトリックを行う必要がありますか? [ここにリンクの説明を入力してください](http://stackoverflow.com/questions/14322299/c-stdfind-with-a-custom-comparator) – tomascapek

+0

[関連する質問](https://stackoverflow.com/questions/11635/case -insensitive-string-comparison-in-c)を使用します。 – jotik

答えて

2

あなたは比較を行うためにstd::find_if、インラインラムダとstd::tolowerを使用することがあります。

//Computing the lower version of mystring 
std::string my_string_lower; 
my_string_lower.reserve(mystring.size()); 
std::transform(mystring.begin(), mystring.end(), std::back_inserter(my_string_lower), ::tolower); 

// Checking if it is exist in the vector: 
auto is_exist = std::find_if(vec.begin(), vec.end(), [&my_string_lower](std::string item){ 
    //Transform the each vector item to lower temporally 
    std::transform(item.begin(), item.end(), item.begin(), ::tolower); 
    return mystring==item; 
}) != vec.end(); 

あなたは、文字列の同じvetorに何度も検索しようとしている場合は、一度それを計算した場合、それが良いだろう:

//Computing the lower version of the whole vector 
std::vector<std::string> vec_lower; 
vec_lower.reserve(vec.size()); 
std::transform(vec.begin(), vec.end(), std::back_inserter(vec_lower),[](std:string item){ 
    std::transform(item.begin(), item.end(), item.begin(), ::tolower); 
    return item; 
}); 

//Computing the lower version of mystring 
std::string my_string_lower; 
my_string_lower.reserve(mystring.size()); 
std::transform(mystring.begin(), mystring.end(), std::back_inserter(my_string_lower), ::tolower); 

// Checking if it is exist in the lower version of the vector: 
auto is_exist = std::find_if(vec_lower.begin(), vec_lower.end(), [&my_string_lower](const std::string& item){ 
    return mystring==item; 
}) != vec_lower.end(); 
+2

'std :: tolower'はstd ::文字列ではなくcharを取ります – marcinj

+0

これはUTF-8文字列では機能しませんのでご注意ください。 – Vincent

+0

@MarcinJędrzejewski編集中通知ありがとう –

3

std::find_ifを使用してカスタムコンパレータを用意する必要があります。大文字と小文字を区別しない比較を達成するには、比較したい両方の文字列を普通の大文字に変換することをお勧めします。

auto ret = std::find_if(vec.begin(), vec.end(), 
    [&myString](const std::string& s) { 
     if (s.size() != myString.size()) 
      return false; 
     return std::equal(s.cbegin(), s.cend(), myString.cbegin(), myString.cend(), [](auto c1, auto c2) { return std::toupper(c1) == std::toupper(c2); }); 
    }); 

これはmyStringは発生が見つからなかった場合vec.end()なりますイテレータを返します。それは次のようなコードにつながります。そのイテレーターで何でもできます(文字列が見つかったかどうかを知るためにvec.end()と比較することを含む)。

ボーナス:Coliru

+0

@jotik私は完全な声明を出したい返されたイテレータで彼が好きなことをすることができます。 – Rerito

+1

悪い、頭のおかげで、 – marcinj

+0

@MarcinJędrzejewski私は 'std :: toupper(std :: string&)'はありません。これは、 'vec.end()'と比較したり、出現回数(w/e)を数えるだけです。 – Rerito

4

に最小限の例を実行しているあなたはSTDを使用する必要があります:: TOLOWERとstd :: find_if:

std::vector<std::string> vec = {"ALF", "B"}; 
    std::string toSearch = "Alf"; 
    auto itr = std::find_if(vec.begin(), vec.end(), 
       [&](auto &s) { 
        if (s.size() != toSearch.size()) 
         return false; 
        for (size_t i = 0; i < s.size(); ++i) 
         if (::tolower(s[i]) == ::tolower(toSearch[i])) 
          return true; 
        return false; 
       } 
    ); 
    if (itr != vec.end()) { 
     std::cout << *itr << std::endl; 
    } 
+2

私はこの答えが好きですが...コードは実際には間違っています。修正するには 'if(std :: tolower [s]]!= std :: tolower(newServerName [i])) falseを返します。 return true; ' 比較を変更し、戻り値を入れ替えます。そうでなければ、最初の文字に一致するすべての文字列は等しいと見なされます。 –

2

あるいは、ずっと小さく、読みやすいためソリューション、Boost!

// #include <algorithm> 
// #include <boost/algorithm/string/predicate.hpp> 

const auto it = std::find_if(
    std::begin(vec), 
    std::end(vec), 
    [&myString](const auto& str) { return boost::iequals(myString, str); } 
); 

const bool found = (it != std::end(vec)); 
0
template <class T> 
long VecFindIgnoreCase(const std::vector<T>& vec, const std::string& sFind) { 
    return VecFindIgnoreCase(vec, sFind.c_str()); 
} 

template <class T> 
long VecFindIgnoreCase(const std::vector<T>& vec, const char* sFind) 
{ 
    for (std::vector<T>::const_iterator iter = vec.begin(); iter != vec.end(); ++iter) 
     if (_stricmp((*iter).c_str(), sFind) == 0) 
      return (long)std::distance(vec.begin(), iter); 
    return -1; 
} 

template <class T> 
long VecFindIgnoreCase(const std::vector<T>& vec, const std::wstring& sFind) { 
    return VecFindIgnoreCase(vec, sFind.c_str()); 
} 

template <class T> 
long VecFindIgnoreCase(const std::vector<T>& vec, const wchar_t* sFind) 
{ 
    for (std::vector<T>::const_iterator iter = vec.begin(); iter != vec.end(); ++iter) 
     if (_wcsicmp((*iter).c_str(), sFind) == 0) 
      return (long)std::distance(vec.begin(), iter); 
    return -1; 
} 

用途:

#include <string> 
#include <vector> 

void TestCode() 
{ 
    std::vector<std::string> strvecA; 
    std::vector<std::wstring> strvecW; 

    strvecA.push_back("abc"); 
    strvecA.push_back("def");    
    strvecA.push_back("ghi"); 
    strvecW.push_back(L"abc"); 
    strvecW.push_back(L"def"); 
    strvecW.push_back(L"ghi"); 

    long ind; 

    ind = VecFindIgnoreCase(strvecA, "ABC"); // ind = 0 found 
    ind = VecFindIgnoreCase(strvecA, "ghI"); // ind = 2 found 
    ind = VecFindIgnoreCase(strvecA, "Xyz"); // ind = -1 not found 

    ind = VecFindIgnoreCase(strvecW, L"aBc"); // ind = 0 found 
    ind = VecFindIgnoreCase(strvecW, L"DEF"); // ind = 1 found 
    ind = VecFindIgnoreCase(strvecW, L"xyZ"); // ind = -1 not found 

    std::string sFind("mno"); 
    if ((ind = VecFindIgnoreCase(strvecA, sFind)) >= 0) { 
     // found at strvecA[ind] 
    } else { 
     // not found 
    } 
} 
+0

コードが何をしているか十分な説明をしてください – Ibo

関連する問題

 関連する問題