Вычисление длины строки с кирилицей

AlexMik
Offline
Зарегистрирован: 15.09.2019

Необходимо рассчитать длину строки с кирилицей.

Делаю так:

byte rusStrlen(const char * str)
{
  byte i,count=0;
  while (str[i] != '\0') 
  {
    if (str[i] < ' ') i=i+2;
    else i++;
    count++;
  }
  //memset(str, 0, sizeof(str));
  return count;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  
  String txtMsg_01 = "ПЕРВАЯ СТР";
  String txtMsg_02 = "SECOND STR";
 

  Serial.println(rusStrlen(txtMsg_01.c_str()));
  Serial.println(rusStrlen(txtMsg_02.c_str()));


  lcd.init();// Инициализация дисплея
  lcd.backlight();
  lcd.setCursor(7 - rusStrlen(txtMsg_01.c_str()) / 2, 0);
  lcd.print(txtMsg_01);
  lcd.setCursor(7 - (rusStrlen(txtMsg_02.c_str()) / 2), 1);
  lcd.print(txtMsg_02);
  delay (3500);
  
  Serial.println(rusStrlen(txtMsg_01.c_str()));
  Serial.println(rusStrlen(txtMsg_02.c_str()));
}

void loop() {
  // put your main code here, to run repeatedly:
}

Работает абы как и абы что. Ткните носом пожалуйста.

Зацепило, блин. Хочу добить этот вопрос.

То, что читал в нете (по данному вопросу) к решению пока не привело.

negavoid
Offline
Зарегистрирован: 09.07.2016

Дайте угадаю, у "SECOND STR" возвращается 9, а у "ПЕРВАЯ СТР" - 18?

Во-первых, в строке 6 длина считается без пробелов. Во-вторых, "ПЕРВАЯ СТР" хранится в кодировке utf8, и 1 символ занимает два байта (а может от 1 до 4, они переменной длины, у кириллицы - двухбайтовые символы, у латиницы - однобайтовые, у всяких смайликов - трёхбайтовые).

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Храните строки в массиве char в кодировке win1251 - всегда будете знать длину, с выводите уже в нужном формате переводя online

anarch
Offline
Зарегистрирован: 10.09.2017

А чем length() не устраивает?

b707
Offline
Зарегистрирован: 26.05.2017

В общем виде, без привязки к кодировке - вопрос вообще не имеет решения. Для разных кодировок методика вычисления длины строки будет разной.

В данном случае я не вполне понимаю, что за кодировку использует ТС. В кодировке UTF8 русские буквы имеют первый байт 0xD0 или 0xD1 - и непонятно, как у автора сравнение с пробелом помогает определить кириллицу...

negavoid
Offline
Зарегистрирован: 09.07.2016

А никак, это чтобы пробел и от 0х00 до 0х20 не считать, хотя - зачем? :)

AlexMik
Offline
Зарегистрирован: 15.09.2019

andycat пишет:
Храните строки в массиве char в кодировке win1251 - всегда будете знать длину, с выводите уже в нужном формате переводя online

Буду очень благодарен за ссылку. Или пример.

Заранее спасибо.

b707
Offline
Зарегистрирован: 26.05.2017

negavoid пишет:

А никак, это чтобы пробел и от 0х00 до 0х20 не считать, хотя - зачем? :)

не, посмотрите на строчки 6 и 7 в его коде. Если символ меньше пробела - он считается длиной в два байта. если больше пробела - один байт. В принципе, подход верный. я только не пойму почему именно пробел. поэтому и спрашиваю - что за кодировка у ТС

 

negavoid
Offline
Зарегистрирован: 09.07.2016

Да вроде не пятница же ж )) Если символ меньше пробела, то следующий чар пропустить, а если больше или равно, то продолжаем по порядку, и только потом count++.

russtrlen("test\1test") поидее вернёт 8, russtrlen("test\1\2\3\4test") - 10, а russtrlen("test test\1") поидее скажет хрю.

AlexMik
Offline
Зарегистрирован: 15.09.2019

Ок. Все. Переписал функцию rusStrlen(const char * str) и все заработало.

Вопрос снят.

Тупо было нужно для подсчета длины строки символов.

Считает. Как смешанные, так и чисто на русском или английском или символами.

Возможно выплывут косяки, но это уже завтра. ))