Concatenating 2 or More Arguments

Arduino’s Serial.print() function accepts only one value to be printed.
However, it is possible to print 2 or more values with the same invocation
to Serial.print() if those values are concatenated to a String value.
The String value can be empty. The 2nd, 3rd, and other arguments are
attached to the initial String argument by using the special concatenation
operator (i.e., +) between the values to be printed.

For example, these lines:

Serial.print("The value of Pi is ");           // Line 1
Serial.println(M_PI);                          // Line 2

can be written in a single line, as long as the first argument is a String:

Serial.println(String("The value of Pi is ") + M_PI);

So how does this work? Consider the following code snippet:

char x[] = {'f', 'o', 'o'};  // x is just a list of chars
char y[] = "foo";            // y is a string
String z = "foo";            // z is a String

Serial.println(String("Size of x is ") + sizeof(x));
Serial.println(String("Size of y is ") + sizeof(y));
Serial.println(String("Size of z is ") + sizeof(z));

This produces the following output:

Size of x is 3               // a list; the values in the list are the 3 chars
Size of y is 4               // a string; it holds the list of 3 chars PLUS an additional trailing byte
Size of z is 6               // a "String"; a complex data type defined in the Arduino program

The variable x is just an array like any other array. Any operation which
works on an array will work on x.

Since y is initialized with text enclosed in double-quotes (""),
it is more than an array. It is a string variable, (which is
different from a list because it is immediately followed by a NULL byte
in memory). The C++ language (on which the Arduino platform is built)
provides many functions which work on strings in addition to those which
work on arrays of char‘s.

The variable z is identified as a String variable, a type of complex
data type with many more capabilities than a simple string. The Arduino
platform offers not not just extra functions which operate on String
objects, but it also operators, in particular, the operator +,
which is defined for String variables to mean concatenation.
Therefore:

String greeting = "Hello";
String salutation = "Mr.";
String lastname = "Brown";
Serial.print(greeting + salutation + lastname);

produces:

HelloMr.Brown

Obviously, this isn’t quite what you wanted: you’d prefer output with spaces between
the words. Just concatenate spaces between the words:

Serial.print(greeting + " " + salutation + " " + lastname);

This produces:

Hello Mr. Brown

Notice that the spaces just concatenated to the String named greeting are
not String variables, but mere string variables as indicated by their
double quotes. The + operator for String objects concatenates
either String objects or mere string objects to a String.
In fact, the String object need not precede the string. Both
these statements display the entire greeting:

Serial.print("Good morning " + salutation + " " + lastname);

and

Serial.print(salutation + " " + lastname + ", good morning!" );

The command Serial.print() demands only that the argument preceding
or immediately following the first concatenation operator be designated
as a bona fide String in order to tolerate being fooled into
printing out a whole collection of variables.

In fact, Serial.print() is even more malleable:

So now let’s rewrite the first example showing
how to print out simple variables:

void setup() {
  Serial.begin(9600);
  while (!Serial) {};         // Wait for the Serial Console to be ready

  char a    = 'x';                   // char values must be enclosed in single quotes
  String b  = "Robotics and Beyond"; // String values must be enclosed in double quotes
  int x     = 15;                    // int's cannot exceed 32767
  int y     = 0x0F;                  // hexadecimal representation of 15.
  long z    = 1000000L;              // long int's can be in the billions
  float n   = 3.14;                  // approximate value of Pi
  double p  = M_PI;                  // more precise value of M_Pi using a built-in constant

  String dummy = "";
  Serial.println(dummy + "a is " + a);
  Serial.println(dummy + "b is " + b);
  Serial.println(dummy + "x is " + x);
  Serial.println(dummy + "y is " + y);
  Serial.println(dummy + "z is " + z);
  Serial.println(dummy + "n is " + n);
  Serial.println(dummy + "p is " + p);
}

void loop() {
}

produces:

a is x
b is Robotics and Beyond
x is 15
y is 15
z is 1000000
n is 3.14
p is 3.14

This looks exactly like the output obtained in first example.

You may be left wondering how to print the value of Pi with better precision.
The answer is to express p as a String variable with a specified precision.
In other words, instead of:

Serial.println(dummy + "p is " + p);

use this:

Serial.println(dummy + "p is " + String(p, 10));

Then the last line appears as:

p is 3.1415927000

A similar problem arises when you want to display an integer in some format other
than the default (i.e., decimal). Suppose for example that you want to display an
integer in HEX format. Once again, it is necessary to call the String function
to get the desired result:

int n = 255;
Serial.print(dummy + "n is " + String(n, HEX);

This produces:

n is ff

Improved Text Formatting

The Serial Console that is part of the Arduino IDE can process only a couple of
text formatting commands, including TAB and NEWLINE. Use of these
commands can clarify your display output, thereby making it easier for users
to notice the things you want them to see.

An obvious example of the need of TAB‘s for alignment is the table shown
previously
where integers 0 through 15 were printed in decimal (DEC), hexadecimal
(HEX), octal (OCT), and binary (BIN) format. In the output, the values
weren’t aligned neatly in columns, so it wasn’t so obvious how numbers were
transformed into binary format. In the following re-write of that example,
TAB‘s are used to align the columns (this achieves left-alignment, not
(sigh) right alignment). You could embed TAB‘s just by pushing the TAB
key on your keyboard, but this leads to code which is hard to maintain (since
you can’t see the TAB‘s). A better way is to use the expression \t
to embed a TAB.

This is the re-written sketch:

void setup() {
  Serial.begin(9600);
  while (!Serial) {};         // Wait for the Serial Console to be ready

  String dummy = "";          // dummy empty String
  for (int i=0; i<=15; i++) {
    Serial.println(dummy + i      + "\t" + 
                   String(i, HEX) + "\t" +
                   String(i, OCT) + "\t" +  
                   String(i, BIN));
  }
}

Now the output is aligned:

0       0       0       0
1       1       1       1
2       2       2       10
3       3       3       11
4       4       4       100
5       5       5       101
6       6       6       110
7       7       7       111
8       8       10      1000
9       9       11      1001
10      A       12      1010
11      B       13      1011
12      C       14      1100
13      D       15      1101
14      E       16      1110
15      F       17      1111

(To get the values right-aligned requires either that you write a function to
do that, or that you use the low-level printf() function, as mentioned in
the Introduction to this packet.)

The Arduino Serial Console also understands one more formatting sequence,
namely NEWLINE, which can be inserted into your text using \n.
The NEWLINE sequence is only really useful when you want to embed 2 or more
newlines within the text of a single Serial.print() command.

For example, here’s a smiley face (OK, lame) using ascii characters and
multiple embedded NEWLINE‘s:

Serial.print(dummy + "        \n" +
                     "        \n" +
                     "  0  0  \n" +
                     "        \n" +
                     " x    x \n" +
                     "  xxxx  \n\n");

which produces:

      0  0

     x    x 
      xxxx

Here’s a (less frivolous!) example, where a fancy header is created
using multiple NEWLINE‘s:

Serial.print(dummy + "/******************************\n" +
                     " * Readings from Analog Pin 0 *\n" + 
                     " ******************************/\n");

which produces:

/******************************
 * Readings from Analog Pin 0 *
 ******************************/