Overview of this Chapter
A complete overview of this course can be found here: Course Overview.
Working with Text: Strings!
It’s all nice and dandy to work with booleans and numbers, but we also need to work with text to communicate.
Granted, the Arduino doesn’t have much use for text when used on it’s own. It has no display. But a display can be attached, or text can be send/received through the serial port and other ways of communication.
We have used strings already a few times. Each time when we used a “Serial.print()
” or “Serial.println()
“, we actually already used strings. Remember that a text in C needs to be enclosed in double quotes? That would make it a string.
But to work well with strings, we need to understand what a string really is.
First of all, we can use a “string” (all lowercase!) – where a string is a so called array of characters. In English that makes sense: it’s a “list” of characters.
The second way of working with strings is by using the “String” object (notice the capital “S”?).
Both will be discussed and shown to you in the next paragraphs and chapters …
Ad Blocking Detected Please consider disabling your ad blocker for our website.
We rely on these ads to be able to run our website.
You can of course support us in other ways (see Support Us on the left).
Array of Char (string)
An “array” (Array Data Type, Array Data Structure) can be seen as a collection of elements of the same data type.
See it, in it’s simplest form, as a list. In the case of a string: a list of char(acters).
A string (all lower case !!!) is an ARRAY OF CHARACTERS
The variable that we define, actually points to the first item in the array – or better said: it points to the memory location of the first item.
In the case of a string, the array keeps going, until your Arduino finds a NULL character. The NULL character terminates the string – or indicates the end of the string.
Say what now?
Yep, a NULL, a nothing. There is a special character defined for this (see our character list).
It’s character zero. But we do not (yet) have to worry about that – but it is something to keep in mind. Since strings are quite often used, the language “C” which we use for Arduino Programming, comes with a standard library of string related functions, which handle quite a lot already automatically.
Another thing to keep in mind is that arrays start counting with “0” for item 1, “1” for item 2, etc.
This is called zero indexed or zero based numbering – counting starts with zero.
A string (Array of Characters), is terminated by a NULL character.
Arrays are ZERO INDEXED, which means they start counting with zero.
So an example could be: string Name = “Hans”;
However, that doesn’t work … you’ll get an error message that “string” was not defined.
The correct way to define a string would be: char Name[] = "Hans";
What this does, is create an array of characters (which is a string), the empty square brackets basically says “compiler! Go figure out yourself how large this array should be“. If we would have entered a number, then that number should at least be big enough to hold our string plus one NULL character.
In the example that would be 4 characters for our text and a fifth character for the NULL character.
We can also define a string with a fixed length like this: char Name[5] = "Hans";
Note that if the number is bigger than the number of characters we need, then this will work just fine. However, your Arduino might allocate the extra characters as well and waste memory space as we’re not using it. On the other hand, if you expect the string to change in the program and all those characters might be needed, then you’d already be prepared.
If this number would be too low, then your compiler will complain and show an error message.
Leaving length the string array (char variablename[] = “…”) undefined will make that the compiler determines the required size of the array – one time only!
Accessing an Element of an Array outside of the length of the array can cause unexpected results, error messages or even crashes of your application!
In either case, it will result in this:
String Array
position (index) |
Content of memory slot |
0 |
H |
1 |
a |
2 |
n |
3 |
s |
4 |
NULL |
The variable “Name” points to the memory location of the “H” character of the string, which is at position 0 (zero) and therefor has “0” as it’s index number.
We can actually retrieve that character. For example “Name[2]” would result in an “n”, “Name[0]” would return a “H”, etc.
If we send address the whole variable, “Name”, then it would return the address of “Name[0]” but your program will keep pulling up the next index, and the next, and the next, until it reaches that NULL character. So in the end, it will return the text of the string.
char Name[] = "Hans";
Serial.println(Name[2]); // prints "n"
Serial.println(Name[0]); // prints "H"
Serial.println(Name); // prints "Hans"
Now we can actually assign a different character to an element (or item) in an array.
Assigning a new text to a string
We now know about variables and strings, and we know how to define a string and assign it an initial value.
What if we want to change the string, for example, replace in “Hans” in our string with “Bram”?
Strangely enough, the following does not work: Name = "Bram";
The Arduino compiler will give you the error message “invalid array assignment”. But a string is a string right?
Not really. Remember how I said before that the variable (in our example “Name”) actually points to the memory location of the first element in the array? It’s a memory address, which is not the same as a string. Believe me, this is something you’ll run into quite often, and it’s one of the reason why I’m not a fan of the C-language (I’m more of a Pascal fan – and plenty of people will argue with me on that one).
Unfortunately this makes things more complicated, and we’d have to assign each character to the proper element. Thank goodness there is a function for that: strcpy()
.
This function, read it as “String Copy”, takes 2 parameters.
The destination where the string should be copied to, and the source where the string is coming from.
The destination should be a variable, it has to be able to “receive” the data, so it has to be the proper data type as well.
The source can be a variable, a constant, or a string (tekst between double quotes).
An example on how to use this, see line 12 where we use strcopy :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
char Name[] = "Hans";
Serial.println(Name[2]); // prints "n"
Serial.println(Name[0]); // prints "H"
Serial.println(Name); // prints "Hans"
strcpy(Name, "Bram");
Serial.println(Name[2]); // prints "a"
Serial.println(Name[0]); // prints "B"
Serial.println(Name); // prints "Bram"
}
void loop() {
// leave empty for now
} |
Ad Blocking Detected Please consider disabling your ad blocker for our website.
We rely on these ads to be able to run our website.
You can of course support us in other ways (see Support Us on the left).
Escape Characters or … Special Characters
Now sometimes we’d like to print for example double quotes, but just typing them into a string will not work – the string would break. The compiler will think you’re done after seeing the second double quotes and everyting remaining will become an unclear mess.
Other special characters are simply impossible to type without making things a mess as well!
As an example that will fail: Serial.println("Hello "guest", welcome to Arduino");
The color highlighting of the Arduino IDE’s text editor already shows your this …
The code highlighting of the Arduino IDE text editor, will show you if a string “breaks” or not, by changing character colors in the string you just typed.
To actually enter a double quote in a string, we need to use an escape character, which in the language C is the backslash (\).
The correct way would be: Serial.println("Hello \"guest\", welcome to Arduino");
The following example shows just that:
The first line shows us the wrong way of doing it. The keywords of importance are printed in orange en the string in a green-like color. But … our string has a chunk of black text in it. The word “guest” is black. It means that this is not part of the string, which is caused by the double quotes around the word “guest”.
Now the second line shows the colors the way they should be, and for that we removed the double quotes. You see the entire string being green-ish?
The third line shows us the trick with the backslash. We placed them right before the special character, so the compiler knows that the next character is special and part of the string.
Arduino IDE code highlighting example
Note that when you want the next character to be special as well, then you’d need to “escape” those as well. For example if we add multiple double quotes around the word “guest”: Serial.println("Hello \"\"guest\"\", welcome to Arduino");
This trick has to be used for certain other characters as well, for example starting a new line is an ASCII character (see the character table, and look in the “Esc” column). If we’d like to place a line break (start a new line) in our string, then we would need ASCII character 10, which we write as “\n”.
The most common ones are:
Most Common Escape Characters
Escape “code” |
ASCII |
Purpose |
\n |
10 |
LF (Line Feed) – Start new line (new line) |
\r |
13 |
CR (Carriage Return) – Go to beginning of a line (return) |
\t |
9 |
Tab – Advance cursor to next tab-stop (tab) |
\” |
34 |
Double Quote |
\’ |
39 |
Single Quote |
\\ |
92 |
Backslash – so we can actually type that one as well |
You do not need to memorize these, you’ll remember them after having used them a few time.
Character versus String or Single Quote versus Double Quote
We have mentioned that we could assign individual characters to the array elements of our string,… so how is that done then?
We have seen that we use double quotes ( “ ) to enclose a sequence of characters.
We can even make a string of zero characters (just: “”) or a string of one character (“A”).
But these are all strings.
Double quotes are used for strings, which can be zero or more characters.
The following code will not work, when we try to assign a character to one of the memory locations of our string (array of char):
Name[1] = "H"; // will generate an error message
The error message invalid conversion from 'const char*' to 'char'
tells us that we are assigning the wrong kind of datatype to our array element. In simple words: This is because we are trying to assign a string to a character.
To make this work, we need to assign a character to the char, instead of a string and for that purpose we use single quotes ( ‘ ).
A way to remember this: one quote = one character, multiple quotes = multiple characters.
Single quotes are used for char(acters), which is exactly one character.
This example will work:
Name[1] = 'H'; // this works!
Let’s look at the previous example, and expand it a little. We want to replace the name “Hans” with the name “Bram”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
char Name[] = "Hans";
Serial.println(Name[2]); // prints "n"
Serial.println(Name[0]); // prints "H"
Serial.println(Name); // prints "Hans"
Name[0] = 'B';
Name[1] = 'r';
Name[2] = 'a';
Name[3] = 'm';
Serial.println(Name[2]); // prints "a"
Serial.println(Name[0]); // prints "B"
Serial.println(Name); // prints "Bram"
}
void loop() {
// leave empty for now
} |
See how we have to assign each individual character to each individual array element?
We can skip “Name[4]” because it already holds the NULL character and we do not want to change that.
However, if our string becomes shorter, for example by replacing “Hans” with “Max” (my other nephew), then we would need to add the NULL character again:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
char Name[] = "Hans";
Serial.println(Name[2]); // prints "n"
Serial.println(Name[0]); // prints "H"
Serial.println(Name); // prints "Hans"
Name[0] = 'M';
Name[1] = 'a';
Name[2] = 'x';
Name[3] = 0;
Serial.println(Name[2]); // prints "x"
Serial.println(Name[0]); // prints "M"
Serial.println(Name); // prints "Max"
}
void loop() {
// leave empty for now
} |
Now “Name[3]” and “Name[4]” are both a NULL character, which is equal to zero.
See how we assign a char a number, where we assign the number zero to Name[3]?
Instead of assigning it a character, we can actually use the ASCII code for a given character.
See our character table for those numbers (look at the column “DEC”).
So to compare, an example with characters and the same one with ASCII codes:
// With characters
Name[0] = 'B';
Name[1] = 'r';
Name[2] = 'a';
Name[3] = 'm';
// With ASCII codes
Name[0] = 66; // = 'B'
Name[1] = 114; // = 'r'
Name[2] = 97; // = 'a'
Name[3] = 109; // = 'm'
Obviously, using ASCII is not the obvious way to do it when you’d like to assign text to a string. However, there are scenario’s where this can be very practical. I’ll illustrate this with a quick nonesense example, which quickly lists all the letters of the alphabet, where we can use a “for” loop to count from 65 (=A) to 90 (=Z).
The “for” loop can be used with numbers, or basically anything we can enumerate, or in other words: Data types that we can count with fixed increments, or whole numbers. For example, a byte, or an integer (both whole numbers):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
char Letter[] = " ";
for(byte A=65; A<=90; A++) {
Letter[0] = A;
Serial.println(Letter[0]);
}
}
void loop() {
// leave empty for now
} |
Now that we know that characters are done with single quotes, we could also do this with this kind of loop.
Just keep in mind that a char can be “counted” as well, and this actually does work (see code below). Char is in essence a “byte”, and as we just have seen, we can assign it a number – so char can be counted as well, as if it’s a whole “number”.
Note : don’t forget that we are counting chars – so we must use single quotes!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
char Letter[] = " ";
for(char A='A'; A<='Z'; A++) {
Letter[0] = A;
Serial.println(Letter[0]);
}
}
void loop() {
// leave empty for now
} |
In both examples the output will be the alphabet in uppercase characters.
Ad Blocking Detected Please consider disabling your ad blocker for our website.
We rely on these ads to be able to run our website.
You can of course support us in other ways (see Support Us on the left).
Other Array Functions: strlen, sizeof, strcat
We have seen that function “strcpy()” (read that as “string Copy”). There are a few practical other functions we should mention.
strlen()
“strlen()” (read as: String Length) takes one parameter, a string, and returns the number of characters in the string. It will however not count the NULL character at the end.
sizeof()
“sizeof()” does the same thing as “strlen()”, however it will include the NULL character in it’s count. It actually returns the size of the full array, even if it would be filled with NULL characters.
strcat()
“strcat()” is an odd one, it will add a string at the end of a given string variable. Read this one as “String Concatenate”.
Example of strlen, sizeof, strcat
Let’s glue these 4 functions together in an example, so you get an idea.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
char Name[45] = "Hans";
int count = 0;
Serial.print("Name = ");
Serial.println(Name);
// determine length
count = strlen(Name);
Serial.print("Length of Name with strlen: ");
Serial.println(count);
// determine array size
count = sizeof(Name);
Serial.print("Length of Name with sizeof: ");
Serial.println(count);
strcat(Name, " has two nephews, called Bram and Max!");
Serial.print("Name = ");
Serial.println(Name);
// determine length
count = strlen(Name);
Serial.print("Length of Name with strlen: ");
Serial.println(count);
// determine array size
count = sizeof(Name);
Serial.print("Length of Name with sizeof: ");
Serial.println(count);
}
void loop() {
// leave empty for now
} |
The resulting output:
Name = Hans
Length of Name with strlen: 4
Length of Name with sizeof: 45
Name = Hans has two nephews, called Bram and Max!
Length of Name with strlen: 42
Length of Name with sizeof: 45
Now if you remember from earlier where I said:
- If we do not define the string length, the compiler will determine/guess the length one time only!
- Accessing elements beyond the size of the array can give unexpected results.
OK, let’s do this intentionally by modifying line 5 to char Name[] = "Hans";
What this does, is that the compiler will guess the required array space, one time only! This means that it will see the string “Hans” and will determine that these 4 characters will need an array of 5 characters (text plus NULL character).
Compile and upload the modified code to your Arduino and you will see something goofy happening, for example:
Name = Hans
Length of Name with strlen: 4
Length of Name with sizeof: 5
phews, called Bram and Max!Hans has two nephews, called Bram����
See the funny characters, and you might notice that your Arduino keeps spitting out funny and weird characters!?
That’s because the array was only 5 characters long.
When we added ” has two nephews, called Bram and Max!” to that string/array, we royally exceed the pre-defined space, and your Arduino will try to print that anyway. Not being able to find the NULL character (we have overwritten it with a non-NULL character, a space-character, in this example), it will keep spitting out whatever is in memory until it finds a NULL character. Which might be right away, or never …
Not exactly what we expected to happen right?
And thats the reason why you have to pay attention to the length of an array.
String Object (String with capital “S”)
The previous “string” was an Array of Char. With a lowercase “s”.
The Arduino IDE however, offers another “String” (capital “S”), which is an object.
The tedious and cumbersome things we had to do with the old “string” (lowercase: Array of Char), are done much easier with the “String” (Capital “S”: an object) object … but what is an object?
Objects
We haven’t learned much about objects yet, even though we have already used one (Serial).
A very short explanation of what an “object” is, would be a “thing” or “item” with properties and functions (methods).
An Object is a “thing” with “properties” and “methods” (functions)
Such a “thing” could be anything, for example a “car“.
Let’s keep this simple and assume a car has a color, a working engine, possibly some gas, number of doors, a trunk, and wheels.
These are called “properties“, they do not do anything, they’re just a given fact, items it already has (or could have).
One of those “could have” properties could be “driver”.
Since the car can be empty (driver == NULL), or a driver can sit in the drivers-seat (driver != NULL).
Now a car can move (driving), park, honk it’s horn, open or close the trunk, open or close the doors, etc.
These are functions of the object “car”. In “object oriented programming” we call those “methods“.
Methods actually “do” something, actions you can do have the car do or that can be done with the car.
There are several reason why we’d like to use objects.
For one; everything is logically grouped together. There is no confusion to what item the properties or functions belong. So when we aks for properties or call a method (function) of a given object “car” then we know it only relates that that specific car.
Another reason is that once an object has been defined, it actually kind-a behaves like a data type, which can use for variables. Say we have one “car” then we create a variable “MyCar” as the object (data type) “car”. But if we have a garage filled with cars, then we can re-use that same definition to create multiple variables (MyCar, YourCar, DadsCar, MomsCar), or even an array of cars (Cars[0], Cars[1], Cars[2],…).
Now we won’t go into object right now, but it’s good to have a basic understanding what an object is.
The “String” (with capital “S”) and “Serial” are such objects.
With “Serial” we have already seen the methods (functions) “begin”, “print” and “println”. We call these methods to have the object do something , like start communication, or send a string to our Serial Monitor of our Arduino IDE.
Maybe you’ve now seen that we always call an object in a format like this: OBJECT.METHOD or OBJECT.PROPERTY? We call the object and separate object and method (or property) with a period.
The “String” Object
As mentioned and shown before: the array of char variant of a string is a little cumbersome to work with. So the good people at Arduino created an object to make working with strings easier. Again a reminder: it’s the “String” with a capital “S”!!!
You will see pretty quickly how much more powerful the “String” is compared to the “string”.
Let’s start with creating a variable of data type “String”: String Name = "Hans";
As we have seen with the old “string”, we can simply create a variable and assign it a value in one single line. Nothing new there, well except for the keyword “String” of course and the lack of square brackets.
Like we have seen with the other “string”, we can also use “Serial.print()”. So let’s shove this together in a quick example:
1 2 3 4 5 6 7 8 9 10 11 12 13
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
String Name = "Hans";
Serial.print("Name = ");
Serial.println(Name);
}
void loop() {
// leave empty for now
} |
Works just like the old “string”, and the result in the Serial Monitor will be: Name = Hans
Nothing new, and nothing exciting just yet.
Now let’s try to change “Hans” to “Bram” in our code. We can do this by assigning a “String” to a “String”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
String Name = "Hans";
Serial.print("Name = ");
Serial.println(Name);
Name = "Bram";
Serial.print("Name = ");
Serial.println(Name);
}
void loop() {
// leave empty for now
} |
Line 10 could also be written as Name = String("Bram");
, which will actually work as well, but now we assign the new object (holding the string “Bram”) to the old object, versus the method in the code where we assign just a string to the object.
At least we already see that assigning new text to “String” is easier.
Now let’s make that string longer, in the previous example, when using the array of char “string”, we noticed that we had to pay attention to the size of the array, so we wouldn’t go beyond it’s capacity. The “String” object however saves us that worry. It corrects automatically.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
String Name = "Hans";
Serial.print("Name = ");
Serial.println(Name);
Name = "Hans has two nephews, their names are Bram and Max!";
Serial.print("Name = ");
Serial.println(Name);
}
void loop() {
// leave empty for now
} |
You see? We can assign a much larger string than what we started out with, and when printing it, we experience zero problems. This is already a second point where the object is easier to use.
So if the “String” object is so much easier to work with? Then why even bother with the “string” array of character?
For two reasons. For one, the object will take up more memory, since it has all these fancy properties and methods. Another reason is that the String object, actually uses the “string” array of characters as well.
Ad Blocking Detected Please consider disabling your ad blocker for our website.
We rely on these ads to be able to run our website.
You can of course support us in other ways (see Support Us on the left).
String object Methods (functions)
Now the “String” object, has a lot of methods (functions) we can work with, which can make our life a lot easier when working with strings, and this is where we will really see the power of objects.
Below an example of some of this trickery … for a full list of available functions, please take a good look at the Arduino String Object Reference. It will show you all the other tricks.
Length(), Concat() and convert numbers
In the example below we will concatenate strings, determine the length of the string and even add numbers to our string, without any real effort.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
String Name = "Hans";
Serial.print("Name = ");
Serial.println(Name);
// determine length
Serial.print("Length of Name with strlen: ");
Serial.println(Name.length());
Name.concat(" has two nephews, called Bram and Max!");
Serial.print("Name = ");
Serial.println(Name);
// determine length
Serial.print("Length of Name with strlen: ");
Serial.println(Name.length());
// Alternative way of adding text
Name = "Hans"; // reset to original text
Serial.print("Name = ");
Serial.println(Name);
Name += " has 2 nephews";
Name = Name + ", the are called Bram" + " and Max";
Serial.print("Name = ");
Serial.println(Name);
// this won't work with arrays
Name = "A large number is: ";
Name = Name + 32768;
Serial.print("Name = ");
Serial.println(Name);
}
void loop() {
// leave empty for now
} |
The output of this code:
Name = Hans
Length of Name with strlen: 4
Name = Hans has two nephews, called Bram and Max!
Length of Name with strlen: 42
Name = Hans
Name = Hans has 2 nephews, the are called Bram and Max
Name = A large number is: 32768
Let’s walk through this example.
We create the String object “Name” and assign it the value “Hans” (lines 7 and 8), which we can print with “Serial” as we have seen before. Now in line 12, we retrieve the length of our string – which is just the number of characters in the string, and not including the NULL terminating character. This is done with the “length()” method of the “String” object: Name.length()
. This method will return a number, an integer, which we send right away to “Serial.print”.
In line 14, we call the method “concat()” to concatenate ” has two nephews, called Bram and Max!” to the original string “Hans”. As you can see, this works right away. But … there is an easier way to glue an extra string to your “String” object by simply using the plus symbol (+), even the compound operator “+=” works. See lines 27 and 28, where we use “+=” and even the regular “+”.
The “String” object however is even more powerful and can right away convert a number (int in this example) to a string, and replace or attach it to an existing string – see line 34 – which is something we cannot do with the previous “string” array of characters.
Now if we know that String("some text")
returns a “String” object, and we know that we can glue strings together with the plus symbol (+), and we know that “Serial.println()” take a “String” as a parameter,… then we can do some tricks to save us the hassle of writing 2 “Serial” lines (print() and println()) whenever we want to print values or variables.
1 2 3 4 5 6 7
| Serial.println(String("Number seven = ")+String(7));
int test = 10;
Serial.println(String("How many fingers do I have? ")+String(test));
Serial.println(String("Ten = ")+
String(test)); |
The first line should be dissected as:
– Create a String object holding the string “Number seven = “,
– Create a String object holding the string of the value 7,
– Glue these two object together (+),
– Pass the resulting String object to the “Serial.println()” method (function).
And the result will be exactly what we want, the Serial Monitor will print “Number seven = 7”.
In line 3 we define an integer (int) variable called “test”.
In line 4 we see an example similar to line 1, just in this case we are not using a value (7) but a variable (test), which works as well.
Now in lines 6 and 7 we see something new, and this has nothing to do with strings or objects.
Remember we said way back that we end a statement with a semicolon?
In line 6 we did not do that, so the compiler assumes that the statement isn’t done yet and continues on the next line.
The advantage is that breaking a statement like this over multiple lines actually makes your code more readable.
Now try this example. Simply copy the code in the “setup()” function. See if you can do this on your own.
Comparing Strings
Now printing and adding strings is all nice and dandy. But can we use strings to compare? Well, yes we can!
string – array of char
With the array of character “string”, we notice something weird. It fails to compare …
We would expect it to say “Hello Hans”, since “Hans” == “Hans”, right? …
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
char Name[] = "Hans";
Serial.print("Name = ");
Serial.println(Name);
if (Name=="Hans") {
Serial.println("Hello Hans");
}
else
{
Serial.println("You are not Hans");
}
}
void loop() {
// leave empty for now
} |
The reason why this fails, is because we are comparing a string with the memory location “pointer” of an array. Which will not be the same obviuosly. We actually need to use a special function for this: “strcmp()” (read that as “string compare”)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
char Name[] = "Hans";
Serial.print("Name = ");
Serial.println(Name);
if (strcmp(Name,"Hans")==0) {
Serial.println("Hello Hans");
}
else
{
Serial.println("You are not Hans");
}
}
void loop() {
// leave empty for now
} |
The function “strcmp()” returns a zero when both strings are the same.
This functions returns a number less than zero when the first string is smaller than the second string, or returns a number greater than zero when the first string is larger than the second string.
But there is a catch …
When comparing the two strings, it will actually compare the ASCII values. So when it returns a number greater than zero, it actually means that it ran into a character which has a greater ASCII value compared to the other character, in the same position in the other string, and this can be confusing, because we humans would expect “Hans” to be greater than “Hi” – but its not. This is in part also because we humans see the longer string “Hans” as the larger one of the two.
When comparing “Hans” and “Hi”, things go fine with the first character – they are the same.
The second characters, “a” (ASCII: 97) and “i”(ASCII: 105), however, will cause an unexpected (human) response.
“strcmp(“Hans”, “Hi”)” will result in a negative number … so “Hans” is smaller than “Hi”.
strcmp() is best used to see if two strings are identical (returns zero)
or not identical (returns is not zero)
Let’s look at an example that shows this unexpected behavior:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
// compare
Serial.print("strcmp(\"Hans\",\"Hans\") = ");
Serial.println(strcmp("Hans","Hans"));
Serial.print("strcmp(\"Hans\",\"Hansie\") = ");
Serial.println(strcmp("Hans","Hansie"));
Serial.print("strcmp(\"Hans\",\"Hi\") = ");
Serial.println(strcmp("Hans","Hi"));
Serial.print("strcmp(\"Hans\",\"Haa\") = ");
Serial.println(strcmp("Hans","Haa"));
}
void loop() {
// leave empty for now
} |
The output:
strcmp("Hans","Hans") = 0
strcmp("Hans","Hansie") = -1
strcmp("Hans","Hi") = -1
strcmp("Hans","Haa") = 1
So we see that “Hans” is smaller than “Hansie”, as we humans would expect.
Unexpected, but “Hans” is also smaller than “Hi”, even though we humans expect the longer string to be the larger one.
So if you’re looking for which string is longer, you’d better compare the length of both strings.
This makes me follow the simple rule that “strcmp()” is best used to see if two strings are identical.
In the example code you might have noticed an excellent example of the earlier mentioned “Escape character” in our strings,….
String – object
Comparing “String” objects result in the same kind of confusion, but instead of using the “strcmp()” function, we can use the simple comparison operators.
I therefor commonly only use to see if two Strings are identical (==) or not equal (!=) to each other.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
String Name = "Hans";
Serial.print("Name = ");
Serial.println(Name);
// compare
Serial.print("Equal: "Hans","Hans" = ");
Serial.println(Name == String("Hans"));
Serial.print("Greater than: "Hans","Hansie" = ");
Serial.println(Name > String("Hansie"));
Serial.print("Less than: "Hans","Hi" = ");
Serial.println(Name < String("Hi"));
Serial.print("Not equal: "Hans","Haa" = ");
Serial.println(Name != String("Haa"));
}
void loop() {
// leave empty for now
} |
So the simple example we started with (for array of char strings) actually does work for the object String:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| void setup() {
// set the speed for the serial monitor:
Serial.begin(9600);
String Name = "Hans";
Serial.print("Name = ");
Serial.println(Name);
if (Name == "Hans") {
Serial.println("Hello Hans");
}
else
{
Serial.println("You are not Hans");
}
}
void loop() {
// leave empty for now
} |
If you have questions, just ask them below in the comment section, and keep in mind: There are no stupid questions! We all had to start at some point!
Next chapter: Arduino Programming for Beginners – Part 8: Arrays
Comments
There are 27 comments. You can read them below.
You can post your own comments by using the form below, or reply to existing comments by using the "Reply" button.
I m totaly lost. In data type chapter string said as array of chatacters and char is only 1 character.
So why we do this ; char Name[5] = “Hans”;
Its chat data type. Shlndt it be string Name [5] = “Hans”; ??
Stan
Hi Stan,
the use of strings and arrays can indeed be confusing the first few times, well, in all honesty, it can even be confusing after many years haha …
A char is indeed one single character and a valid datatype. A string (the English word) indicates a bunch of characters, but is not a valid datatype.
So …
This code basically says:
Create some space in memory that can hold 5 char’s, make “Name” point to the first char, and fill the space with the chars “H”, “a”, “n” and “s”. The end of the text (so after the “s”) in the allocated space is marked with a null character (which is also a “char”, we just can’t see it), so the 4 characters plus the null character fill up the allocated space of 5 chars.
So that would be an array of 5 char’s.
Now the data type “string” (small “s”) does not exist, and is not defined. Consider this like an alternative phrase or alias for saying “array of char”.
The object String (capital “S”) however is a valid datatype and offers tools to work with the chars.
For example, with a the 5 char array we just had, it would take a bit to put a 6 char text in. First we’d need to make the array larger, and then we can put the char’s in it. The object “String” however handles this automatically. Very convenient of course, but the downside is that it uses more memory that the array of char because it comes with a bunch of functions that do not come with that array of char.
Also note that the array of char is the classic and more commonly used way to store text.
I hope that explains it a little bit
hans
So ita good to use char datatype not string datatype(?)
Stan
But in here u say ;
Also note that the array of char (string) is the classic and more commonly used way to store text. So which one to use for a text? char or string? Becauae in last sentence its confused again
Stan
You can either use “array of char” or “String”. For beginners “String” (with the capital “S”) would be the easiest.
Once you want to save memory and optimize your code, then the “array of char” can be a better choice.
Both can be used for text.
Both have their purpose:
array of char: Efficient, less memory use, but sometimes harder to work with,
String (capital S!): Very easy to use, consumes more memory, but saves work when doing a lot with the text.
Sorry – didn’t mean to confuse you
hans
Well okay i think we have a misspoint. I was talkimg about char and string. And you gave an example for char but you put not only 1 charactee into. You put 5 characters including Null. So its a 4 character Text (Hans). And i said its a Text so it must be a string datatype or function but u wrote code as ;char Name[5] = “Hans.So that blow up my mind a lil. Hehe.
Stan
Hahah, yes that’s why this topic can be a little confusing.
They are both text and string (in human language),…
hans
Yes u r right Hans. Its better i repeat last 3 chapters several hundred times hehe
Stan
Haha, you’re most welcome to do so!! Good for my advertising revenue hahahahahah
hans
Advertising revenue??? Hahahahhahahhaha oh my.. i need some hours to stop to laugh !! 😂😂You are Golden my friend.
Stan
Haha, well, it barely covers my hosting expenses hahah … so one or more click will probably not make a difference
hans
Hans , Is it possible to make a donate to your person ?
Stan
Hi Stan,
you can always donate … and it is very much appreciated, but not required of course.
Option 1 is shopping at Amazon, it won’t cost you anything, but if you’re not in the US then that might not be so beneficial (shipping costs etc). Alternatively you can donate through PayPal to hans @ luijten . net.
hans
Um okay. Well i surely tried amazon but it dont work cus i m outta Usa. And in here paypal is cancelled. Hehe! Hmm thry say paypal will come again soon. Umm Hans is there anyway to reach u outta this community messaging place ? I would like to ask you something about the source book that i mentioned before. Its Not about codes and chapters. No worry
Stan
Hi Stan,
well, if you don’t mind others reading our conversation, I’d recommend our forum: Arduino Forum – you’ll have to register but that’s free (if you haven’t already). Alternatively (and you need to be registered for that as well) you can go to the “User” menu and use “messages” there.
Just in case that doesn’t work for you either; I’ll send you an email
hans
I have registered and gone to messages but it dont show up ur name when i fill into recipient section
stann
I’ve sent you a message and an email … not sure why the message didn’t show my name though …
hans
Hi,
If I do Serial.println(“this is a test”), it means that I make use of String (library), right?
So, in order to avoid this, it is better to declare a char array, initialize it with the value “this is a test” and then print it? Even if I will not use this variable again in my sketch?
Thank you!
vali
Hi Vali,
I have to admit that I do not have a solid answer on this question.
Easiest way to test this, is by compiling it both ways and see what the summary in the Arduino IDE says (memory used etc).
If using an array significantly impacts the size (in a positive way) then I’d say: you’re right.
But I honestly do not know if the text “this is a test” will be passed as a String or as a char-array.
I suspect though, that it will be passed as a char array and not a String object.
Hans
Very, very useful! Thank you very much! Many things are now really more clear to me.
…just one question: how can be replaced a chunk of chars inside an array of chars starting from a known starting point inside the string?
e.g. char Name[] = “You are not Hans nor Max”; —>> need to change to “You are not Bram nor Max” (same string length, of course!).
Hoping in another useful reply…
Lippoli
Hi Lippoli!
Thank you for the kind words, and great to hear this has been useful to you
As for your question;
There is no cookie cut solution for this unfortunately (as far as I know), and (I assume) that this is the reason most will work with the String object (which consumes more memory, but is much easier to work with in some scenarios).
Option 1:
If you do want to work with an array of chars anyway, then this would be the generic approach:
Basically we split the original array in 2 pieces (assuming the word you would like to replace exists only once in the array):
Part 1 – Everything before the word we want to replace.
Part 2 – Everything after the word we want replaced.
Next we merge these 2 parts and the new word, into a new array: Part 1 + new word + Part 2.
Not complex, but not convenient either.
Option 2:
However, since you mentioned the same string length (replace “Hans” with “Bram”), then you could use the characters of the new word to overwrite the existing name. Not a very safe approach, since the new word may be longer or shorter than the original.
If this is in a fixed location then you could hard code it, something like this (not recommended, unless you’re 100% sure about the positions and lengths):
Option 3:
As an alternative you could look into the use of sprintf() which allows you to do something like this:
Which would result in “You are not Hans nor Max”.
Where as
Would result in “You are not Bram nor Max”.
I rarely use this, so my code may not be entirely correct, but it could get you started: More details on sprintf.
Personally I’d stick to the String object though, unless your Arduino is running low on memory.
Hans
Besides my many thanks of my previous msg, I want to to thank you for your very fast reply, as I am working on this right now.
I think I will stick with option 2 as I need to work with arrays. Positions and lengths are fixed (readings from sensors), but isn’t possible to replace more than one char at a time instead of one by one?
Lippoli
You’re most welcome, glad I could help
I always try to respond promptly, but sometimes the day just doesn’t go as planned and there may be a little delay
You could indeed do multiple chars at once, however now you’ll have to go into the realm of using pointers.
Unfortunately, pointers can be a little confusing, especially when beginning with this, causing potentially unexpected results.
Basically what one would do is copy x number of chars from memory, straight to the memory location of the chars you want to replace.
Personally I’d stay away from this approach until you’re very familiar with using memory, allocating memory, copying memory blocks and working with pointers.
Using sprintf() instead will be a much easier one line approach, and still use char arrays. I’d personally would use this approach.
You could even predefine a your lines, and populate the array in one single line, each time it is needed, for example:
This would populate the array “Name” with the text “Temperature: %s — Humidity: %s“,
where the first %s is being replaced with the value of varTemperatiure,
and the second %s is being replaced with the value of varHumidity.
Note: %s indicates a string, but your sensors most likely use numbers (integer or float). In that case replace %s with %d (integer) or %f (float).
This even allows for some really nice formatting, for example if you want a number to always take up a certain number of characters.
A few examples:
There are more variations, just keep in mind that the sprintf() implementation on Arduino is a little limited, and some “standard” format specifiers (like scientific notation and long long int) may not work.
So this could look something like this (now using numbers – for example an integer and a float):
Here you can find some more details as well, and the option to do a live demo with regular C code (modify code, click “Execute” in the upper left corner) the code as you see fit. Note that the live demo relies on regular GCC C and this is not exactly the same as Arduino C. Compare my example with the code you see in the Live Demo to get an idea.
Hope this helps.
Hans
Thank you Hans !!!!
I solved my problem carefully reading your answer and your examples. I really missed the detail on the format specifiers to limit the number of characters (I am replacing some text inside a 20×4 lcd display lines). Now everything runs nicely! Also yr suggestions on using the online C compiler (I didn’t know it) were really useful to speed test some routines instead of modifying and re-compile all my long code each time!
Cheers…
lippoli
Hi Lippoli!
Thanks, I’m happy to hear this was helpful for you, and thanks for the feedback.
Have fun programming
Hans
Can we declare array of String ?
If YES then how to declare and assign values to array of String ?
and how to print it ?
Rahul
Hi Rahul,
Yes you can, see also Chapter 8:
Assigning values:
Reading:
Hans