Although I have long experience of other languages, I've not used C until playing around with microcontrollers using the Arduino IDE. I'm a bit uncomfortable with my use of pointers in conjunction with C strings.
Since this is a microcontroller project, I want to avoid the String class and try to write code that will be reasonably efficient as well as readable by C programmers (i.e. idiomatic or following best practise)
I read data from a serial port, including a number in ASCII character form. I will display that number on a three-digit seven-segment display, so I want to right-justify numbers less than three digits and if the number is larger than 999 I just want to display the last three digits. I can indicate errors like out-of range numbers separately.
I have the following working code
void setup() {
Serial.begin(115200);
Serial.println(last3Digits("12345")); // 345
Serial.println(last3Digits("789")); // 789
Serial.println(last3Digits("60")); // _60
Serial.println(last3Digits("5")); // __5
Serial.println(last3Digits("")); // __0
}
char * last3Digits(char * aString) {
char * retVal = "abc";
byte len = strlen(aString);
switch (len) {
case 0:
strncpy(retVal, "__0", 3);
break;
case 1:
retVal[0] = '_';
retVal[1] = '_';
retVal[2] = aString[0];
break;
case 2:
retVal[0] = '_';
retVal[1] = aString[0];
retVal[2] = aString[1];
break;
default: // len >= 3
strncpy(retVal, aString+len-3, 3); // copy only last 3 digits
}
retVal[3] = 0;
return retVal;
}
// ---------------------------------------------------
byte counter = 0;
void loop() {
Serial.print(counter);
Serial.print(" ");
delay(1000);
if (++counter > 9) { counter = 0; }
}
The above can be run in an online emulator at https://wokwi.com/arduino/projects/315730913481720385
My function last3Digits()
seems clumsy to me. I imagine it can be made smaller without losing readability, and I imagine I must have made some other rookie mistakes.
- overwriting a string constant (what is the better way to allocate space?)
- redundant setting of string terminator (felt safer)
- ?