如何检查字符是否在给定的字符范围内?

时间:2014-04-08 14:25:54

标签: c++ ascii

C ++:我如何检查字符是否在给定的字符范围之间?

说,如果我有一个字符串名称。 我想检查一下这个字符串的第一个字符是否在' a'之间。到' n'。

我该怎么办?

待办事项(姓名[0] ==' a')(姓名[0] ==' b')......太长了......

如果可能的话,我想要一个优雅地处理ASCII值的解决方案。

6 个答案:

答案 0 :(得分:7)

如果你想检查你的第一个字符是否在&#39; a&#39;之间。例如,检查name[0] >= 'a' && name[0] <= 'n'应正确完成工作。

但请注意,如果您还可以在信中使用大写字母作为第一个字符,则必须检查(name[0] >= 'a' && name[0] <= 'n') || (name[0] >= 'A' && name[0] <= 'N')

答案 1 :(得分:3)

您可以将std::all_oflambda expression

结合使用
std::all_of(name.begin(), name.end(), [](char i) { return (i >= 'a' && i <= 'z'); });

Live demo

这对于大多数应用程序来说都足够便携,因为字符集通常遵循ASCII约定实现,如§2.3/ 14中所述:

  

基本源字符集成员的字形旨在识别ISO / IEC 10646子集中与ASCII字符集对应的字符。但是,由于源文件字符到源字符集的映射(在转换阶段1中描述)被指定为实现定义,因此需要一个实现来记录源文件中基本源字符的表示方式。

上述算法的复杂性为O(n)。另一种方法(检查每个字符在k字符的字符范围内是一个)是O(n*k),但至少你可以确定它不是实现定义的。

答案 2 :(得分:2)

如果您确定平台上使用的字符集是ASCII,则可以使用以下内容:

if (std::all_of(name.begin(), name.end(), [](char c){return ((c >= 'a') && (c <= 'n'));}) ) {
    // name contains only characters between 'a' and 'n' inclusive
}

否则,这样的事情应该可以解决问题:

if (name.find_first_not_of("abcdefghijklmn") == std::string::npos) {
    // name contains only characters between 'a' and 'n' inclusive
}

答案 3 :(得分:1)

一种老式的便携式方法:

    bool is_in_range(char range_start, char range_end, char c)
    {
      static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
      unsigned int start_position = 0;
      unsigned int end_position = 0;
      unsigned int character_position = 0;
      c = std::tolower(c);
      for (unsigned int i = 0; i < sizeof(alphabet); ++i)
      {
         if (range_start == alphabet[i])
         {
            start_position = i;
         }
         if (range_end == alphabet[i])
         {
            end_position = i;
         }
         if (c == alphabet[i])
         {
            character_position = i;
         }
      }
      bool result = false;
      if (end_position <= start_position)
      {
        result = false;
      }
      else
      {
        if ((character_position >= start_position) && (character_position <= end_position))
        {
          result = true;
        }
      }
      return result;
}

答案 4 :(得分:0)

循环遍历字符串,使用str [i]&gt;&#39; a&#39;检查每个字符并查看它是否保持在a和n之间。和str [i]&lt;&#39; n&#39;

答案 5 :(得分:0)

对于连续的角色范围,您可以:

_Bool isbetween(int c, int start, int end){
  return ((unsigned)c-start < (end-start));
}

要考虑案例,请使用tolower()和小写范围:

static inline int tolower(int c){
  return c | ( ((unsigned)c-'A' < 26)<<5 );
}
//isbetween(tolower(x),'a','n');

对于非连续范围,您可能需要创建一个遮罩。在这个例子中,我将检查元音(为简洁起见,因为只有5个,但是可以使用32个范围内的任何组合或64个进行一些修改......  事实上,64位平台上的64位掩码将消除案例处理的需要。)

static const unsigned vowel_mask =  (1<<('a'-'a'))
  |(1<<('e'-'a'))|(1<<('i'-'a'))|(1<<('o'-'a'))|(1<<('u'-'a'));

int isvowel(int c){ //checks if c is a,A,e,E,i,I,o,O,u,U 
  unsigned x = (c|32)-'a';
  return ((x<32)<<x)&vowel_mask;
}

请注意,这些实现不包含分支;然而,使用无符号比较可能会阻止自动编译器矢量化(英特尔内在函数,不进行无符号比较)...如果这是您的目标,则可以使用2 & ed比较。根据字符的分隔距离,此方法可能适用于非ascii系统,也可能不适用。

GCC

isvowel:
        or      edi, 32     # tmp95,
        xor     eax, eax  # tmp97
        sub     edi, 97   # x,
        cmp     edi, 31   # x,
        setbe   al    #, tmp97
        shlx    eax, eax, edi   # tmp99, tmp97, x
        and     eax, 1065233      # tmp96,
        ret

isvowel: # @isvowel
  or edi, 32
  add edi, -97
  mov eax, 32
  xor ecx, ecx
  cmp edi, eax
  setb cl
  shlx eax, ecx, edi
  and eax, 1065233
  ret

ICC

isvowel:
  xor eax, eax #15.26
  or edi, 32 #14.23
  add edi, -97 #14.27
  cmp edi, 32 #15.26
  setb al #15.26
  shlx eax, eax, edi #15.23
  and eax, 1065233 #15.26
  ret #15.26

除标准stackoverflow许可证外,此代码还将发布到公共域