Как правильно соединить char + char? или string + char?
- Войдите на сайт для отправки комментариев
Сб, 05/08/2017 - 12:10
Добрый день! Понимаю что вопрос избитый, но прокопал инет и форумы, так и не прийдя к общему знаменателю... Вообщем работаю с модулем Sim900. Приведу небольшой кусок кода для разбора полета:
const char* Tel[] = {"891257*****", "891297*****", "891958*****" }; char Tel1[13] = "+791257*****"; char Tel2[13] = "+791297*****"; char Tel3[13] = "+791958*****"; byte CheckSignal() { byte result = 99; char gprsBuffer[21]; sim900_clean_buffer(gprsBuffer, 21); char *s; sim900_send_cmd("AT+CSQ\r\n"); sim900_read_buffer(gprsBuffer, 21, 5); if (NULL != ( s = strstr(gprsBuffer, "+CSQ: "))) { result = atoi(s + 6); sim900_wait_for_resp("OK\r\n", CMD); } return result; } bool sms_text(String txt) { // А если не String а Char? то дальше как с этим работать? Serial.println("AT+CMGS=\"" + String(Tel1) + "\""); // Можно ли оптимизировать не используя String? delay(1000); Serial.println(txt); delay(200); Serial.println((char)26); delay(200); delay(10000); Serial.println("AT+CMGS=\"" + String(Tel2) + "\""); delay(200); Serial.println(txt); delay(200); Serial.println((char)26); } if (NULL != (strstr(inputString, "+CLIP:"))) { numtel = 0; if (NULL != (strstr(inputString, Tel1))) { numtel = 1; } if (NULL != (strstr(inputString, Tel2))) { numtel = 2; } if (NULL != (strstr(inputString, Tel3))) { numtel = 3; } if (numtel > 0) { sim900_check_with_cmd("ATA\r\n", "OK\r\n", CMD); } } if (digitalRead(pwr_st) == HIGH) { sms_text("Last telephone: " + String(Tel[lastcomm]) + "; 220B OK; SigGSM=" + String(Signal)); // вот тут и возникает проблема, то полностью строка отправляется, то начиная с "; 220B OK; SigGSM=" а первая часть куда-то теряется }
Может для такой задачи есть вариант уйти от String? Микроконтроллер Ardu Mini и думаю что не хватает ему ОЗУ для работы со строками...
Ну, во-первых, никогда не передавайте объекты String по значению, за исключением тех случаев, когда Вы точно знаете что делаете и зачем Вам это нужно (подробности в раделе "1. Неоправданная передача параметра функции по значению")! Вам достаточно в строке 20 добавить один символ "&" после слова String, как Вашей памяти сразу и намного полегчает!
А в остальном, я не понял вопроса. Вы спрашиваете можно лиз вообще избавиться от String? ну, конечно, можно. Как-то же люди писали программы до появления этого класса.
Хорошая статья, почитаю завтра)) А символ & после String что означает? И если работать только с char, то сильно усложнит код написания?
Хорошая статья, почитаю завтра)) А символ & после String что означает?
Вот завтра и узнаете.
И если работать только с char, то сильно усложнит код написания?
"усложнит" - оценочное понятие - кому как. По мне, так существенно упростит, потому что всё в своих руках и не надо постоянно думать, что там понаписали авторы класса String.
вот меня, как юного ардуинщика, тоже интересует вопрос в из заголовка топика про char+char
у мну есть функция
мне надо ее вызвать чемто типа
где
PS тяжело переходить с BASCOMAVR на С
Ну, разумеется никаких плюсов. Погуглите strcat и strcpy
ура! спасибо великому гуглу! танцам с бубном и паре выкуренных сигарет из мануалов
работает))
ура! спасибо великому гуглу! танцам с бубном и паре выкуренных сигарет из мануалов
работает))
А теперь почитайте что нить про p_strcpy.
А теперь почитайте что нить про p_strcpy.
а чем strcpy плоха
ура! спасибо великому гуглу! танцам с бубном и паре выкуренных сигарет из мануалов
работает))
Учитывая, что и strcpy, и strcat вовращаю адрес получившейся строки, можно написать тоже самое и так (не уверен. что это лучше, но просто, чтобы Вы знали):
ура! спасибо великому гуглу! танцам с бубном и паре выкуренных сигарет из мануалов
работает))
Учитывая, что и strcpy, и strcat вовращаю адрес получившейся строки, можно написать тоже самое и так (не уверен. что это лучше, но просто, чтобы Вы знали):
а вот про p_strcpy я нефига не нашел...
а вот про p_strcpy я нефига не нашел...
Это у коллеги опечатка. Правильно strcpy_P (правда, сейчас Atmel рекоммендует использовать strcpy_PF).
Это функции для копирования строк из PROGMEM.
Вообще, сделайте закладку на атмеловскую документацию - не раз поможет. В первый раз прочитайте более или менее всё, чтобы знать что там есть, а потом используйте как справочник.
Это у коллеги опечатка. Правильно strcpy_P
ну вот, а я тоже полГугля перерыл. Кстати, есть такая p_strcpy или pstrcpy в некоторых версиях Си - та же самая strcpy, только "безопасная" - проверяет результат на переполнение, вроде
только "безопасная" - проверяет результат на переполнение, вроде
стандартная безопасная функция здесь strcpy_s
Если я правильно понял, то у меня получилось такая фукнция:
bool sms_text(String& txt) {
}
Передаю в нее строковое значение
sms_text("Power 220B OK!");
на что получаю сообщение компилятора:
invalid initialization of non-const reference of type 'String&' from an rvalue of type 'const char*'
1) В чем разница между String& и String* ?
2) Как лучше обойти ошибку компилятора? привести к char или оставить строку?
1) В чем разница между String& и String* ?
Первое ссылка, а второе указатель. Только легче не стало, правда? Развёрнутый ответ тянет на семестровый курс. Читайте Страуструпа. Только не ищите там сразу ответ на этот вопрос - даже если найдёте, понятнее не станет, а читайте от корки до корки. Через полгода - год у Вас не будет этих (и многих других) вопросв.
2) Как лучше обойти ошибку компилятора? привести к char или оставить строку?
Непонятно что Вам надо. Передать ссылку, ну так создайте объект и передавайте.
String kaka = "Power 220B OK!";
sms_text(kaka);
На столько озадачен экономией ОЗУ у Мини, что хочется выбрать код,чтобы сэкономить эту память. Вот это мне надо )) т.к я уже столкнулся с тем, что сказано в Вашей статье, когда не хватает памяти и контроллер вытворяет непредсказуемые вещи.
Сейчас переписал функции таким образом:
Вот таким образом следуя инструкциям, вроде все объявления переменных заключены в скобках {}, если я правильно все понял, то после закрытия скобок память будет освобождаться. Вот только еще момент - объявил переменную
char
flsend[60];
указав размер 60, чуть больше чем требуется, + 5-7 байт. Этот хвост не помешает правильному выполнению? Мусора там не будет? И хочется еще раз Ваше заключение )P.S. нашел книгу Страуструпа "Программирование. Принципы и практика с использованием C++" это про нее Вы говорите?
На столько озадачен экономией ОЗУ у Мини, что хочется выбрать код,чтобы сэкономить эту память.
В таком случае от String избавляйтесь целиком и полностью. Если не поможет, можно символьные константы перенести в память программы (если её хватает).
Ваш код не полный и я, например, не вижу как описана переменная Signal, которая используется в 54 строке.
чуть больше чем требуется, + 5-7 байт. Этот хвост не помешает правильному выполнению?
Не помешает.
Мусора там не будет?
Будет, но не помешает.
P.S. нашел книгу Страуструпа "Программирование. Принципы и практика с использованием C++" это про нее Вы говорите?
Я имел в виду вот эту.
Не понял строк 46-48 и 50б 52 и 54.
Во них всех Вы копируете в начало массива flsend, т.е. в строке 47 Вы затираете то, что записали в строке 46, в строке 48 затираете то, что записали в строке 47 и т.п.
Как говорится научи д***а молится , так он и голову разобъет. http://cppstudio.com/post/695/
Особенно внимательно изучите там текст программы. Особенно то что выделено малиновым.
ПС: Извините что влез в ваш обучающий процесс.
объявил переменную
char
flsend[60];
указав размер 60, чуть больше чем требуется, + 5-7 байт.зачем?
Во них всех Вы копируете в начало массива flsend, т.е. в строке 47 Вы затираете то, что записали в строке 46, в строке 48 затираете то, что записали в строке 47 и т.п.
Как я понял из примера выше strcat соединяет char строки в один массив... разве не? )) (тогда пример был не верен??)Я попытался у себя реализовать это же. Объявить массив, собрать в него данные в зависимости от текущих состояний портов, и послать их в виде смс.
Т.е в массиве flsend я жду строку "Last telephone: +79128111111; 220B OK; SigGSM=15,6"
Пока писал увидел косяк )) 48 строка лишняя )))))
объявил переменную
char
flsend[60];
указав размер 60, чуть больше чем требуется, + 5-7 байт.зачем?
На всякий пожарный )) мало ли что там Sim вернет ))
Во них всех Вы копируете в начало массива flsend, т.е. в строке 47 Вы затираете то, что записали в строке 46, в строке 48 затираете то, что записали в строке 47 и т.п.
Почему я затираю массив?
Почему я затираю массив?
подсказка: на всякий случай(с) :D
Получается "смотрю в книгу - вижу фигу"? )) В описании фукнции strcat скачано что она призвана объединять строки. Пример приведет в таком же виде, что у меня. Где собака зарыта тогда? )))
Почему я затираю массив?
Ну, откуда мне знать почему? Возможно перепутали strcat и strcpy, а может так и хотели. В общем, не знаю я почему, но затираете - факт.
Ёшкин кот!!!! Вот это бревно у меня в глазу видать! Спасибо большое!)))
Решил потестить мой скеч MemoryExplorer'ом. Запихнул в каждую функцию, и в таймер в loop вывод информации о состоянии памяти(Тестирую на Mega2560. А прототип собран на Mini). Вот что получил:
Стартанул (в Setup после открытия Serial):
---- Memory report: POINT #0
HEAP:@083E(2110)-@210E(8462);
Unallocated from:@083E(2110);
Stack pointer: @218E(8590)
Free List: EMPTY
В ходе программы получаю такие данные:
вход в процедуру:
---- Memory report: POINT Sim_wait_resp #0
HEAP:@083E(2110)-@20F9(8441);
Unallocated from:@083E(2110);
Stack pointer: @2179(8569)
Free List: EMPTY
-----
После выхода из процедуры:
---- Memory report: POINT Sim_wait_resp #3
HEAP:@083E(2110)-@20F9(8441);
Unallocated from:@083E(2110);
Stack pointer: @2179(8569)
Free List: EMPTY
На таймере в Loop: - каждый раз эти же показания:
---- Memory report: POINT Timer #0
HEAP:@083E(2110)-@210E(8462);
Unallocated from:@083E(2110);
Stack pointer: @218E(8590)
Free List: EMPTY
Самые маленькие значения были
Вход в процедуру:
---- Memory report: POINT Sim_read_buf #0
HEAP:@083E(2110)-@20F6(8438);
Unallocated from:@083E(2110);
Stack pointer: @2176(8566)
Free List: EMPTY
-----
Выход из процедуры:
---- Memory report: POINT Sim_read_buf #1
HEAP:@083E(2110)-@210E(8462);
Unallocated from:@083E(2110);
Stack pointer: @218E(8590)
Free List: EMPTY
-----
Free List: EMPTY - везде, и не меняется.
Unallocated from:@083E(2110); - везде и не меняется.
Можно ли сделать вывод, что у меня нет утечек памяти в скетче?
Ну, судя по всему, да, Вы вообще не пользуеесь кучей, а только стеком
А исходя из этого заключения может быть так, что скетч работает на меге, но начинает глючить на мини? К примеру зависает отправка смс, и она постоянно отправляет их. Или не хочет брать трубку, как-будто не распознает входящий. Хотя в отладке все вижу. Подключил через мегу - на первый порт Мини, на второй Сим, а на нулевом Монитор компа. И вижу все что ходит между ними. Когда идет входящий то это отображается на мониторе, но Мини иногда просто игнорирует. Хотя на Меге такого не происходит... уже всю голову сломал
Может стек переполняется. Можете на мини такую же печать поставить?
Попробовал поднять на Мини софтварный порт и получил:
Скетч использует 10398 байт (36%) памяти устройства. Всего доступно 28672 байт.
Глобальные переменные используют 1603 байт (78%) динамической памяти, оставляя 445 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
а до него - использовал 45% для глобальных переменных... и оставлял 1100байт для локальных
При старте:
---- Memory report: POINT #0
HEAP:@0743(1859)-@0810(2064);
Unallocated from:@0743(1859);
Stack pointer: @0890(2192)
Free List: EMPTY
-----
на таймере:
---- Memory report: POINT Timer #0
HEAP:@0743(1859)-@0810(2064);
Unallocated from:@0743(1859);
Stack pointer: @0890(2192)
Free List: EMPTY
на входе в процедуру
---- Memory report: POINT Sim_read_buf #0
HEAP:@0743(1859)-@07F5(2037);
Unallocated from:@0743(1859);
Stack pointer: @0875(2165)
Free List: EMPTY
-----
на выходе:
---- Memory report: POINT Sim_read_buf #3
HEAP:@0743(1859)-@0810(2064);
Unallocated from:@0743(1859);
Stack pointer: @0890(2192)
Free List: EMPTY
-----
Вот что получаю ))
это самые маленькие значения:
HEAP:@0743(1859)-@07F5(2037);
Unallocated from:@0743(1859);
Stack pointer: @0875(2165)
На что нужно обращать внимание? А точнее что искать при анализе данных?))
без виртуального сериал порта:
Скетч использует 6114 байт (21%) памяти устройства. Всего доступно 28672 байт.
Глобальные переменные используют 928 байт (45%) динамической памяти, оставляя 1120 байт для локальных переменных. Максимум: 2048 байт.
И всё равно не работает?
Как надо - неа )) начинает норм, а потом, то трубку не берет, то сигнала сети нет, то рестартит шилду по алгоритму - отправить AT если нет ответа - рестарт. То берет трубу, но не реагирует на DTMF сигналы. Хаос какой-то непредсказуемый получается... Наверное придется выложить мою схему подключения и весь код программы? Может не там ищу )
Вдруг дело в кондерах, ведь когда тестирую на меге, то на питании у нее нет кондеров(для маленькой аккумуляции энергии, чтобы не вырубалась пока срабатывает реле переключения на резервный источник), а к мини уже все прикручено