Работа со строками

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

Доброе время суток.

Подскажите как представляются строки в памяти? У мен ясложилось такое впечатление, что английские буквы занимают один байт, а русские два байта. Причем это все в одной строке.

Если это так, то как перебрать все символы в цикле for?

Строку объявляю так:

char s[] = {"ABCDАБВГ"};

Как объявить строку с двухбайтными символами?

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

В классической кодовой странице - 256 символов, а с юникодами - все гораздо сложнее. Если хочется "перебрать" для вывода на экран, то там есть разница между lcd.print и lcd.write. В одном из случаев код буквы выводит на экран символ.

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

И все-таки кто мне может объяснить странное поведение программы:

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); 

const char S1[] = {"ABCДE"};  // Все буквы кроме Д латинские

void setup() { 

   lcd.begin(16, 2);  // установить число строк и столбцов 
   lcd.setCursor(0, 0); 

   for (byte i = 0; i < sizeof(S1); i++)    { 
       lcd.setCursor(0, 0); 
       lcd.print("                ");                 
       lcd.setCursor(0, 0); 
       lcd.print(S1[i]); 
       lcd.setCursor(0, 1); 
       lcd.print("                ");                 
       lcd.setCursor(0, 1); 
       lcd.print(word(S1[i])); 
       delay(1000); 
       } 
} 

void loop() {   
   lcd.setCursor(0, 0); 
   lcd.print("                ");                 
   lcd.setCursor(0, 0); 
   lcd.print(sizeof(S1)); 
}  

В две строки выводится символ и его код. Получается вот что:

A - 65

B - 66

C - 67

= - 65488

= - 65428

E - 69

И в конце выводится размер массива длиной 0 (ноль).

Поскольку у знакогенератора нет русских символов, то я привел знак равно. НО, дело не в этом.

Почему в цикле мы проходим дважды букву "Д"? Ведь я объявил массив символов, значит и перебирать я должен в цикле символы, не зависимо сколько под них отведено байт и в какой они кодировке.

И почему у меня размер массива ноль?

 

__Alexander
Offline
Зарегистрирован: 24.10.2012

си под авр не знает что такое массив символов. для него это просто массив байт, слов и т.д....

в данном случае байт. и он один под один символ. отладте и увидите.

длина возвращается правильная, проверяйте.

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

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

Даже если они описаны в одной переменной?

Т.Е. строка "RГY" занимает 5 байт (R и Y по байту, Г - два байта, \0) - так?

olegab
Offline
Зарегистрирован: 09.04.2013

вот как это выглядит в Mega2560:

__Alexander
Offline
Зарегистрирован: 24.10.2012

ну всё правильно.

Snubist
Offline
Зарегистрирован: 18.02.2013

Действительно

вот такой код

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
String Str="А";

void setup() {
  lcd.begin(16, 2);
  lcd.print(Str.length());
}

void loop() {     

}

в случае латинской "A" выдаст 1

а для кирилицы выдаст 2

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

olegab пишет:

вот как это выглядит в Mega2560:

Ну вот видно, что симвод "Д" имеет код C4 (ANSI) и занимает один байт. С другой стороны, если вывести длину этого символа, то окажется, что он занимает два байта.

Так как же работать с такой путаницей?

__Alexander
Offline
Зарегистрирован: 24.10.2012

переходить на нормальный си.

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

__Alexander пишет:

переходить на нормальный си.

Наверное подразумевается, что я в курсе, что это означает.

Я никогда не программировал. А по сему у меня сразу возникает следующая мысль:

взять borland c++ (ну или как он сейчас называется embarcadero), написать на нем что-то, скомпилировать и полученный файл exe закачать в arduino.

Однако что-то мне подсказывает, что ничего работать не будет.

__Alexander
Offline
Зарегистрирован: 24.10.2012

ну как бы да, намекает. ))

ардуиной IDE используеться winavr. вот на нем голом и писать, без применения непонятных функций. или ломать голову и пытаться их понять. есть куча всяких компиляторов.

вот у меня IAR, например. неплохая штучка. )

http://keepfoto.ru/i/jox/Bq3X9

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

пока нашел выход такой:

вместо "ПРИВЕТ"

пишу {'П','Р','И','В','Е','Т'}

тогда все работает и перебор нормально идет

IAR посмотрел (ссылку), действительно неплохо. Надо будет скачать и поковырять. Спасибо.

olegab
Offline
Зарегистрирован: 09.04.2013

 

Oleg_SS пишет:

то симвод "Д" имеет код C4 (ANSI) и занимает один байт. С другой стороны, если вывести длину этого символа, то окажется, что он занимает два байта.

Так как же работать с такой путаницей?

там у вас не длина выводится а результат функции:

unsigned int makeWord(unsigned int w) { return w; }

когда ей скармливают char из ASCII диапазона, она его нормально конвертирует в 2х байтный unsigned int, а когда значение из второй половины - C4h (B1100 0100) - видимо преобразует его во что-то "страшное".

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

__Alexander
Offline
Зарегистрирован: 24.10.2012

olegab пишет:

там у вас не длина выводится а результат функции: unsigned int makeWord(unsigned int w) { return w; }

Можно полную функцию?

olegab пишет:

если не пугает перспектива портировать их "под чистый c"  - удачи

Что то меня наоборот, пугает портирование столетнего языка под пятиминутную систему... тут нечего бояться, ардуино IDE умрет, а стандарт си как жил, так и будет жить.

olegab
Offline
Зарегистрирован: 09.04.2013

__Alexander пишет:

Что то меня наоборот, пугает портирование столетнего языка под пятиминутную систему... тут нечего бояться, ардуино IDE умрет, а стандарт си как жил, так и будет жить.

А чем реализация стандарта c не нравится? на мой взгляд вполне приличный компилятор, хотя конечно  с ардуино знаком не долго. Тем не менее компилятор нравится, хорошо оптимизирует, не задействованный код не включает в сборку, то что можно вычислить на этапе компиляции в сборку вносит в виде вычисленных значений.

про столетний язык и пятиминутную систему не понял.

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

 

olegab пишет:

Можно полную функцию?

собственно весь код был приведен выше, могу повторить: unsigned int makeWord(unsigned int w) { return w; }

преобразовывает компилятор непосредственно перед вызовом,  как я и предполагал для байтов с установленным старшим битом старший байт дополняется до 1