помогите разобраться с /char/ и /String/

plafon
Offline
Зарегистрирован: 06.01.2017

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

для отправки смс сделал (выдернуто из кода):

01void sms(String text, String phone)  // отправка СМС
02{
03  //Serial.println("Start SMS send");
04  Serial.println("AT+CMGS=\"" + phone + "\"");
05  delay(500);
06  Serial.print(text);
07  delay(500);
08  Serial.print((char)26);
09  delay(500);
10  //Serial.println("SMS send OK");
11  delay(2000);
12}
13 
14void loop() {
15 
16if ( LEVEL_TS2 == LOW  )
17  {
18    if ( send_TS2 == 0  ) //проверяем что на это событие еще не отправлена смс
19    {
20    sms(String("TS2 alarm"), String("+79090232082"));
21    send_TS2 = 1; // флаг, что по данному событию сообщение отправлялось
22    delay(3000);
23 
24}}}

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

пробовал сделать так:

01// добавил такую строчку:
02char phone1[]={"+79090232082"}
03 
04// далее все осталось прежним, только в цикле loop номер заменил на phone1 соответственно
05void sms(String text, String phone)  // отправка СМС
06{
07  //Serial.println("Start SMS send");
08  Serial.println("AT+CMGS=\"" + phone + "\"");
09  delay(500);
10  Serial.print(text);
11  delay(500);
12  Serial.print((char)26);
13  delay(2000);
14}
15 
16void setup() {
17}
18 
19void loop() {
20if ( LEVEL_TS2 == LOW  )
21  {
22    if ( send_TS2 == 0  ) //проверяем что на это событие еще не отправлена смс
23    {
24    sms(String("TS2 alarm"), String(phone1));
25    send_TS2 = 1; // флаг, что по данному событию сообщение отправлялось
26    delay(3000);
27}}}

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Строковые константы, записанные в "двойных кавычках" интерпретируются компилятором как массив символов, а не объект класса String

правильно -

String phone1 = "+79090232082";

plafon
Offline
Зарегистрирован: 06.01.2017

Спасибо, загрузил, все работает! Да, это я читал , только из примеров синтаксиса так и не разобрался как правильно написать в коде. Запутался в том, начав читать про String перешел на string массив, а оттуда из приведенных примеров написания перешел на char. получилось, что string это массив char-ов в двойных кавычках. Как задать в коде String примера нет, а сейчас получается что и объект класса String проставлен в двойные кавычки... или дело только в заглавной букве... Буду разбираться. И как тогда правильно написать двумерный массив?

(Из примера на char:

01char* myStrings[]={"This is string 1", "This is string 2", "This is string 3",
02"This is string 4", "This is string 5","This is string 6"};
03  
04void setup(){
05Serial.begin(9600);
06}
07  
08void loop(){
09for (int i = 0; i < 6; i++){
10   Serial.println(myStrings[i]);
11   delay(500);
12   }
13}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Я в объектном программировани ни в зуб ногой, но String работает объектами, значит объекты и надо прописывать, то-есть

String telefon1 = "ХХХХХХХХХХХ"

String telefon2 = "ХХХХХХХХХХХ"

и так далее, объекты жрут память, но фунция sms у вас оперирует объектами, не меняя её - никак (я так думаю, реально знающие могут меня поправить)

Хотя...

1void loop(){
2for (int i = 0; i < 6; i++){
3   String myString = myStrings[i];
4   Serial.println(myString);
5   delay(500);
6   }
7}
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

String это не ООП. Это есть в обычном Си. В обычном Си есть поинтеры(русск.название указатели). Так вот в них народ не разбирается. А раз не разбирается, то это сложно. А сложно это OOП.  char* myStrings[] Это массив указателей на начало "This is string 1","This is string 2" ну и так далее. И радуйтесь что вам не втюхивают шаблоны.

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Ему бы код поправить, чтоб заработало ))) а как - дело десятое, точнее - пример привидите как через указатель присвоить значение переменной, в IDE и чтобы скетч заработал
 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ua6em пишет:

 чтобы скетч заработал

Я что против . Пусть читает #14 и пробует. Там только "обработка программы напильником". Мы можем только морально поддержать ТС.

maxnnovik
Offline
Зарегистрирован: 17.12.2016
Массив одномерных данных
 
byte numbers_array[22] = {
    B00111111, B00000110, B01011011, B01001111, // 0 1 2 3
    B01100110, B01101101, B01111101, B00000111, // 4 5 6 7
    B01111111, B01101111, B01000000, B01100011, // 8 9 - о
    B10111111, B10000110, B11011011, B11001111, // 0 1 2 3
    B11100110, B11101101, B11111101, B10000111, // 4 5 6 7
    B11111111, B11101111 // 8 9
  };
plafon
Offline
Зарегистрирован: 06.01.2017

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

qwone пишет:

ua6em пишет:

 чтобы скетч заработал

Я что против . Пусть читает #14 и пробует. Там только "обработка программы напильником". Мы можем только морально поддержать ТС.

А почему буфер используют в 10 байт? Стандартный буфер для COM порта 64 байта или не?
 

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

qwone пишет:

String это не ООП. 

А что это?

qwone пишет:

Это есть в обычном Си.

Классы? А ... простите, какой именно С Вы называете обычным?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

А что это?

Вы что думаете, что у меня университетское образование по программированию. Или я каждый день встречаюсь с Си. Ошибся. Перепутал srting и String. 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Здравствуйте.

Я опять с char...

Имею строку формата

1char stroka[15] = "123456ON+10#";

Мне нужно получить число между + и #

1char *uk1, *uk2;
2uk1 = strchr(buffers, '+');
3uk2 = strchr(buffers, '#');
4uint8_t num = uk2 - uk1;
5char pp[10] = "";
6strncpy(pp, strstr(buffers, "ON+") + 3, num - 1);

Как сделать проще?

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

Irinka пишет:

Мне нужно получить число между + и #

Именно число? Или строковое представление? Сейчас Вы строковое представление получаете. Если число, то после того, как нашли адрес +, просто берите atoi от него + 1 и больше ничего не нужно.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

http://arduino.ru/Reference/StringSubstring

Ну и какие-нибудь indexof(«#»), для получения параметров. Чисто предположение, проверить сейчас нет возможности. 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

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

Именно число? Или строковое представление? Сейчас Вы строковое представление получаете. Если число, то после того, как нашли адрес +, просто берите atoi от него + 1 и больше ничего не нужно.

Да, число, я его после преобразовывала в число.

atoi отбросит лишние символы?

А если в строке будет несколько параметров, к примеру:

1char stroka[15] = "123456|ON|10|#";

Как проще разбить эту строку по разделителю?

 

BOOM пишет:

http://arduino.ru/Reference/StringSubstring

Ну и какие-нибудь indexof(«#»), для получения параметров. Чисто предположение, проверить сейчас нет возможности. 

char а не string )))

 

 

AndreyD
AndreyD аватар
Offline
Зарегистрирован: 07.10.2018

Irinka пишет:

Имею строку формата

1char stroka[15] = "123456ON+10#";

Мне нужно получить число между + и #

Может не проще, но альтернативнее.

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Плюс замените на \0, найдите позицию # и указатель, начиная с неё+1, передайте в atoi.

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

Irinka пишет:

А если в строке будет несколько параметров, к примеру:

1char stroka[15] = "123456|ON|10|#";

тут куча дополнительных вопросов. Первый и главный, откуда берётся строка? Если её готовит человек ручками, то надо обрабатывать ошибки формата. А если машина готовит, то не надо. Это две большие разницы.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Машина готовит

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

Т.е. считаем, что ошибок в подготовке данных нет.

Ну, тогда: самый просто способ, кончено strtok

01void setup(void){
02    Serial.begin(115200);
03    char *sInput = (char *) "123456ON+10|32|45|123|#";
04 
05    for (char *p = strtok(strchr(sInput, '+'), "+|"); p; p = strtok(NULL, "#|")) {
06        const int f = atoi(p);
07        Serial.println(f);
08    }
09}
10 
11void loop(void){}

но, можно и как у Вас было.

01void setup(void){
02    Serial.begin(115200);
03    char *sInput = (char *) "123456ON+10|32|45|123#";
04 
05    for (char * p = strchr(sInput, '+'); p && *(p+1); p = strchr(p, '|')) {
06        const int f = atoi(p+++1);
07        Serial.println(f);
08    }
09}
10 
11void loop(void){}

Но с strtock будет раза в три быстрее.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Большое спасибо.

 

1for (char *p = strtok(strchr(sInput, '+'), "+|"); p; p = strtok(NULL, "#|")) {

Почему здесь NULL?  strtok(NULL, "#|")

и ещё вопрос:

01uint32_t vals[2];
02char stroka[50] = "12345676AN401";
03 
04for (char*p  = strtok(stroka, "AN"); p; p = strtok(NULL, "AN")) {
05  static uint8_t i;
06  Serial.print("i = "); Serial.print(i); Serial.println("");
07  vals[i++] = atol(p);
08}
09Serial.print("vals0 = "); Serial.print(vals[0]); Serial.println("");
10Serial.print("vals1 = "); Serial.print(vals[1]); Serial.println("");
11 
12 
13for (char*p  = strtok(stroka, "AN"); p; p = strtok(NULL, "AN")) {
14  static uint8_t i;
15  Serial.print("i = "); Serial.print(i); Serial.println("");
16  vals[i++] = atol(p);
17}
18Serial.print("vals0 = "); Serial.print(vals[0]); Serial.println("");
19Serial.print("vals1 = "); Serial.print(vals[1]); Serial.println("");

Почему при выполнении второго цикла i=0 и всё, нет i=1

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Irinka пишет:

Почему при выполнении второго цикла i=0 и всё, нет i=1

так суббота жеж )))
PS "чти день субботний"

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

Irinka пишет:

1for (char *p = strtok(strchr(sInput, '+'), "+|"); p; p = strtok(NULL, "#|")) {

Почему здесь NULL?  strtok(NULL, "#|")

NULL означает, что надо не начинать новый поиск, а продолжить текущий. Это написано в описании функции strtok, ссылку на которое я давал в посте #20.

Irinka пишет:

Почему при выполнении второго цикла i=0 и всё, нет i=1

Потому, что во втором цикле она не нашла 401, а нашла только 12345676. То, что 401 печатается - не должно вводить Вас в заблуждение. Это оно от первого цикла там осталось.

А не нашла она потому, что strtok вставляет в строку концевые нули после лексем. Так что после первого цикла Ваша строка уже поменялась. Вставьте

1Serial.print("stroka = "); Serial.print(stroka); Serial.println();

перед обоими for и увидите, что строка уже не та.

Это (то, что strtok гадит в строку) тоже, кстати, написано в п-описании. Вы его не читали?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

А не нашла она потому, что strtok вставляет в строку концевые нули после лексем.

Это (то, что strtok гадит в строку) тоже, кстати, написано в п-описании.

"...вот она какая тётя Хая..." PS и как это можно всё запомнить )))

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

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

Это (то, что strtok гадит в строку) тоже, кстати, написано в п-описании. Вы его не читали?

Теперь всё поняла. Ещё раз спасибо.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Ещё ещё вопрос.

1static uint32_t qaz =123456;;
2        char stroka[15];
3        ultoa(qaz , stroka, DEC);
4        if (strstr (buffers, stroka) != NULL) {....}

Чтобы произвести поиск числа типа uint_32t в строке обязательно число переводить в char создавая ещё одну переменную...?

sadman41
Offline
Зарегистрирован: 19.10.2016

Охохо... А вы представляете, чем строка от числа отличается и как поиск происходит?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Думаю, что происходит посимвольное сравнение, если первый символ 1 строки  равен первому символу 2 строки то если 2 символ 1 строки ....

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Похоже, что не все так плохо, как могло казаться.

Что, если я Вам приведу пример:

- Число 123 в uint32 хранится в памяти МК как: 0000 0000 0111 1011 

- Строка 123  хранится в памяти МК как: 0011 0001 |  0011 0010 | 0011 0011 

                                                              ASCII 49    |  ASCII 50    | ASCII 51
 

Будет ли в этом случае побайтовое сравнение корректным?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Не будет.

sadman41
Offline
Зарегистрирован: 19.10.2016

Вот вам и ответ: хотите сравнить строки - сравнивайте строки. Сравнение числа и строки - бессмысленно и безрезультатно.

На всякий случай сообщаю вам, что char[] и char* - в СИ это, по большому счету, одна сущность - ASCIIZ-строка, он же массив ASCII-кодов, заканчивающийся терминатором '\0' (байтом 0x00, Zero-кодом).