Home / Tutorials / Tutorial: Output formatting in ROBOTC

Tutorial: Output formatting in ROBOTC

Aligning your fruit ‘n veg

If you’ve ever had to output anything on the screen in ROBOTC, you’ve probably used nxtDisplayTextLine() or one of its many siblings.  Your code may, or may not have looked something like this:

task main() 
{ 
  int num_apples   = 10;  // how do you like them apples? 
  int num_pears    = 8; 
  int num_cherries = 116; 

  nxtDisplayCenteredTextLine(0, "ROBOTC"); 
  nxtDisplayCenteredTextLine(1, "Fruit Stand");   
  nxtDisplayTextLine(3, "%d apples", num_apples); 
  nxtDisplayTextLine(4, "%d pears", num_pears); 
  nxtDisplayTextLine(5, "%d cherries", num_cherries); 
  wait1Msec(5000); 
}

The screen will look something like the one below, which is fine if you don’t care about layout.

image

The items are not arranged very neatly and most of the time that doesn’t really matter that much.  However, consider the scenario when the number of items change rapidly, what do you think will happen to the words “apples”, “pears” and “cherries”?  try the program below and you’ll see what I mean:

task main() 
{ 
  int num_apples   = 0;  // how do you like them apples? 
  int num_pears    = 0; 
  int num_cherries = 0; 

  nxtDisplayCenteredTextLine(0, "ROBOTC"); 
  nxtDisplayCenteredTextLine(1, "Fruit Stand"); 

  while (true) 
  { 
    num_apples   = abs(rand()) % 200; 
    num_pears    = abs(rand()) % 200; 
    num_cherries = abs(rand()) % 200; 

    nxtDisplayTextLine(3, "%d apples", num_apples); 
    nxtDisplayTextLine(4, "%d pears", num_pears); 
    nxtDisplayTextLine(5, "%d cherries", num_cherries); 
    wait1Msec(200); 
  } 
}

Doesn’t it get super annoying to see those lines jumping back and forth, depending on whether it’s a 1, 2 or 3-digit number?  You work around it by checking how many digits the number is long and printing some spaces in front of the number but that would be cumbersome and would only make your code look cluttered.  What if there was a way to get the firmware to take care of that stuff for you?

Take a look at the next program and see if you can spot the subtle difference.  When you’ve figured it out, run it and check out the results.

task main() 
{ 
  int num_apples   = 0;  // how do you like them apples? 
  int num_pears    = 0; 
  int num_cherries = 0; 

  nxtDisplayCenteredTextLine(0, "ROBOTC"); 
  nxtDisplayCenteredTextLine(1, "Fruit Stand"); 

  while (true) 
  { 
    num_apples   = abs(rand()) % 200; 
    num_pears    = abs(rand()) % 200; 
    num_cherries = abs(rand()) % 200; 

    nxtDisplayTextLine(3, "%3d apples", num_apples); 
    nxtDisplayTextLine(4, "%3d pears", num_pears); 
    nxtDisplayTextLine(5, "%3d cherries", num_cherries); 
    wait1Msec(200); 
  } 
}

image

Doesn’t that look much better?  The cool thing is, there are lots of output modifiers, the bad thing is, there are lots of output modifiers!  Sometimes it can get a little confusing, so I’ll stick with the most commonly used ones (by me, anyway).

Supported modifiers

Here’s a complete list of all of the ones supported by ROBOTC.  I’ve marked the ones I use with an asterisk (*)

  • %c – a single character *
  • %s – a string or char array *
  • %f – a signed or unsigned float *
  • %d – a signed or unsigned long or int *
  • %i – a signed or unsigned long or int
  • %o – unsigned octal int or long
  • %u – unsigned decimal int or long
  • %x – unsigned hex int or long (lower case, e.g. 67ad)
  • %X – unsigned hex int or long (upper case, e.g. 67AD) *
  • %p – address of a pointer *
  • %% – the actual percentage sign *

The following modifiers are not currently working (as of 30 march 2013) but are due to be fixed soon

  • %e – Signed float with exponent, e.g. 1.697597e-5 (lower case)
  • %E – Signed float with exponent, e.g. 1.697597E-5 (upper case)
  • %g – Signed float, but will print as either standard %f or %e, depending on which is shorter
  • %G – Signed float, but will print as either standard %f or %E, depending on which is shorter

Leading zeroes

SNT5372-09C SPDO 140mph-220kphSo what else can you with these to change the way your printed variables look?

Say you were making a tacho counter , like in your car (not the Mexican restaurant), you would want the number of digits displayed to be the same.  In car they look like this.  There are 5 digits with leading zeroes.  Using the output modifiers you can achieve the same.

The following piece of code will simply count upwards from 0 and display a 5 digit number with leading zeroes:

task main() 
{ 
  int counter = 0; 
  while (true) 
  { 
    nxtDisplayCenteredBigTextLine(4, "%05d", counter++); 
    wait1Msec(100); 
  } 
}

It should something like this after a little while:

image

The leading zeroes thing will also work with some of the other types.  Play with it and see which ones work and which ones don’t.

Floats

Now we’ll take a look at floats.  You can do some pretty cool things with them.  Consider the following:

float pie = 3.1415926535

When we print that out, we’re actually only interested in displaying the first 2 numbers after the decimal point.  So how do we do that?  Take a look:

task main() 
{ 
  float pie = 3.1415926535; 
  nxtDisplayCenteredBigTextLine(4, "%.2f", pie); 
  wait1Msec(10000); 
}

Running this will display the following:

image

 

The actual value of the float has not been changed, only the number of digits that are being displayed.

0xhexadecimals

I am a big fan of the %X modifier to display data but to make it obvious that it’s a hex number I like to add the 0x to it and make sure they have leading zeroes, so all line up nicely on the screen:

task main() 
{ 
  long pie = 3141593; 
  long foo = 871839011; 
  long meh = 781; 

  nxtDisplayCenteredTextLine(2, "0x%08X", pie); 
  nxtDisplayCenteredTextLine(4, "0x%08X", foo); 
  nxtDisplayCenteredTextLine(6, "0x%08X", meh); 
  wait1Msec(10000); 
}
image image
Neatly aligned with leading zeroes.  All is well with the world. Freakishly messy, tearing apart the very fabric of time and space itself.

So not only are output modifiers great for making sure your output is tidy, it will also ensure the continuing existence of the universe.  Keep that in mind next time you’re going to use them.  The people of Earth depend on you.

Supported functions

There are many functions that support the output modifiers:

  • nxtDisplay*()
  • writeDebugwriteDebugStream*()
  • sprintf()
  • snprintf()
  • StringFormat()

There’s also a function called sscanf() but that’s a story for another time.

 

About Xander

Xander Soldaat is a Software Engineer and former Infrastructure Architect. He loves building and programming robots. He recently had the opportunity to turn his robotics hobby into his profession and has started working for Robomatter, the makers of ROBOTC and Robot Virtual Words.