Помогите разобраться, что за глюк co string.length()

MaksVV
Offline
Зарегистрирован: 06.08.2015

открываю новый скетч, копирую в это окно данный скетч

String message = "Привет!!!";

void setup() {
  
  Serial.begin (9600);
  Serial.println (message.length(), HEX);}

void loop() {}

В момент загрузки предлагает сохранить скетч, отказываюсь, то есть загружаю в ардуино без сохранения на компе. В мониторе порта при этом как положено показывает "9"

Потом сохраняю скетч на компьютере, загружаю в ардуино, в мониторе порта после сохранения на компе и загрузки в дуню начинает показывать "F". Чё за хрень может быть? 

Комп перезагружал, IDE обновил, фантазия кончилась  

Пол дня убил чтоб найти в большом скетче , что length косячит.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

С кодировкой разберитесь.  При сохранении она у Вас изменяет кодировку и русские буквы начинают по два байта занимать, а length выдаёт длину строки не в символах, а в байтах, вот 15 и получается. Сами посчитайте. Всё правильно.

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

MaksVV пишет:

Пол дня убил чтоб найти в большом скетче , что length косячит.

я тут не при делах(с) #153

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

ЕвгенийП пишет:

 При сохранении она у Вас изменяет кодировку и русские буквы начинают по два байта занимать

спасибо, не думал что так IDE может действовать

MaksVV
Offline
Зарегистрирован: 06.08.2015

а как можно в символах посчитать? может есть и такая функция ?

MaksVV
Offline
Зарегистрирован: 06.08.2015

ЕвгенийП пишет:
а length выдаёт длину строки не в символах, а в байтах, вот 15 и получается. Сами посчитайте. Всё правильно.

я почему впарился, потому как описание здесь читал

 

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

MaksVV пишет:

а как можно в символах посчитать? может есть и такая функция ?

так оно и считает в символах - открой скетч и прочитай свой "Привет!!!":

Привет!!!       // было 9 символов
Привет!!! // стало 15 символов

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

блин, есть возможность по простому подсчитать строку (количество байт например), в которой смесь русских и латинских символов?0 Чтоб на каждый неважно рус или лат по два байта приходилось, ну или по одному байту  и на рус и на лат( тогда получается в данном случае считаем количество символов)  

MaksVV
Offline
Зарегистрирован: 06.08.2015

Клапауций 112 пишет:

так оно и считает в символах - открой скетч и прочитай свой "Привет!!!":

Привет!!!       // было 9 символов
Привет!!! // стало 15 символов

 

мне нужно как то сделать чтоб либо 9 показывал, либо 18

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

MaksVV пишет:

я почему впарился, потому как описание здесь читал

 

под символом подразумевается char, а не то, что ты видишь в текстовом редакторе и что тебе напереводили местные туземцы.

char == 1 байт

MaksVV
Offline
Зарегистрирован: 06.08.2015

это я понял. Есть идеи как мне задачу решить?, кроме заливания скетча сначала в новое окно

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

MaksVV пишет:

это я понял. Есть идеи как мне задачу решить?, кроме заливания скетча сначала в новое окно

сохрани скетч в кодировке кириллица-1251

b707
Онлайн
Зарегистрирован: 26.05.2017

MaksVV пишет:

это я понял. Есть идеи как мне задачу решить?, кроме заливания скетча сначала в новое окно

не использовать в программе кириллицу вообще. По хорошему говоря, в скетче на микроконтроллере она ни к чему.

Это будет самый простой и безглючный вариант, любой другой будет существенно сложнее.

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Цель скетча отправка смс на русском языке. В формате PDU. Поиск результатов не дал. До конца вроде как никто не довел этцу тему, по крайней мере я не нашел рабочий скетч.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Там нужно сосчитать длину текстовой части в байтах и длину закодированной части номера телефона. Изврат полнейший

b707
Онлайн
Зарегистрирован: 26.05.2017

Если строчки известны и они короткие, можно заранее задать их в HEX

Например "Привет" в кодировке Win-1251 будет

char privet[] = {0xcf,  0xf0, 0xe8, 0xe2, 0xe5, 0xf2, 0x00};

 

Ну и в принципе, есть примеры PDU_decode - значит можно написать и encode

andriano
andriano аватар
Онлайн
Зарегистрирован: 20.06.2015

MaksVV пишет:
Цель скетча отправка смс на русском языке. В формате PDU. Поиск результатов не дал. До конца вроде как никто не довел этцу тему, по крайней мере я не нашел рабочий скетч.

Я думаю, Ваш скетч - не писатель, из головы сочинять не будет. А будет несколько заранее заготовленных фраз. Вот длины этих фраз посчитать где-то вне Ардуино и внести нужные цифры в Ваш скетч. Вероятнее всего, длины нужно считать в формате PDU. Это наиболее прямой и подходящий для микроконтроллера способ.

В принципе, считать совсем необязательно глазками/ручками, можно написать для этого специальную программу на ПК. 

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

MaksVV пишет:
Поиск результатов не дал. До конца вроде как никто не довел этцу тему, по крайней мере я не нашел рабочий скетч.

шо?! опять не дают упыри рабочий скетч? #155 О_О

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

а типа wchar_t в AVR нетю?

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

DetSimen пишет:

а типа wchar_t в AVR нетю?

при чём тут AVR, если сабж о том, что длина строки меряется в байтах, а не символах?

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

MaksVV пишет:
Там нужно сосчитать длину текстовой части в байтах и длину закодированной части номера телефона. Изврат полнейший

т.е. сохранять скетч в однобайтной кодировке ты принципиально не будешь?

MaksVV
Offline
Зарегистрирован: 06.08.2015

Клапауций 112 пишет:

MaksVV пишет:
Поиск результатов не дал. До конца вроде как никто не довел этцу тему, по крайней мере я не нашел рабочий скетч.

шо?! опять не дают упыри рабочий скетч? #155 О_О


Вас не поймёшь. Начнешь какую нить тему, тебе тут тычут нах велосипед изобретаешь, а говоришь не нашёл готового решения сразу - упыри скетч не дали.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DetSimen пишет:

а типа wchar_t в AVR нетю?

Почему "нетю"? Этого добра навалом.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Клапауций 112 пишет:

т.е. сохранять скетч в однобайтной кодировке ты принципиально не будешь?


Просто пока не сталкивался с этим, разберусь , попробую. За совет спасиб.

MaksVV
Offline
Зарегистрирован: 06.08.2015

andriano пишет:

MaksVV пишет:
Цель скетча отправка смс на русском языке. В формате PDU. Поиск результатов не дал. До конца вроде как никто не довел этцу тему, по крайней мере я не нашел рабочий скетч.

Я думаю, Ваш скетч - не писатель, из головы сочинять не будет. А будет несколько заранее заготовленных фраз. Вот длины этих фраз посчитать где-то вне Ардуино и внести нужные цифры в Ваш скетч. Вероятнее всего, длины нужно считать в формате PDU. Это наиболее прямой и подходящий для микроконтроллера способ.

В принципе, считать совсем необязательно глазками/ручками, можно написать для этого специальную программу на ПК. 


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

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

MaksVV пишет:
а говоришь не нашёл готового решения сразу - упыри скетч не дали.

какого "готового", если ты дуб-дерево... нет, что бы признаться, что опять жёстко ступил, запутавшись кодировках.

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

MaksVV пишет:
Просто пока не сталкивался с этим, разберусь , попробую. За совет спасиб.

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

MaksVV
Offline
Зарегистрирован: 06.08.2015

дак искал до того как запутался в кодировках. Кому бы помогли эти мои признания

MaksVV
Offline
Зарегистрирован: 06.08.2015

короче ты не реально крут, это факт. Все это уже давно знают

andriano
andriano аватар
Онлайн
Зарегистрирован: 20.06.2015

DetSimen пишет:

а типа wchar_t в AVR нетю?

wchar_t - это для UTF-16. И подозреваю, двухбайтную кодировку не пропустит компилятор.

А для UTF-8 в С/С++ нету подходящего типа данных. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

andriano пишет:

DetSimen пишет:

а типа wchar_t в AVR нетю?

wchar_t - это для UTF-16. И подозреваю, двухбайтную кодировку не пропустит компилятор.

А для UTF-8 в С/С++ нету подходящего типа данных. 

нада изобрести. 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

MaksVV пишет:
Цель скетча отправка смс на русском языке. В формате PDU. Поиск результатов не дал. До конца вроде как никто не довел этцу тему, по крайней мере я не нашел рабочий скетч.

Ну почему - я давно уже решил: https://github.com/Porokhnya/GreenHouseProject Вполне себе принимаются/отправляются SMS на русском, только не стал париться со сборными сообщениями.

MaksVV
Offline
Зарегистрирован: 06.08.2015

DIYMan пишет:
Ну почему - я давно уже решил: https://github.com/Porokhnya/GreenHouseProject Вполне себе принимаются/отправляются SMS на русском, только не стал париться со сборными сообщениями.

Это не мой уровень. вообще ничего не понятно. 

andriano
andriano аватар
Онлайн
Зарегистрирован: 20.06.2015

DetSimen пишет:

andriano пишет:

А для UTF-8 в С/С++ нету подходящего типа данных. 

нада изобрести. 

Дороговато для контроллера.

MaksVV
Offline
Зарегистрирован: 06.08.2015

короче искал ,искал конвертер в UCS2  - такие функции попадаются, мне не разобраться. Вот как я сделал, чтобы мне понятно было и новичкам . Но в итоге скетч работает только с загрузки с нового окна (когда скетч не сохранен на компе), пока не нашел решения. 

String message = "Здорово!!!\r как жизнь?";

void setup (){
Serial.begin (9600);
//конвертация строки в UCS2, где каждый символ по два байта
byte textbyte[120] = {0};
int k = 0; int n=0;
while ( k<(message.length()*2)) {
byte b0 = byte (message[k]);
if (b0<128) {textbyte[k+n] = 0;  //если символ  - латиница/цифры/знаки
textbyte[k+n+1] = message[k]; 
}

else {                          // иначе, если кириллица
  int val = b0+0x350;           // прибавляем 350h
  byte b1 = ( byte )( val >> 8 ); 
  textbyte[k+n] = b1;  
  byte b2 = ( byte )val;
  textbyte[k+n+1] = b2; 
  }
  k++; n++;}

  for (int i=0; i < (message.length()*2); i++){  // распечатаем итоговый массив, 
    if (textbyte[i]<16) Serial.print (0);        // в котором лежит конвертированная строка в байтах
    Serial.print (textbyte[i], HEX);
    Serial.print (" ");
  }
}
void loop() {}

  

 

b707
Онлайн
Зарегистрирован: 26.05.2017

MaksVV пишет:

короче искал ,искал конвертер в UCS2  - такие функции попадаются, мне не разобраться. Вот как я сделал, чтобы мне понятно было и новичкам . Но в итоге скетч работает только с загрузки с нового окна (когда скетч не сохранен на компе), пока не нашел решения.

решение вам озвучивали раньше - не храните в скетче переменную message в кириллице, преобразуйте ее заранее в UCS2

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Как-то давно давно, надо было посчитать количество символов при смешенном алфавите, написал такой вот костыль, который уже много лет работает без нареканий.

Строка конечно используется "классическая" (массив char) а не String arduino'вский.

Думаю если посидеть вечерок можно и перекодировку придумать.

byte rusStrlen(const char * str)
{
  byte i, len = 0;
  while(str[i++] != '\0')
  {
    len++;
    if(str[i]<0)
      i++;
  }
  return len;
}
Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

MaksVV пишет:

пока не нашел решения. 

т.е. принципиально не будем учиться создавать файлы в нужной тебе однобайтной кодировке?

ок. скачай свой же скетч и проверь, что проблемы не существует в принципе - размер строки String message = "Привет!!!" 9 байт.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Это силами IDE сделано? Если нет, то это ещё более неудобно. Стоит что-нибудь поправить в скетче , кодировка сбрасывается и постоянно нужно перекодировать. А так я хоть вижу на русском строки String. Всё таки проще перед заливкой в ардуино в новое окно вставить. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Penni пишет:

Как-то давно давно, надо было посчитать количество символов при смешенном алфавите, написал такой вот костыль, который уже много лет работает без нареканий.

Строка конечно используется "классическая" (массив char) а не String arduino'вский.

Думаю если посидеть вечерок можно и перекодировку придумать.

byte rusStrlen(const char * str)
{
  byte i, len = 0;
  while(str[i++] != '\0')
  {
    len++;
    if(str[i]<0)
      i++;
  }
  return len;
}

а не подскажите мне , дубу-дереву, как этим пользоваться по аналогии со скетчем в первом сообщении топика.

b707
Онлайн
Зарегистрирован: 26.05.2017

byte Length_of_string =  rusStrlen(message.cstr());

учи синтаксис языка... а то так деревом и помрешь :)

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015
char myStr[] = "ПриветHello";
Serial.println(rusStrlen(myStr), DEC);

Выведет в сериал 11 а не 17

 

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

MaksVV пишет:

Это силами IDE сделано? Если нет, то это ещё более неудобно. Стоит что-нибудь поправить в скетче , кодировка сбрасывается и постоянно нужно перекодировать. А так я хоть вижу на русском строки String. Всё таки проще перед заливкой в ардуино в новое окно вставить. 

нет! - это сцуко сделано силой виндового блокнота(сохратинть файл в кодировке ANSI), если у тебя другого текстового редактора.

правь скетч любым текстовым редактором - в настройках ИДЕ укажи соответвующую настройку.

повылазило и не видишь па-русски - пункт в меню "исправить кодировку".

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Penni пишет:

char myStr[] = "ПриветHello";
Serial.println(rusStrlen(myStr), DEC);

Выведет в сериал 11 а не 17

 

дак я так и сделал, до того как спросить. Опять где то накосячил чтоли?) В монитор 0 выводит


char message[] = "Привет!!!";
void setup() {
Serial.begin (9600);
Serial.println (rusStrlen(message), DEC);

}

void loop() {}

byte rusStrlen(const char * str)
{
  byte i, len = 0;
  while(str[i++] != '\0')
  {
    len++;
    if(str[i]<0)
      i++;
  }
  return len;
}

 

b707
Онлайн
Зарегистрирован: 26.05.2017

В 16 строке

if(str[i]>0)
MaksVV
Offline
Зарегистрирован: 06.08.2015

эмм, все равно 0

b707
Онлайн
Зарегистрирован: 26.05.2017

MaksVV пишет:

эмм, все равно 0

А если строчку на латинице - например "Hello" ?

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015
char myStr[] = "Привет!!!";

byte rusStrlen(const char * str)
{
  byte i, len = 0;
  while(str[i++] != '\0')
  {
    len++;
    if(str[i]<0)
      i++;
  }
  return len;
}

void setup()
{
  Serial.begin(9600);
  Serial.println(rusStrlen(myStr));
}

void loop()
{
}

Вот это точно работает, только что залил и проверил

b707
Онлайн
Зарегистрирован: 26.05.2017

Penni пишет:


Вот это точно работает, только что залил и проверил

обьясните смысл строки 9 - как может численное значение символа в строке быть меньше нуля?

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Ну получается двухбайтовые символы, если их читать побайтово то они будут отрицательные, а если целиком считать то положительные. Вот и получается читаем побайтово и если отрицательный байт то это русский символ и двигаемся не на один а на два шага вперед, если английский символ или знаки то двигаемся на один. Я сильно не вникал тогда, а сейчас надо вспоминать, я тогда вывел байты в сериал в DEC и посмотрел что либо -48 либо -49 первый байт, вот это и использовал для подсчета. Для моих целей было преемлемо.

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

b707 пишет:

обьясните смысл строки 9 - как может численное значение символа в строке быть меньше нуля?

ну, как то может... массив строки у нас тип char, с сериала приходит тип char(может принимать значения от -128 до 127) - а, на печать уже выдаётся unsigned char. О_О

*не вникал с магию кода, но подозреваю, что будет работать для однобайтной кодировки:

Впоследствии оказалось удобнее использовать 8-битовые кодировки (кодовые страницы), в которых нижнюю половину кодовой таблицы (0—127) занимают символы US-ASCII, а верхнюю (128—255) — дополнительные символы, включая набор национальных символов.

0—127 - латиница

всё, что больше 127 или меньше 0(в зависимости от типа чар) - национальная кодировка