string

Тип string в Arduino — это массив char с нулевым символом в конце: экономит память и совместим с функциями strcmp(), strcpy(), sprintf().

Полная статья

Описание

В Arduino текст можно хранить двумя способами: использовать объект String или работать с обычным массивом типа char, вручную позаботившись о нулевом завершении. Эта статья посвящена второму подходу — так называемым C-строкам. Он требует чуть больше внимания, но потребляет меньше памяти и лучше подходит для ресурсоограниченных плат. Если вам нужны удобные методы работы с текстом и объём памяти не критичен, обратитесь к странице String object.

Синтаксис

Существует несколько равнозначных способов объявить строку на основе char:

  • char Str1[15];
  • char Str2[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o'};
  • char Str3[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o', '\0'};
  • char Str4[] = "arduino";
  • char Str5[8] = "arduino";
  • char Str6[15] = "arduino";

Варианты объявления

  • Объявить массив символов нужного размера без начального значения — как в Str1. Содержимое определяется позже.
  • Объявить массив с запасом на один символ и инициализировать его набором символов — компилятор сам добавит нулевой символ в конец, как в Str2.
  • Явно вписать нулевой символ '\0' в конец массива символов — Str3.
  • Инициализировать строковым литералом в двойных кавычках, не указывая размер — компилятор подберёт его автоматически с учётом завершающего нуля, как в Str4.
  • Инициализировать строковым литералом с явным указанием размера массива — Str5.
  • Объявить массив с запасом для будущего расширения строки — Str6.

Нулевое завершение строки

Главное правило C-строк: в конце всегда должен стоять нулевой символ (ASCII-код 0, записывается как '\0'). Именно по нему стандартные функции вроде Serial.print() определяют, где заканчивается строка. Если нулевого символа нет, функция продолжит читать память за пределами массива — это приведёт к непредсказуемому поведению или сбою.

Практически это означает, что массив должен быть на один элемент длиннее самого текста. Именно поэтому Str2 и Str5 объявлены с размером 8, хотя слово «arduino» содержит 7 символов: восьмая позиция отводится под нулевой символ. В случае Str4 компилятор сам посчитает нужный размер. В Str3 нулевой символ добавлен вручную явно.

Технически можно создать массив без нулевого символа в конце — например, указав размер Str2 равным 7. Большинство функций при этом сломаются. Если ваш скетч ведёт себя странно и выводит случайные символы после строки — первым делом проверьте, есть ли нулевое завершение.

Одинарные и двойные кавычки

Важно не путать: строки всегда заключаются в двойные кавычки ("Abc"), а одиночные символы — в одинарные ('A'). Использование одинарных кавычек для строки приведёт к ошибке компиляции.

Перенос длинных строк

Если строковой литерал не помещается в одну строку кода, его можно разбить на части:

    char myString[] = "This is the first line"
    " this is the second line"
    " etcetera";

Массивы строк

Когда нужно хранить набор текстовых сообщений — например, для вывода на LCD-дисплей — удобно использовать массив строк. Поскольку каждая строка сама является массивом char, результатом будет двумерный массив.

В примере ниже звёздочка в объявлении char " char*" означает, что переменная является указателем — точнее, массивом указателей " pointers". Все имена массивов в C++ по сути являются указателями, поэтому такой синтаксис необходим для создания массива строк. Углубляться в теорию указателей необязательно — достаточно понимать, что эта конструкция позволяет хранить несколько строк и обращаться к ним по индексу.

Пример кода

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

Где применяется

  • Вывод фиксированных сообщений на дисплей — массив строк позволяет хранить меню или подсказки и выводить нужную по индексу.
  • Разбор команд через Serial — принятые байты записываются в char-буфер и сравниваются со строками-командами через strcmp().
  • Форматирование данных — функции sprintf() и snprintf() работают именно с char-массивами и позволяют собирать строки из чисел и текста.
  • Экономия памяти — на платах с малым объёмом ОЗУ (например, Arduino Uno) char-массивы потребляют значительно меньше памяти, чем объекты String.

Практические замечания

  • Всегда выделяйте на один байт больше, чем длина текста — для нулевого символа.
  • Не копируйте строки оператором =: используйте strcpy() или strncpy(), иначе вы скопируете только указатель.
  • Функция strlen() возвращает длину строки без нулевого символа — учитывайте это при выделении буферов.
  • При работе с Serial.readBytesUntil() или аналогичными функциями вручную добавляйте '\0' после последнего принятого символа.
  • Переполнение буфера (запись за пределы массива) — одна из самых частых ошибок при работе с C-строками. Всегда проверяйте, что записываемый текст помещается в объявленный массив.

Полезные материалы