Где-то, я ту туплю, но где???

Тема в разделе "Флудилка", создана пользователем IvanUA, 26 дек 2017.

  1. IvanUA

    IvanUA Гуру

    Что-то совсем запутался. Казалось бы простая задачка, а решения не нахожу.
    Может уважаемые форумчане - подскажут в чем мой косяк?

    Вот в такой записи:
    Код (C++):
     char *serverM = "m13.cloudmqtt.com";
    Serial.println(serverM);
    в ком порт получаю: m13.cloudmqtt.com - казалось бы все просто.

    В такой записи:
    Код (C++):
    String serverM = (String)("\"" + server.arg("mqtt_server") + "\"");
    Serial.println(serverM);
    в ком порт получаю: "m13.cloudmqtt.com" - не важно с кавычками или без.

    А вот в таком варианте не могу скомпилировать.
    Код (C++):
    char *serverM = (String)("\"" + server.arg("mqtt_server") + "\"");
    Serial.println(serverM);
    cannot convert 'String' to 'char*' in initialization

    Пробовал конвертировать стринг через .c_str(), и прочее, если компилится, то в компорт пишет крякозябрики....
     
  2. rkit

    rkit Гуру

    Неплохо начать с того, чтобы определиться. что же вы пытаетесь сделать. Никто кроме вас этого не знает.
     
  3. ИгорьК

    ИгорьК Гуру

    Иван, это надо перетерпеть :)
     
    Толик Иванов нравится это.
  4. IvanUA

    IvanUA Гуру

    Есть переменная char*serverM ="m13.cloudmqtt.com"
    В ней как вы понимаете хранится адрес сервера.
    Если его прописывать явным образом - как выше, то вопросов не возникает, а вот если я пытаюсь изменить эту переменную через WEB морду вот тут и возникает проблема.
    Из входящего сообщения я этот адрес достаю и если его записать в переменную типа стринг, то он прекрасно отображается, А вот в переменную типа *char лезть не хочет.... пробовал и так server.arg("mqtt_server"),c_str()
     
  5. IvanUA

    IvanUA Гуру

    Игорь, а детальнее можно?
     
  6. rkit

    rkit Гуру

    Читайте про работу со строками в C, в частности про функцию sprintf
     
    IvanUA нравится это.
  7. IvanUA

    IvanUA Гуру

    Вот только в таком варианте нет ошибок компилятора, но

    Код (C++):
      char *serverM = (char*) server.arg('mqtt_server').c_str();
      Serial.println(serverM);
    На выходе имеем только "ї"
    За sprintf - сейчас почитаю
     
  8. ИгорьК

    ИгорьК Гуру

    Детальнее: присутствие rkit в теме обычно мало что дает с практической стороны, но почувствовать себя лохом балабановским приходится. В общем, в каждой деревне такой водится но один.

    По теме я не помогу - Си не тренерую.

    Фигня в чем - появился rkit, нормальные люди не приходят. Поэтому ждать ответа можно долго. Держитесь :)
     
    Толик Иванов, ostrov и DIYMan нравится это.
  9. IvanUA

    IvanUA Гуру

    Игорь, я уважаю Ваше мнение и опыт. Но как говаривал мой дед еще когда.... "даже если ты опытен и мудр, не стесняйся спрашивать..."
    Вот и здесь. Я реально убил на эту тему сутки (а так хотел по бырику закончить и забыть). Что я только не делал, и в массивы загонял символы и прочее. Все одно что-то да не так получалось.... Перевел кучу буржуйских форумов с подобными ошибками и все бестолку....

    А вот rkit - от меня большое спасибо. Направление в котором вы меня послали, оказалось самым удачным.
    Код (C++):
     sprintf(mqtt_server, "%s", server.arg("mqtt_server").c_str());
      Serial.println(mqtt_server);
    Не сразу, но заработало.)))
     
  10. ИгорьК

    ИгорьК Гуру

    :)
     
  11. SergeiL

    SergeiL Оракул Модератор

    Главное только чтобы под именем "mqtt_server" был адрес буфера достаточного размера, а не просто указатель, как в начале.
     
    Последнее редактирование: 26 дек 2017
    IvanUA нравится это.
  12. IvanUA

    IvanUA Гуру

    В настройке глобальных переменных у меня идет оглашение этой переменной со *
    Код (C++):
    char *mqtt_server = "m13.cloudmqtt.com";
    На сколько я успел понять то char *mqtt_server и char mqtt_server[50] - разные вещи.
    И как раз * резервирует под массив символов максимально возможное число ячеек.
    Могу конечно и ошибаться.
     
  13. rkit

    rkit Гуру

    Нет, это одно и то же. Ваше оглашение выделит ровно столько памяти, сколько нужно для хранения строки в кавычках. То же самое число можно просто записать в квадратных скобках, и не будет никакой разницы.
     
    IvanUA нравится это.
  14. SergeiL

    SergeiL Оракул Модератор

    Если Вы используете sprintf(), в качестве указателя на буфер памяти, Вы должны передавать адрес выделенного буфера в памяти (массив, или динамически выделенную область).

    Указанный вами вариант,
    не совсем правильный, указатель здесь указывает на строку, которая может быть размещена в защищенной от записи памяти.

    Правильнее будет:
    или хотя бы:
    Но здесь нужно понимать, что формируемая sprintf() строка, не должна превысить длину строки инициализации.
     
    Последнее редактирование: 26 дек 2017
    IvanUA нравится это.
  15. IvanUA

    IvanUA Гуру

    То есть, если предположить что адрес сервера будет не более 20 символов то лучше использовать
    Код (C++):
    char mqtt_server[20] = "m13.cloudmqtt.com";
    Кстати при вводе адреса с WEB страницы, я тоже ограничил количество вводимых символов в 20 шт.
    Код (C++):
    <div class="col-sm-6">
         <input id="mqtt_server" value="{{mqtt_server}}" class="form-control" pattern="[- 0-9a-zA-Z._/]{1,20}" placeholder="MQTT сервер">
    </div>
     
  16. SergeiL

    SergeiL Оракул Модератор

    Если на WEB странице можно ввести 20 символов, то длина буфера должна быть 21.
    Не забываем, что в си строка всегда завершается "\0".
     
    IvanUA нравится это.
  17. IvanUA

    IvanUA Гуру

    Так чего то подумалось, что таки их должно быть 22)))
    В массивах то счет знаков идет от 0.... И того 20 + 1 симол [0] + 1 в конце \0
     
  18. SergeiL

    SergeiL Оракул Модератор

    Если максимальная длина строки 20 символов.
    В массиве:
    Код (C++):
    char buff[21];
    будет 21 'элемент от buff[0] по buff[20]. С 0-го по 19 будут 20 символов строки, а в 20-м - завершающий '\0'
     
  19. AlexU

    AlexU Гуру

    На будущее: лучше использовать функцию 'snprintf()', вместо 'sprintf()'. При вызове 'snprintf()' Вы ей передаёте не только буфер, но и его длину. И если в процессе форматирования результирующая строка окажется больше буфера, то в буфер будет записано ровно столько, сколько может поместиться с учётом терминального '\0'. А 'sprintf()' ни чего не зная о длине буфера тупо перезапишет данные за пределами буфера, если строка окажется больше. Это может привести к неожиданным и плохо отлавливаемым ошибкам в работе программы.
    И хотя Вы уверенны в том, что строка не будет превышать 20 символов, лишняя перестраховка не помешает.
     
    Securbond, SergeiL, IvanUA и ещё 1-му нравится это.