C ++:不区分大小写的前n个字符的字符串比较

问题描述

|| 我的问题与此类似,但是我有两个字符串(如
char *
),任务是将
strnicmp
函数(仅适用于MS VC)替换为
boost::iequals
。 注意
strnicmp
不是
stricmp
-它仅比较前n个字符。 有没有比这更简单的解决方案了:
void foo(const char *s1,const char *s2) 
{
    ...

    std::string str1 = s1;
    std::string str2 = s2;
    int n = 7;

    if (boost::iequals(str1.substr(0,n),str2)) {
        ...
    }
}
    

解决方法

如果确实需要,请编写自己的函数:
bool mystrnicmp(char const* s1,char const* s2,int n){
  for(int i=0; i < n; ++i){
    unsigned char c1 = static_cast<unsigned char>(s1[i]);
    unsigned char c2 = static_cast<unsigned char>(s2[i]);
    if(tolower(c1) != tolower(c2))
      return false;
    if(c1 == \'\\0\' || c2 == \'\\0\')
      break;
  }
  return true;
}
    ,为了不区分大小写,您需要一个自定义比较功能 (或函子):
struct EqIgnoreCase
{
    bool operator()( char lhs,char rhs ) const
    {
        return ::tolower( static_cast<unsigned char>( lhs ) )
            == ::tolower( static_cast<unsigned char>( rhs ) );
    }
};
如果我理解正确,那么您正在检查前缀。的 最简单的方法是:
bool
isPrefix( std::string const& s1,std::string const& s2 )
{
    return s1.size() <= s2.size()
        && std::equals( s1.begin(),s1.end(),s2.begin(),EqIgnoreCase() );
}
(请注意尺寸检查。如果是,则
s1
不能是
s2
的前缀 比longer10长。当然,
std::equals
会 如果调用
s1
的时间长于,则会遇到不确定的行为
s2
。)     ,对于用C字符串(字符指针)定义的函数,将STL字符串“向上”运行似乎效率极低,但是我认为这完全是不成熟的想法。 我会考虑直接的C解决方案“更简单”,但这再次取决于人的观点。
#include <ctype.h>

void foo(const char *s1,const char *s2)
{
  size_t i,n = 7;

  for(i = 0; i < n; i++)
  {
    if(tolower(s1[i]) != tolower(s2[i]))
      return;
    if(s[i] == \'\\0\' && s2[i] == \'\\0\')
      break;
  }
  /* Strings are equal,do the work. */
  ...
}
假设如果两个字符串都在前缀长度用尽之前结束,则表示匹配。 当然,上面假设ASCII字符串,其中ѭ16才有意义。     ,我建议自己编写函数,如下所示:
bool strnicmp2(const char *s,const char *t,size_t n) {
    while (n > 0 && *s && *t && tolower(*s) == tolower(*t)) {
        ++s;
        ++t;
        --n;
    }
    return n == 0 || !*s || !*t;
}
    ,这样的事情应该起作用。
#include <iostream>
#include <string>
#include <cctype>
#include <cstring>
#include <algorithm>

struct isequal
{
  bool operator()(int l,int r) const
  {
    return std::tolower(l) == std::tolower(r);
  }
};

bool istrncmp(const char* s1,const char* s2,size_t n)
{
  size_t ls1 = std::strlen(s1);
  size_t ls2 = std::strlen(s2);
  // this is strict,but you can change
  if (ls1 < n || ls2 < n)
    return false;

  return std::equal(s1,s1 + n,s2,isequal()); 
}

int main(void)
{
  std::cout << istrncmp(\"fooB\",\"fooA\",3) << std::endl;
  std::cout << istrncmp(\"fooB\",5) << std::endl;
  std::cout << istrncmp(\"fooB\",\"f1oA\",3) << std::endl;
  return 0;
}
    ,我不知道这算不算简单,但是它的行数更少,速度应该还不错。
#include <boost/iterator/transform_iterator.hpp>
#include <algorithm>
#include <cctype>

bool equal_insensitive_n( char const *a,char const *b,size_t n ) {
    n = std::min( n,std::min( ::strlen( a ) + 1,::strlen( b ) + 1 ) );
    #define tilc(S) boost::make_transform_iterator( (S),::tolower )
    return std::equals( tilc(a),tilc(a) + n,tilc(b) );
    #undef tilc
}