Сравнение wstring с игнорированием регистра

Размер чисел, участвующих в вычислениях с плавающей запятой, не является самым важным. Это расчет, который выполняется, который имеет отношение к делу.

По сути, если вы выполняете вычисление, а результатом является иррациональное число или повторяющееся десятичное число, то при округлении этого числа в используемую вами структуру данных конечного размера будут возникать ошибки округления. Поскольку double в два раза больше числа с плавающей точкой, ошибка округления будет намного меньше.

В тестах могут быть специально использованы числа, которые могут вызвать такую ​​ошибку, и поэтому проверено, что вы использовали соответствующий тип в своем коде.

19
задан Naveen 1 July 2009 в 09:16
поделиться

8 ответов

Если вы не против привязки к реализации Microsoft, вы можете использовать эту функцию, определенную в

int _wcsnicmp(
   const wchar_t *string1,
   const wchar_t *string2,
   size_t count 
);

. Но если вам нужно наилучшее соотношение производительности / совместимости / функциональности вам, вероятно, придется взглянуть на библиотеку ускорения (в любом случае часть ее - stl). Простой пример (взят из другого ответа на другой вопрос):

#include <boost/algorithm/string.hpp>

std::wstring wstr1 = L"hello, world!";
std::wstring wstr2 = L"HELLO, WORLD!";

if (boost::iequals(wstr1, wstr2))
{
    // Strings are identical
}
28
ответ дан 30 November 2019 в 03:08
поделиться

Если вам нужно, чтобы строка всегда выполняла сравнение без учета регистра (при использовании операторов == или! =), То возможное элегантное решение - переопределить метод char_traits :: compare.

Определите свою собственную структуру. Пример

struct my_wchar_traits: public std::char_traits< wchar_t>
{
    static int compare( const char_type* op1, const char_type* op2, std::size_t num) 
    {
       // Implementation here... any of the previous responses might help...
    } 
};

Затем определите свою собственную строку без учета регистра:

typedef std::basic_string< wchar_t, my_wchar_traits> my_wstring;
1
ответ дан 30 November 2019 в 03:08
поделиться

Кстати об английском? хотя я бы выбрал свой прекрасный Boost :)

bool isequal(const std::wstring& first, const std::wstring& second)
{
    if(first.size() != second.size())
        return false;

    for(std::wstring::size_type i = 0; i < first.size(); i++)
    {
        if(first[i] != second[i] && first[i] != (second[i] ^ 32))
            return false;
    }

    return true;
}
2
ответ дан 30 November 2019 в 03:08
поделиться

Использование стандартной библиотеки:

bool comparei(wstring stringA , wstring stringB)
{
    transform(stringA.begin(), stringA.end(), stringA.begin(), toupper);
    transform(stringB.begin(), stringB.end(), stringB.begin(), toupper);

    return (stringA == stringB);
}

wstring stringA = "foo";
wstring stringB = "FOO";
if(comparei(stringA , stringB))
{
    // strings match
}
6
ответ дан 30 November 2019 в 03:08
поделиться

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

http://www.boost.org/doc/libs/1_39_0/doc/html/string_algo.html

2
ответ дан 30 November 2019 в 03:08
поделиться

Вы можете использовать std :: tolower () для преобразования строк в нижний регистр или использовать функцию wcscasecmp , чтобы выполнить сравнение без учета регистра в c_str () .

Вот функтор сравнения, который вы также можете использовать напрямую:

struct ci_less_w
{
  bool operator() (const std::wstring & s1, const std::wstring & s2) const
  {
      #ifndef _WIN32
            return wcscasecmp(s1.c_str(), s2.c_str()) < 0;
      #else
            return _wcsicmp(s1.c_str(), s2.c_str()) < 0;
      #endif
  }
};
3
ответ дан 30 November 2019 в 03:08
поделиться
#include <algorithm>
#include <string>
#include <cstdio>


 bool icase_wchar_cmp(wchar_t a, wchar_t b)
{
  return std::toupper(a) == std::toupper(b);
}


bool icase_cmp(std::wstring const& s1, std::wstring const& s2)
{
  return (s1.size() == s2.size()) &&
             std::equal(s1.begin(), s1.end(), s2.begin(),
                              icase_wchar_cmp);
}



int main(int argc, char** argv)
{
  using namespace std;

  wstring str1(L"Hello"), str2(L"hello");

  wprintf(L"%S and %S are %S\n", str1.c_str(), str2.c_str(),
              icase_cmp(str1,str2) ? L"equal" : L"not equal");

  return 0;
}
2
ответ дан 30 November 2019 в 03:08
поделиться

Вы можете использовать mismatch () или lexicographic_compare (). Это предлагает Скотт Мейерс в Effecitve STL, пункт 35.

-1
ответ дан 30 November 2019 в 03:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: