簡體   English   中英

如何檢查字符是否在給定的字符范圍內?

[英]How do I check if a character is in a given range of characters?

C ++:如何檢查字符是否在給定范圍的字符之間?

說,如果我有一個字符串名稱。 我想檢查這個字符串的第一個字符是否在'a'到'n'之間。

我該怎么做?

要做(名稱[0] =='a')(名稱[0] =='b')...太長了...

如果可能的話,我想要一個優雅地處理ASCII值的解決方案。

例如,如果要檢查字符串的第一個字符是否在“a”和“n”之間,檢查name[0] >= 'a' && name[0] <= 'n'應該執行工作得當。

但請記住,如果你也可以在封信中加上大寫作為第一個字符,你必須檢查(name[0] >= 'a' && name[0] <= 'n') || (name[0] >= 'A' && name[0] <= 'N') (name[0] >= 'a' && name[0] <= 'n') || (name[0] >= 'A' && name[0] <= 'N')

您可以將std::all_oflambda表達式結合使用:

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

現場演示

這對於大多數應用程序來說足夠便攜,因為字符集通常遵循ASCII約定來實現,如§2.3/ 14中的解釋:

基本源字符集成員的字形旨在識別ISO / IEC 10646子集中對應於ASCII字符集的字符。 但是,由於源文件字符到源字符集(在轉換階段1中描述)的映射被指定為實現定義,因此需要實現來記錄源文件中基本源字符的表示方式。

上述算法的復雜性為O(n) 另一種方法(在k字符的字符范圍內檢查每個字符為1)是O(n*k) ,但至少可以確定它不是實現定義的。

如果您確定平台上使用的字符集是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
}

一種老式的便攜方法:

    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;
}

循環遍歷字符串,檢查每個字符,看看它是否使用str [i]>'a'和str [i] <'n'保持在a和n之間

對於連續的角色范圍,您可以:

_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許可證之外,此代碼還將發布到Public Domain

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM