помогите разобраться с /char/ и /String/
- Войдите на сайт для отправки комментариев
Всем доброго времени суток, занимаюсь подключением GSM модуля к ардуинке, но новичок в деле программирования. Вопрос по коду: мне необходимо по наступлению события отправлять смс на указанный номер, или на несколько номеров, зависит от того, какое событие произошло, так вот, чтобы не перебивать во всех местах номер телефона в случае его изменения, хочу сделать некую постоянную, присвоив ей значение необходимого номера, и в дальнейшем по тексту кода оперировать именем этой переменной.
для отправки смс сделал (выдернуто из кода):
void sms(String text, String phone) // отправка СМС
{
//Serial.println("Start SMS send");
Serial.println("AT+CMGS=\"" + phone + "\"");
delay(500);
Serial.print(text);
delay(500);
Serial.print((char)26);
delay(500);
//Serial.println("SMS send OK");
delay(2000);
}
void loop() {
if ( LEVEL_TS2 == LOW )
{
if ( send_TS2 == 0 ) //проверяем что на это событие еще не отправлена смс
{
sms(String("TS2 alarm"), String("+79090232082"));
send_TS2 = 1; // флаг, что по данному событию сообщение отправлялось
delay(3000);
}}}
всё хорошо работает, но таких событий в коде будет множество, плюс при наступлении некоторых из них смс будет отправляться на несколько номеров, поэтому каждый раз при смене номера перелопачивать код мне не улыбается.
пробовал сделать так:
// добавил такую строчку:
char phone1[]={"+79090232082"}
// далее все осталось прежним, только в цикле loop номер заменил на phone1 соответственно
void sms(String text, String phone) // отправка СМС
{
//Serial.println("Start SMS send");
Serial.println("AT+CMGS=\"" + phone + "\"");
delay(500);
Serial.print(text);
delay(500);
Serial.print((char)26);
delay(2000);
}
void setup() {
}
void loop() {
if ( LEVEL_TS2 == LOW )
{
if ( send_TS2 == 0 ) //проверяем что на это событие еще не отправлена смс
{
sms(String("TS2 alarm"), String(phone1));
send_TS2 = 1; // флаг, что по данному событию сообщение отправлялось
delay(3000);
}}}
и нифига не сработало. предполагаю что дефайном тоже это делать неправильно. Подскажите пожалуйста бедноумному чайнику как это правильно сделать и почему не сработал мой вариант?
Строковые константы, записанные в "двойных кавычках" интерпретируются компилятором как массив символов, а не объект класса String
правильно -
String phone1 = "
+79090232082";Спасибо, загрузил, все работает! Да, это я читал , только из примеров синтаксиса так и не разобрался как правильно написать в коде. Запутался в том, начав читать про String перешел на string массив, а оттуда из приведенных примеров написания перешел на char. получилось, что string это массив char-ов в двойных кавычках. Как задать в коде String примера нет, а сейчас получается что и объект класса String проставлен в двойные кавычки... или дело только в заглавной букве... Буду разбираться. И как тогда правильно написать двумерный массив?
(Из примера на char:
char* myStrings[]={"This is string 1", "This is string 2", "This is string 3", "This is string 4", "This is string 5","This is string 6"}; void setup(){ Serial.begin(9600); } void loop(){ for (int i = 0; i < 6; i++){ Serial.println(myStrings[i]); delay(500); } }Я в объектном программировани ни в зуб ногой, но String работает объектами, значит объекты и надо прописывать, то-есть
String telefon1 = "ХХХХХХХХХХХ"
String telefon2 = "ХХХХХХХХХХХ"
и так далее, объекты жрут память, но фунция sms у вас оперирует объектами, не меняя её - никак (я так думаю, реально знающие могут меня поправить)
Хотя...
void loop(){ for (int i = 0; i < 6; i++){ String myString = myStrings[i]; Serial.println(myString); delay(500); } }String это не ООП. Это есть в обычном Си. В обычном Си есть поинтеры(русск.название указатели). Так вот в них народ не разбирается. А раз не разбирается, то это сложно. А сложно это OOП.
char* myStrings[]Это массив указателей на начало "This is string 1","This is string 2" ну и так далее. И радуйтесь что вам не втюхивают шаблоны.Ему бы код поправить, чтоб заработало ))) а как - дело десятое, точнее - пример привидите как через указатель присвоить значение переменной, в IDE и чтобы скетч заработал
чтобы скетч заработал
Я что против . Пусть читает #14 и пробует. Там только "обработка программы напильником". Мы можем только морально поддержать ТС.
Спасибо друзья за ваши ответы, скетчик доработал, всё работает. С новыми вопросами пока пытаюсь разобраться сам, но если что, думаю опять к вам на поклон пойду, уж не гоните сразу )
чтобы скетч заработал
Я что против . Пусть читает #14 и пробует. Там только "обработка программы напильником". Мы можем только морально поддержать ТС.
А почему буфер используют в 10 байт? Стандартный буфер для COM порта 64 байта или не?
String это не ООП.
А что это?
Это есть в обычном Си.
Классы? А ... простите, какой именно С Вы называете обычным?
А что это?
Вы что думаете, что у меня университетское образование по программированию. Или я каждый день встречаюсь с Си. Ошибся. Перепутал srting и String.
Здравствуйте.
Я опять с char...
Имею строку формата
Мне нужно получить число между + и #
char *uk1, *uk2; uk1 = strchr(buffers, '+'); uk2 = strchr(buffers, '#'); uint8_t num = uk2 - uk1; char pp[10] = ""; strncpy(pp, strstr(buffers, "ON+") + 3, num - 1);Как сделать проще?
Мне нужно получить
числомежду + и #Именно число? Или строковое представление? Сейчас Вы строковое представление получаете. Если число, то после того, как нашли адрес +, просто берите atoi от него + 1 и больше ничего не нужно.
http://arduino.ru/Reference/StringSubstring
Ну и какие-нибудь indexof(«#»), для получения параметров. Чисто предположение, проверить сейчас нет возможности.
Именно число? Или строковое представление? Сейчас Вы строковое представление получаете. Если число, то после того, как нашли адрес +, просто берите atoi от него + 1 и больше ничего не нужно.
Да, число, я его после преобразовывала в число.
atoi отбросит лишние символы?
А если в строке будет несколько параметров, к примеру:
Как проще разбить эту строку по разделителю?
http://arduino.ru/Reference/StringSubstring
Ну и какие-нибудь indexof(«#»), для получения параметров. Чисто предположение, проверить сейчас нет возможности.
char а не string )))
Имею строку формата
Мне нужно получить число между + и #
Может не проще, но альтернативнее.
void setup() { Serial.begin(9600); char stroka[15] = "123456ON+10#", c; uint32_t result = 0; uint8_t len = sizeof(stroka) / sizeof(*stroka); for (int8_t i = 0; i < len ; i++) { if (stroka[i] == '+') { for (int8_t j = i + 1; j < len; j++) { c = stroka[j]; if (c == '#') break; if (c >= '0' && c <= '9') result = result * 10 + (stroka[j] - 48); } break; } } Serial.println(result); } void loop() {}Плюс замените на \0, найдите позицию # и указатель, начиная с неё+1, передайте в atoi.
А если в строке будет несколько параметров, к примеру:
тут куча дополнительных вопросов. Первый и главный, откуда берётся строка? Если её готовит человек ручками, то надо обрабатывать ошибки формата. А если машина готовит, то не надо. Это две большие разницы.
Машина готовит
Т.е. считаем, что ошибок в подготовке данных нет.
Ну, тогда: самый просто способ, кончено strtok
void setup(void){ Serial.begin(115200); char *sInput = (char *) "123456ON+10|32|45|123|#"; for (char *p = strtok(strchr(sInput, '+'), "+|"); p; p = strtok(NULL, "#|")) { const int f = atoi(p); Serial.println(f); } } void loop(void){}но, можно и как у Вас было.
void setup(void){ Serial.begin(115200); char *sInput = (char *) "123456ON+10|32|45|123#"; for (char * p = strchr(sInput, '+'); p && *(p+1); p = strchr(p, '|')) { const int f = atoi(p+++1); Serial.println(f); } } void loop(void){}Но с strtock будет раза в три быстрее.
Большое спасибо.
for (char *p = strtok(strchr(sInput, '+'), "+|"); p; p = strtok(NULL, "#|")) {Почему здесь NULL? strtok(NULL, "#|")
и ещё вопрос:
uint32_t vals[2]; char stroka[50] = "12345676AN401"; for (char*p = strtok(stroka, "AN"); p; p = strtok(NULL, "AN")) { static uint8_t i; Serial.print("i = "); Serial.print(i); Serial.println(""); vals[i++] = atol(p); } Serial.print("vals0 = "); Serial.print(vals[0]); Serial.println(""); Serial.print("vals1 = "); Serial.print(vals[1]); Serial.println(""); for (char*p = strtok(stroka, "AN"); p; p = strtok(NULL, "AN")) { static uint8_t i; Serial.print("i = "); Serial.print(i); Serial.println(""); vals[i++] = atol(p); } Serial.print("vals0 = "); Serial.print(vals[0]); Serial.println(""); Serial.print("vals1 = "); Serial.print(vals[1]); Serial.println("");Почему при выполнении второго цикла i=0 и всё, нет i=1
Почему при выполнении второго цикла i=0 и всё, нет i=1
так суббота жеж )))
PS "чти день субботний"
for (char *p = strtok(strchr(sInput, '+'), "+|"); p; p = strtok(NULL, "#|")) {Почему здесь NULL? strtok(NULL, "#|")
NULL означает, что надо не начинать новый поиск, а продолжить текущий. Это написано в описании функции strtok, ссылку на которое я давал в посте #20.
Почему при выполнении второго цикла i=0 и всё, нет i=1
Потому, что во втором цикле она не нашла 401, а нашла только 12345676. То, что 401 печатается - не должно вводить Вас в заблуждение. Это оно от первого цикла там осталось.
А не нашла она потому, что strtok вставляет в строку концевые нули после лексем. Так что после первого цикла Ваша строка уже поменялась. Вставьте
Serial.print("stroka = "); Serial.print(stroka); Serial.println();перед обоими for и увидите, что строка уже не та.
Это (то, что strtok гадит в строку) тоже, кстати, написано в п-описании. Вы его не читали?
А не нашла она потому, что strtok вставляет в строку концевые нули после лексем.
Это (то, что strtok гадит в строку) тоже, кстати, написано в п-описании.
"...вот она какая тётя Хая..." PS и как это можно всё запомнить )))
Это (то, что strtok гадит в строку) тоже, кстати, написано в п-описании. Вы его не читали?
Теперь всё поняла. Ещё раз спасибо.
Ещё ещё вопрос.
static uint32_t qaz =123456;; char stroka[15]; ultoa(qaz , stroka, DEC); if (strstr (buffers, stroka) != NULL) {....}Чтобы произвести поиск числа типа uint_32t в строке обязательно число переводить в char создавая ещё одну переменную...?
Охохо... А вы представляете, чем строка от числа отличается и как поиск происходит?
Думаю, что происходит посимвольное сравнение, если первый символ 1 строки равен первому символу 2 строки то если 2 символ 1 строки ....
Похоже, что не все так плохо, как могло казаться.
Что, если я Вам приведу пример:
- Число 123 в uint32 хранится в памяти МК как: 0000 0000 0111 1011
- Строка 123 хранится в памяти МК как: 0011 0001 | 0011 0010 | 0011 0011
ASCII 49 | ASCII 50 | ASCII 51
Будет ли в этом случае побайтовое сравнение корректным?
Не будет.
Вот вам и ответ: хотите сравнить строки - сравнивайте строки. Сравнение числа и строки - бессмысленно и безрезультатно.
На всякий случай сообщаю вам, что char[] и char* - в СИ это, по большому счету, одна сущность - ASCIIZ-строка, он же массив ASCII-кодов, заканчивающийся терминатором '\0' (байтом 0x00, Zero-кодом).