Как напечатать несколько строк в строке?
Скажем, у меня есть некоторые переменные, которые я хочу распечатать на терминале, что самый простой способ распечатать их в строке?
В настоящее время я делаю что-то вроде этого:
Serial.print ("Var 1:"); Serial.println (var1);
Serial.print («Var 2:»); Serial.println (var2);
Serial.print («Var 3:»); Serial.println (var3);
Есть ли лучший способ сделать это?
10 ответов
ardprintf
- это функция, которую я взломал вместе, которая имитирует printf
по последовательному соединению. Эта функция (приведенная внизу) может быть вставлена в начало файлов, где нужна функция. Он не должен создавать конфликтов.
Его можно назвать похожим на printf
. Посмотрите его в действии в этом примере:
void setup ()
{
Serial.begin (9600);
}
void loop ()
{
int l = 2;
char * j = "test";
long k = 123456789;
char s = 'g';
float f = 2.3;
ardprintf ("test% d% l% c% s% f", l, k, s, j, f);
Задержка (5000);
}
Ожидаемый результат:
test 2 123456789 g test 2.30
Прототип функции:
int ardprintf (char *, ...);
Он возвращает количество аргументов, обнаруженных в вызове функции.
Это определение функции:
#ifndef ARDPRINTF
#define ARDPRINTF
#define ARDBUFFER 16
#include <stdarg.h>
#include <Arduino.h>
int ardprintf (char * str, ...)
{
int i, count = 0, j = 0, флаг = 0;
char temp [ARDBUFFER + 1];
for (i = 0; str [i]! = '\ 0'; i ++) if (str [i] == '%') count ++;
va_list argv;
va_start (argv, count);
для (i = 0, j = 0; str [i]! = '\ 0'; i ++)
{
если (ул [я] == '%')
{
temp [j] = '\ 0';
Serial.print (температура);
J = 0;
temp [0] = '\ 0';
Переключатель (ул [++ я])
{
case 'd': Serial.print (va_arg (argv, int));
ломать;
case 'l': Serial.print (va_arg (argv, long));
ломать;
case 'f': Serial.print (va_arg (argv, double));
ломать;
case 'c': Serial.print ((char) va_arg (argv, int));
ломать;
case 's': Serial.print (va_arg (argv, char *));
ломать;
по умолчанию: ;
};
}
еще
{
temp [j] = str [i];
j = (j + 1)% ARDBUFFER;
если (J == 0)
{
temp [ARDBUFFER] = '\ 0';
Serial.print (температура);
Темп [0] = '\ 0';
}
}
};
Serial.println ();
return count + 1;
}
#undef ARDBUFFER
#endif
** Чтобы напечатать символ %
, используйте %%
. *
Теперь, доступный на Github gists .
Обычно я не ставил два ответа на вопрос, но я только что нашел этот сегодня, где вы можете использовать printf без какого-либо буфера.
//Функция printf и связанная с ней печать
int serial_putchar (char c, FILE * f) {
if (c == '\ n') serial_putchar ('\ r', f);
return Serial.write (c) == 1? 0: 1;
}
FILE serial_stdout;
void setup () {
Serial.begin (9600);
//Настроить stdout
fdev_setup_stream (& serial_stdout, serial_putchar, NULL, _FDEV_SETUP_WRITE);
stdout = & serial_stdout;
printf («Мое любимое число -% 6d! \ n», 12);
}
void loop () {
статический длинный счетчик = 0;
if (millis ()% 300 == 0) {
printf ("millis ():% ld \ tcounter:% ld (% 02X) \ n", millis (), counter, counter ++);
задержка (1);
}
}
Это все еще имеет ограничение с плавающей запятой.
edit: Я думал, что немного поработаю над этим, и он работает очень хорошо. Я добавил лучший тест в цикл с форматированным выходом.
Это, вероятно, не лучше, просто другое. Вы можете использовать объект String для вывода. Эти объекты позволяют конкатенацию и поддерживают автоматическое типирование.
Serial.begin (9600);
Строковая метка = "Var";
const byte nValues = 3;
int var [nValues] = {36, 72, 49};
for (int i = 0; i <nValues; i ++) {
String stuff = label + i + ":";
Serial.println (материал + var [i]);
}
Обычно я использовал вкладки, чтобы все стало лучше в Serial. Имея элементы, как я могу позволить arduino стрелять как можно быстрее, будучи в состоянии заметить определенные изменения в переменных.
Попробуйте что-то вроде этого:
Serial.println ("Var 1: \ tVar 2tVar 3:");
Serial.print ( "\ т");
Serial.print (var1);
Serial.print ( "\ т");
Serial.print (var2);
Serial.print ( "\ т");
Serial.print (var3);
Serial.println ();
Или что-то вроде этого:
Serial.print ("Var 1:"); Serial.println (var1);
Serial.print ("\ tVar 2:"); Serial.println (var2);
Serial.print ("\ tVar 3:"); Serial.println (var3);
Обычно я (больно) придерживаюсь нескольких строк Serial.print
, но когда он становится запутанным, я возвращаюсь к sprintf
. Это раздражает то, что у вас должен быть доступный буфер для него.
Использование так же просто (??), как:
char buffer [35]; //вы должны знать, как долго ваши данные могут быть
//не забывая о непечатаемых и нулевых символах
Sprintf (буфер, "var1:% I \ tvar2:% I \ tvar3:% I", var1, var2, var3);
Serial.println (буфер);
Слово предупреждения, однако, не поддерживает (по умолчанию) поддержку плавающих типов.
Я использую это только для отладки, но:
int a = 10;
int b = 20;
Serial.println ("a =" + String (a) + "и b =" + String (b));
Используя Streaming.h
вместо
Serial.print ("Var 1:"); Serial.println (var1);
Serial.print («Var 2:»); Serial.println (var2);
Serial.print («Var 3:»); Serial.println (var3);
можно написать
Serial <"Var 1:" <var1) <"Var 2:" <var2 <"Var 3:" <var3 <епсИ;
Определение <
в Streaming.h
, в сущности, переводит это в ряд обычных вызовов Serial.print ()
, То есть <
представляет собой синтаксический сахар, реализованный без увеличения размера кода.
Если у вас нет установленного Streaming.h
, получите Streaming5.zip
из arduiniana.org . Разархивируйте его в каталог ваших библиотек, например, в ~ /sketchbook /libraries
. Добавьте строку #include <Streaming.h>
в эскизы, где вы используете <<
в качестве оператора потока.
Предусмотрены спецификаторы базового преобразования _HEX, _DEC, _OCT и _BIN, а также функция _FLOAT (с числом десятичных знаков) и endl
. Например, для печати значений широты и долготы в форме «Ваши координаты: -23.123, 135.4567» можно написать:
Serial <«Ваши координаты« <<_FLOAT (широта, 3) <"," <_FLOAT (долгота, 4) <епсИ;
Это также можно записать как
Serial <F («Ваши координаты») <<_FLOAT (широта, 3) <"," <_FLOAT (долгота, 4) <епсИ;
, который сохранил бы более длинную строку в PROGMEM вместо того, чтобы вносить ее в ОЗУ.
Примечание, Streaming.h
не создает никаких строк как таковых; он просто доставляет текст своих <
-аргументов в поток. A класс PString на arduiniana может создавать строки из входов потока, если нужны строки вместо потокового вывода или необходимо.
Использование будет зависеть от типа данных ваших переменных.
Если они int
, это будет % d
или % i
Если они string
, это будет % s
Обертка для печати
Вы можете изменить лимит на основе ваших требований
#include <stdarg.h>
void p (char * fmt, ...) {
char buf [128]; //результирующая строка, ограниченная 128 символами
va_list args;
va_start (args, fmt);
vsnprintf (buf, 128, fmt, args);
va_end (args);
Serial.print (BUF); //Результат вывода в Serial
}
Источник: https://playground.arduino.cc/Main/Printf
Примеры использования:
p ("Var 1:% s \ nVar 2:% s \ nVar 3:% s \ n", var1, var2, var3); //строки
p ("Var 1:% d \ nVar 2:% d \ nVar 3:% d \ n", var1, var2, var3); //номера
ESP8266
Его встроенный в Serial
класс фреймворка. Нет необходимости в дополнительной библиотеке или функции.
//строки
Serial.printf ("Var 1:% s \ nVar 2:% s \ nVar 3:% s \ n", var1, var2, var3);
//номера
Serial.printf ("Var 1:% d \ nVar 2:% d \ nVar 3:% d \ n", var1, var2, var3);
Подробнее о советах по форматированию на странице справки формата printf: http: //www. cplusplus.com/reference/cstdio/printf/
\ n
- это escape-последовательность для строки.
Последовательности Escape используются для представления определенных специальных символов в строковых литералах и символьных литералах.
Источник: http://en.cppreference.com/w/cpp/language /бежать
[EDIT] - Как отметил @Juraj, он недоступен на большинстве модулей AVR. Поэтому я добавил упоминание ESP8266 и оболочку printf для общих модулей AVR.
От http://playground.arduino.cc/Main/Printf Я заметил, что это отлично работает на моем mega2560
Вот и все, что просто сработало, нет необходимости в vsnprintf_P или PROGMEM ...
#include "Arduino.h"
void local_printf (const char * format, ...)
{
статическая линия счисления [80];
va_list args;
va_start (args, format);
int len = vsnprintf (строка, sizeof (строка), формат, args);
va_end (арг);
для (char * p = & line [0]; * p; p ++) {
if (* p == '\ n') {
Serial.write ( '\ г');
}
Serial.write (* р);
}
if (len> = sizeof (строка))
Serial.write ( '$');
}
void setup ()
{
Serial.begin (115200);
local_printf ("% s:% d:% s \ n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
}
void loop ()
{
static int count = 0;
local_printf ("% s:% d:% s% d \ n", __FILE__, __LINE__, __PRETTY_FUNCTION__, count ++);
задержка (1 * 1000);
}
//src /main.c: 24: void setup ()
//src /main.c: 30: void loop () 0
//src /main.c: 30: void loop () 1
int Money_amount = 55;
Serial.print (String («Новая сумма: $» + Money_amount));
Вы увидите на терминале:
Новая сумма: $ 55