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

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

Всем доброго времени суток,  занимаюсь подключением 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);
}}}

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

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

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

правильно -

String phone1 = "+79090232082";

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

Спасибо, загрузил, все работает! Да, это я читал , только из примеров синтаксиса так и не разобрался как правильно написать в коде. Запутался в том, начав читать про 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);
   }
}

 

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

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

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

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

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

Хотя...

void loop(){
for (int i = 0; i < 6; i++){
   String myString = myStrings[i];
   Serial.println(myString);
   delay(500);
   }
}
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 это не ООП. 

А что это?

class String ...

qwone пишет:

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

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

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

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

А что это?

class String ...

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

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

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

Я опять с char...

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

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

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

            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);

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

ЕвгенийП
ЕвгенийП аватар
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 отбросит лишние символы?

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

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

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

 

BOOM пишет:

http://arduino.ru/Reference/StringSubstring

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

char а не string )))

 

 

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

Irinka пишет:

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

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

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

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

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() {}

 

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

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

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

Irinka пишет:

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

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

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

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

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

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

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

Ну, тогда: самый просто способ, кончено 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 будет раза в три быстрее.

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

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

 

 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

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

Irinka пишет:

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

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

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

Irinka пишет:

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

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

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

Irinka пишет:

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

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

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

Serial.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

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

  static uint32_t qaz =123456;;
          char stroka[15];
          ultoa(qaz , stroka, DEC);
          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-кодом).