Проверить, является ли символ русской буквой

Я использую кодировку UTF8 и setlocale(LC_ALL, "russian") В строке лежат символы, надо найти все, являющиеся русскими буквами. Как это сделать? Я уже пробовал делать строку из этого символа и подобные методы, но если просто "оторвать" символ, записанный в UTF8 от остальной строки, то получится неизвестно что, тк коды часто не влезают в один байт. Единственное решение, которое я нашел, использует std::wstring, но хотелось бы как-нибудь обойтись без него. Возможно ли?


Ответы (1 шт):

Автор решения: avp

Вот простой пример, как это сделать

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>


// Returns Unicode of cyrillic or 0
// see https://jrgraphix.net/r/Unicode/0400-04FF
int
is_rus_letter (const char *s, int only_rus)
{
  if ((*s & 0xe0) != 0xc0)
    return 0;
  if ((s[1] & 0xc0) != 0x80)
    return 0;
  uint32_t uc = ((s[0] & 0x1f) << 6) | (s[1] & 0x3f); // 5 bits `s[0]` and 6 bits `s[1]`

  if (uc < 0x400 || uc > 0x4ff)
    return 0; // not cyrillic
  if (only_rus) 
    if ((uc < 0x410 || uc > 0x44f) && // А - Я; а - я
        !(uc == 0x401 || // Ё
          uc == 0x451)) // ё
      return 0;
        
  return uc;
}

int
main (int ac, char *av[])
{

  char s[LINE_MAX + 1];

  printf("enter lines (not longer %d bytes)\n", LINE_MAX);
  while (fgets(s, LINE_MAX, stdin)) {
    int n = 0;
    for (int i = 0; s[i]; i++) {
      int uc;
      if ((uc = is_rus_letter(s + i, 1))) {
        n++;
        char r[3]; r[0] = s[i], r[1] = s[i + 1]; r[2] = 0;
        printf("in pos %d rus 0x%03x '%s'\n", i, uc, r);
      }
    }
    printf("%d rus letters\n", n);
  }
  
  return puts("End") == EOF;
}

Если что-то не понятно, спрашивайте

→ Ссылка