Возврат из функции строки символов

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Dinosaur пишет:

Я честно пытаюсь, пытаюсь понять умных человеков. Проблема, как Вы верно заметили, в отсутствии у меня базовых знаний. Вы объясняете элементарные, на Ваш взгляд, вещи исходя из своего уровня, а я со своего уровня из воспринимаю их как татарскую грамоту. Я был бы признателен, если бы ткнули меня носом туда, где можно почерпнуть знания, необходимые для понимания написанного Вами в этой ветке. Все что вижу непонятного сразу пытаюсь загуглить как оно работает, но не всегда доходит с первого раза. Да и со второго тоже.

Ваша беда в отсутствии систематизированных знаний. Попытайтесь прочесть от корки до корки https://codernet.ru/books/c_plus/c_rukovodstvo_dlya_nachinayushhix_gerbert_shildt/ хотя бы один раз.

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

andriano пишет:
Ваша беда в отсутствии систематизированных знаний. Попытайтесь прочесть от корки до корки https://codernet.ru/books/c_plus/c_rukovodstvo_dlya_nachinayushhix_gerbert_shildt/ хотя бы один раз.

Спасибо за рекомендацию, прям сейчас и начну - на больничном времени вагон ))) Если еще что то порекомендуете почитать для понимания азов - буду признателен (главное чтобы было написано доступным для непрограммиста языком).

 

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

Dinosaur пишет:
Возможно не все так однозначно: сидел мучал сегодня скетч, обратил внимание что если размер буфера задаю равным количеству символов, но строку 80 скетча (из поста 19) излагаю в следующей редакции:

displayString = ((String)F("Date:") + newTime.date + F(" ") + getMonthShort() + F(" ") + newTime.year + F(" ") + newTime.dow);

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

Отвечу сам себе - чуда не случилось, стало вылетать в другом месте. При размере буфера +1 байт, работает нормально. Запейсал в скрижали.

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

andriano пишет:
Попытайтесь прочесть от корки до корки https://codernet.ru/books/c_plus/c_rukovodstvo_dlya_nachinayushhix_gerbert_shildt/ хотя бы один раз.

Порекомендуйте пожалуйста ide (под пк на windows) в которой можно примеры из книжки проверять - а то мне знакома только Arduino IDE, в книжке на первом же примере споткнулся на #include <iostream>

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

1. Я изменил несколько строк в твоем скетче из 19 и он работает.

собственно функцию getMonthShort() и строчку 80 ;)))))


const char m_s_1[] PROGMEM = "JAN";
const char m_s_2[] PROGMEM = "FEB";
const char m_s_3[] PROGMEM = "MAR";
const char m_s_4[] PROGMEM = "APR";
const char m_s_5[] PROGMEM = "MAY";
const char m_s_6[] PROGMEM = "JUN";
const char m_s_7[] PROGMEM = "JUL";
const char m_s_8[] PROGMEM = "AUG";
const char m_s_9[] PROGMEM = "SEP";
const char m_s_10[] PROGMEM = "OCT";
const char m_s_11[] PROGMEM = "NOV";
const char m_s_12[] PROGMEM = "DEC";
const char* const month_names[] PROGMEM = {m_s_1, m_s_2, m_s_3, m_s_4, m_s_5, m_s_6, m_s_7, m_s_8, m_s_9, m_s_10, m_s_11, m_s_12};

struct time {
  uint8_t seconds: 6;
  uint8_t minutes: 6;
  uint8_t hours: 5;
  uint8_t dow: 3;
  uint8_t date: 5;
  uint8_t month: 4;
  uint16_t year: 12;
};

time newTime;

void setup() {
  newTime.year = 2000;
  Serial.begin(115200);
}

void loop() {
  uint32_t actualTime = millis();
  static uint32_t lastChangeTime;
  if (actualTime - lastChangeTime > 500) {
    static uint32_t num;
    String printstring = (String)num + F(" passed");
    Serial.println(printstring);
    num++;
    lastChangeTime = actualTime;
    changeTime();
    printTime();
  }
}

void changeTime() {
  newTime.seconds++;
  if (newTime.seconds > 59) {
    newTime.seconds = 1;
  }
  newTime.minutes++;
  if (newTime.minutes > 59) {
    newTime.minutes = 1;
  }
  newTime.hours++;
  if (newTime.hours > 23) {
    newTime.hours = 1;
  }
  newTime.dow++;
  if (newTime.dow > 6) {
    newTime.dow = 0;
  }
  newTime.date++;
  if (newTime.date > 31) {
    newTime.date = 1;
  }
  newTime.month++;
  if (newTime.month > 12) {
    newTime.month = 1;
  }
  newTime.year++;
  if (newTime.year > 2100) {
    newTime.year = 2010;
  }
}

void printTime() {
  String displayString = ((String)F("Time:") + (String)newTime.hours + F(":") + (String)newTime.minutes + F(":") + (String)newTime.seconds);
  Serial.println(displayString);
   displayString = ((String)F("Date:") + (String)newTime.date + F(" ") + (String)getMonthShort() + F(" ") + (String)newTime.year + F(" ") + (String)newTime.dow);
  Serial.println(displayString);
  Serial.println("---"); 
}
/*
String getMonthShort() {
  uint8_t idx = (getMonth() - 1);
  char arrayBuf[strlen_P(pgm_read_ptr_near(month_names + idx))]; // длина массива рассчитывается правильно
  strcpy_P(arrayBuf, pgm_read_ptr_near(month_names + idx));
  Serial.print("arrayBuf - ");
  Serial.println(arrayBuf);                                      // и вот тут даже печатается правильно
  //return (String)(idx);                                        // и в таком варианте не виснет и не перезагружается
  return (String)(arrayBuf);                                     // но стоит вернуть arrayBuf, как все виснет/перегружается
}
*/

const __FlashStringHelper * getMonthShort() {
  
  return reinterpret_cast<const __FlashStringHelper *>(pgm_read_ptr_near(month_names + (getMonth() - 1)));
}

uint8_t getMonth() {
  return newTime.month;
}

2. Огромное количество онлайн ИДЕ и для с++ тоже. Набери в Яндексе online IDE. И выбери - какое понравится. Для учебы это проще. Многие позволяют регистрацию и будут помнить твои задачки от раза к разу.

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

wdrakula пишет:
1. Я изменил несколько строк в твоем скетче из 19 и он работает.собственно функцию getMonthShort() и строчку 80 ;)))))

Спасибо за пример, не могли бы вы ткнуть носом где про этот FlashStringHelper почитать можно на простом русском языке, на уровне доступном начинающему (всё что смог нагуглить, объясняет через высокие материи, которые мне пока непонятны)? Или возможно будете любезны, и распишите что происходит в каждом действии переделанной функции (вижу букв кода стало гораздо меньше, чем получилось у меня, но перестало быть понятно)

wdrakula пишет:
2. Огромное количество онлайн ИДЕ и для с++ тоже. Набери в Яндексе online IDE. И выбери - какое понравится. Для учебы это проще. Многие позволяют регистрацию и будут помнить твои задачки от раза к разу.

Ок, спасибо. Отстал я от жизни, привык что все нужно инсталлировать себе на комп )))

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

В данный момент такой вариант работает:

String LCD_RTC_Keypad_MCP23017::convert(uint8_t ptr, int8_t bias) {

static const char ml_1[] PROGMEM = "January";
static const char ml_2[] PROGMEM = "February";
static const char ml_3[] PROGMEM = "March";
static const char ml_4[] PROGMEM = "April";
static const char ml_5[] PROGMEM = "May";
static const char ml_6[] PROGMEM = "June";
static const char ml_7[] PROGMEM = "July";
static const char ml_8[] PROGMEM = "August";
static const char ml_9[] PROGMEM = "September";
static const char ml_10[] PROGMEM = "October";
static const char ml_11[] PROGMEM = "November";
static const char ml_12[] PROGMEM = "December";
static const char ms_1[] PROGMEM = "JAN";
static const char ms_2[] PROGMEM = "FEB";
static const char ms_3[] PROGMEM = "MAR";
static const char ms_4[] PROGMEM = "APR";
static const char ms_5[] PROGMEM = "MAY";
static const char ms_6[] PROGMEM = "JUN";
static const char ms_7[] PROGMEM = "JUL";
static const char ms_8[] PROGMEM = "AUG";
static const char ms_9[] PROGMEM = "SEP";
static const char ms_10[] PROGMEM = "OCT";
static const char ms_11[] PROGMEM = "NOV";
static const char ms_12[] PROGMEM = "DEC";
static const char dl_1[] PROGMEM = "Monday";
static const char dl_2[] PROGMEM = "Tuesday";
static const char dl_3[] PROGMEM = "Wednesday";
static const char dl_4[] PROGMEM = "Thursday";
static const char dl_5[] PROGMEM = "Friday";
static const char dl_6[] PROGMEM = "Saturday";
static const char dl_7[] PROGMEM = "Sunday";
static const char ds_1[] PROGMEM = "MON";
static const char ds_2[] PROGMEM = "TUE";
static const char ds_3[] PROGMEM = "WED";
static const char ds_4[] PROGMEM = "THU";
static const char ds_5[] PROGMEM = "FRI";
static const char ds_6[] PROGMEM = "SAT";
static const char ds_7[] PROGMEM = "SUN";

static const char* const names[] PROGMEM = {
  ml_1, ml_2, ml_3, ml_4, ml_5, ml_6, ml_7, ml_8, ml_9, ml_10, ml_11, ml_12,
  ms_1, ms_2, ms_3, ms_4, ms_5, ms_6, ms_7, ms_8, ms_9, ms_10, ms_11, ms_12,
  dl_1, dl_2, dl_3, dl_4, dl_5, dl_6, dl_7,
  ds_1, ds_2, ds_3, ds_4, ds_5, ds_6, ds_7
};
  
  ptr = ptr + bias;
  char arrayBuf[strlen_P(pgm_read_word(&(names[ptr]))) + 1];
  strcpy_P(arrayBuf, (char*)pgm_read_word(&(names[ptr])));            // работает одинаково
  return (String)(arrayBuf);
}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Dinosaur пишет:

Порекомендуйте пожалуйста ide (под пк на windows) в которой можно примеры из книжки проверять - а то мне знакома только Arduino IDE, в книжке на первом же примере споткнулся на #include <iostream>

Да, собственно, любая. Начиная от классической MS VS, и заканчивая какой-нибудь Atollic TrueSTUDIO, которая позволяет писать код как для ПК, так и для МК.

Dinosaur пишет:

...не могли бы вы ткнуть носом где про этот FlashStringHelper почитать можно

Ищите по ключевому слову PROGMEM

Цитата:

на простом русском языке, на уровне доступном начинающему

Боюсь, Ваши требования чрезмерны.

Ардуино - открытая система, для которой пишут все, кому не лень. Поэтому не всегда можно найти даже информацию на английском, ориентированную исключительно на программистов.

Учитесь пользоваться тем, что есть. (а нередко кроме исходников ничего и нет)

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Dinosaur пишет:

Спасибо за пример, не могли бы вы ткнуть носом где про этот FlashStringHelper почитать можно на простом русском языке, на уровне доступном начинающему (всё что смог нагуглить, объясняет через высокие материи, которые мне пока непонятны)? Или возможно будете любезны, и распишите что происходит в каждом действии переделанной функции (вижу букв кода стало гораздо меньше, чем получилось у меня, но перестало быть понятно)

Прочитать  - думаю - негде. Строк кода стало не просто меньше! ;)) Она стала одна.

return reinterpret_cast<const __FlashStringHelper *>(pgm_read_ptr_near(month_names + (getMonth() - 1)));

Сейчас поясню, что это и для чего.

Авторы реализации Стринг для Ардуино решили, что нужна интеграция с прогмем-строками. Для этого при сосздании операций "+" или преобразования нужно отличать указатель на строку от указателя в прогмем.

Для этого придумано имя класса "__FlashStringHelper". У этого класс нет экземпляров. Это только способ немного обмануть компилятор. Макрос F() переопределяет прогмем-строку в указатель на это вот хитрое имя класса. А для аргументов типа "указатель на этот хелпер" есть перегрузка соответствующих операций.

Так я и использовал уже готовый инструмент из стрингов: у тебя есть прогмем-стринги с именами месяцев, так? Вот и нужно вернуть их просто в виде указателя на хелпер. А с ним уже справится конструктор класса String(). Понятно? Зачем писать новый код для того, что уже написано другими?

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

wdrakula пишет:
Для этого придумано имя класса "__FlashStringHelper". У этого класс нет экземпляров. Это только способ немного обмануть компилятор. Макрос F() переопределяет прогмем-строку в указатель на это вот хитрое имя класса. А для аргументов типа "указатель на этот хелпер" есть перегрузка соответствующих операций.

Так я и использовал уже готовый инструмент из стрингов: у тебя есть прогмем-стринги с именами месяцев, так? Вот и нужно вернуть их просто в виде указателя на хелпер. А с ним уже справится конструктор класса String(). Понятно? Зачем писать новый код для того, что уже написано другими?

Спасибо за объяснили, пока не совсем понял (как правильно заметили ранее, базы нет), поэтому сперва проштудирую учебник (разберусь с классами, указателями) а затем постараюсь осмыслить. Всем признателен!