Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 不区分大小写的std::字符串集_C++_Stl - Fatal编程技术网

C++ 不区分大小写的std::字符串集

C++ 不区分大小写的std::字符串集,c++,stl,C++,Stl,如何在std::set中插入或搜索不区分大小写的字符串 比如说- std::set<std::string> s; s.insert("Hello"); s.insert("HELLO"); //not allowed, string already exists. std::set s; s、 插入(“你好”); s、 插入(“你好”)//不允许,字符串已存在。 std::set提供了提供您自己的比较器的可能性(大多数std容器也是如此)。然后,您可以执行任何类型的比较。完整示例

如何在std::set中插入或搜索不区分大小写的字符串

比如说-

std::set<std::string> s;
s.insert("Hello");
s.insert("HELLO"); //not allowed, string already exists.
std::set s;
s、 插入(“你好”);
s、 插入(“你好”)//不允许,字符串已存在。

std::set提供了提供您自己的比较器的可能性(大多数std容器也是如此)。然后,您可以执行任何类型的比较。完整示例可用

您需要定义自定义比较器:

struct InsensitiveCompare { 
    bool operator() (const std::string& a, const std::string& b) const {
        return strcasecmp(a.c_str(), b.c_str()) < 0;
    }
};

std::set<std::string, InsensitiveCompare> s;
struct InsensitiveCompare{
布尔运算符()(常数std::string&a,常数std::string&b)常数{
返回strcasecmp(a.c_str(),b.c_str())<0;
}
};
std::集s;

如果
straccmp
不可用,您可以尝试
stricmp
strcoll

据我所知,这比stricmp()更具可移植性,因为stricmp()实际上不是std库的一部分,但仅由大多数编译器供应商实现。因此,下面是我的解决方案,只是滚动你自己的

#include <string>
#include <cctype>
#include <iostream>
#include <set>

struct caseInsensitiveLess
{
  bool operator()(const std::string& x, const std::string& y)
  {
    unsigned int xs ( x.size() );
    unsigned int ys ( y.size() );
    unsigned int bound ( 0 );

    if ( xs < ys ) 
      bound = xs; 
    else 
      bound = ys;

    {
      unsigned int i = 0;
      for (auto it1 = x.begin(), it2 = y.begin(); i < bound; ++i, ++it1, ++it2)
      {
        if (tolower(*it1) < tolower(*it2))
          return true;

        if (tolower(*it2) < tolower(*it1))
          return false;
      }
    }
    return false; 
  }
};

int main()
{
  std::set<std::string, caseInsensitiveLess> ss1;
  std::set<std::string> ss2;

  ss1.insert("This is the first string");
  ss1.insert("THIS IS THE FIRST STRING");
  ss1.insert("THIS IS THE SECOND STRING");
  ss1.insert("This IS THE SECOND STRING");
  ss1.insert("This IS THE Third");

  ss2.insert("this is the first string");
  ss2.insert("this is the first string");
  ss2.insert("this is the second string");
  ss2.insert("this is the second string");
  ss2.insert("this is the third");

  for ( auto& i: ss1 )
   std::cout << i << std::endl;

  std::cout << std::endl;

  for ( auto& i: ss2 )
   std::cout << i << std::endl;

}

这是一个通用的解决方案,也适用于除
std::string
以外的其他字符串类型(使用
std::wstring
std::string\u视图
char const*
进行测试)。基本上,任何定义一组字符的东西都应该起作用

这里的关键点是使用它,它允许我们在比较器中统一处理以null结尾的字符数组、字符指针和范围

通用代码(“iset.h”):

#pragma once
#include <set>
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <boost/range/as_literal.hpp>

// Case-insensitive generic string comparator.
struct range_iless
{
    template< typename InputRange1, typename InputRange2 >
    bool operator()( InputRange1 const& r1, InputRange2 const& r2 ) const 
    {
        // include the standard begin() and end() aswell as any custom overloads for ADL
        using std::begin; using std::end;  

        // Treat null-terminated character arrays, character pointers and ranges uniformly.
        // This just creates cheap iterator ranges (it doesn't copy container arguments)!
        auto ir1 = boost::as_literal( r1 );
        auto ir2 = boost::as_literal( r2 );

        // Compare case-insensitively.
        return std::lexicographical_compare( 
            begin( ir1 ), end( ir1 ), 
            begin( ir2 ), end( ir2 ), 
            boost::is_iless{} );
    }
};

// Case-insensitive set for any Key that consists of a range of characters.
template< class Key, class Allocator = std::allocator<Key> >
using iset = std::set< Key, range_iless, Allocator >;
#include "iset.h"  // above header file
#include <iostream>
#include <string>
#include <string_view>

// Output range to stream.
template< typename InputRange, typename Stream, typename CharT >
void write_to( Stream& s, InputRange const& r, CharT const* sep )
{
    for( auto const& elem : r )
        s << elem << sep;
    s << std::endl;
}

int main()
{
    iset< std::string  >     s1{  "Hello",  "HELLO",  "world" };
    iset< std::wstring >     s2{ L"Hello", L"HELLO", L"world" };
    iset< char const*  >     s3{  "Hello",  "HELLO",  "world" };
    iset< std::string_view > s4{  "Hello",  "HELLO",  "world" };

    write_to( std::cout,  s1,  " " );    
    write_to( std::wcout, s2, L" " );    
    write_to( std::cout,  s3,  " " );    
    write_to( std::cout,  s4,  " " );    
}
#pragma一次
#包括

#包括

你能澄清一下“区分大小写插入”的含义吗?当我读到“不区分大小写比较”时,我不禁想起了我的岳母+1.如果字符串中有NUL字符,此方法将无法正常工作。参见.<代码> StimP不是标准C或C++,也不是POSIX或ANSI。它在GCC中不可用,但至少是标准POSIX,并且具有相同的签名。不过,使用
std::tolower()
编写您自己的实现非常简单。一句话:如果您使用的是希腊语文本,这将不起作用,因为通常不可能单独使用
tolower
实现不区分大小写的比较。教科书中关于这种不可能性的例子是∑∑∑,它不区分大小写,与∑∑∑∑∑(希腊语中的“多达”)相同。
#include "iset.h"  // above header file
#include <iostream>
#include <string>
#include <string_view>

// Output range to stream.
template< typename InputRange, typename Stream, typename CharT >
void write_to( Stream& s, InputRange const& r, CharT const* sep )
{
    for( auto const& elem : r )
        s << elem << sep;
    s << std::endl;
}

int main()
{
    iset< std::string  >     s1{  "Hello",  "HELLO",  "world" };
    iset< std::wstring >     s2{ L"Hello", L"HELLO", L"world" };
    iset< char const*  >     s3{  "Hello",  "HELLO",  "world" };
    iset< std::string_view > s4{  "Hello",  "HELLO",  "world" };

    write_to( std::cout,  s1,  " " );    
    write_to( std::wcout, s2, L" " );    
    write_to( std::cout,  s3,  " " );    
    write_to( std::cout,  s4,  " " );    
}