programs is getting input from users and providing
feedback to them. In typical simple embedded systems,
this often involves buttons and LEDs. More complex
systems may have keypads and LCDs. For our purposes —
which are primarily educational — we assume that since
the user will have a PC to use for development and
uploading code, that we can also use that PC for
communicating with the embedded system user via a
terminal program, allowing us to use the PC keyboard and
screen for input and output. This gives us the luxury
(burden?) of using actual human readable sentences.
For example, we might want to have a standard sentence
with a variable in it such as “The temperature is X degrees
Fahrenheit” where X is a variable for the temperature. We want
to have a way of reading a temperature with our microcontroller,
then putting that value in X before sending it back to the user
to read on a PC terminal: “The temperature is 70 degrees
Fahrenheit.” As a preview, we would do this using the stdio.h
library function: printf(“The temperature is %d degrees
Fahrenheit.”,temperature_variable) — where the ‘%d’ tells the
printf() function to write the value from temperature_variable.
Before we implement our version of the stdio.h
function printf(), let’s take a look at stdlib.h to get an idea
of what these libraries really are and how they are written.
You can probably visualize lots of situations like the
one above where you might want to use stock constant
text phrases mixed with variable data. The stdlib.h has
some functions that will help. Let’s look at a few and see
how they are implemented.
A Few Practical Examples:
strlen, atoi, itoa, and reverse
Since folks who either didn’t like to type or more likely
were short on memory wrote these functions, the names are
a bit more cryptic that those we use for our avrtoolbox
functions — strlen is used to get the ‘string length,’ atoi is
used to convert ‘ASCII to integer,’ itoa is used to convert
‘integer to ASCII,’ and reverse (which has a readable
name) is used to reverse the order of characters in a
string, which might sound like an odd thing to do.
However, as we’ll see in a moment, it is quite useful.
Let’s write them ourselves (with some help from K&R):
int strLen(char s)
i = 0;
while(s[i] != ‘\0’) ++i;
In strlen, we accept a pointer to a string which is an
array of characters with a terminal character ‘\0’. The
while statement evaluates each character, incrementing
the index, i, until the terminal character is found. The
return value is the number of characters, not including the
terminal character. Well, that wasn’t rocket science, was it?
It is a simple solution to a simple problem, but some of
these functions are very clever, such as atoi.
//NOTE: “borrowed” from K&R p. 43 atoi function
int atoi(char s)
int i, n;
n = 0;
for(i = 0; s[i] >= ‘0’ && s[i] <= ‘9’;
n = 10 n + (s[i] - ‘0’);
The atoi — ASCII to integer — function converts a
string of ASCII characters representing the integers 0 through
9 into an integer number equivalent to the string. If you
didn’t figure this one out yourself, then use your paper and
pencil computer to run the function with char s equaling
“1, 2, 3, 4,\0” to see how it works. Note the condition in the
for statement will cause the loop to bail if one of the
characters is not equal to or between the characters 0 and
9. This gets us out of the loop, but not out of trouble. In a
robust function, we would have some kind of error reporting
mechanism so that code calling atoi could know that it sent
a bad string, and so the calling function could build in some
way to recover. We’ll get into all that some other time and
be careful not to make mistakes now. (Famous last words.)
The conversion algorithm relies on the convenient fact
that the ASCII characters for integers are represented by a
sequence of numbers. ‘0’ is 0x30 in ASCII; ‘1’ is 0x31; and
so on. So, if s[i] = ‘1’ (the character), we get (s[i] – ‘0’) = 1
(the integer). That is, we subtract the character 0, which has
a value of 0x30 from the character 1 which has a value of
0x31, leaving us with the number 1. Voilà: ASCII to integer.
We start with n = 0, so the first time through the 10*n = 0
and the character are converted to the 1’s position in the
integer. For each subsequent pass, the n has a value so we
multiply it by 10, providing the 10’s, 100’s, and so forth.
You were asked to think about this algorithm before
looking at the atoi function. Don’t be concerned if yours
wasn’t as simple and elegant as this one. Mine wasn’t. It
takes a while to start thinking like a computer. (Then your
brain turns to silicon and people avoid you.) Just be glad
other clever folks have thought about this and are willing
to give you a good solution.
September 2011 59