0

I'm trying to create a function that will take a String as an input, and at every 20 characters, it will instert "\n" so that the string doesn't go off the side of my screen (I'm using an oled with the SSD1306Ascii library).

This is my code so far, but when I run it nothing appears on the screen (I have another part of the code which passes the string to the funtion):

String message = "";
String newMessage = "";

void printMessage(String message) { oled.clear(); if(message.length() > 20) { current = 20; while(current < message.length()) { newMessage = message.substring(current-20, current) + "\n"; newMessage = newMessage + message.substring(current+1); current+20; } oled.println(newMessage); } else { oled.println(message); } }

2 Answers2

0

I think that your implementation is fundamentally flawed. In the while loop, when you assign newMessage to a message.substring you are discarding all the work done in the previous iterations.

Also I would recommend keeping the splitting and the printing separated. The operator += also is very handy here. This code (untested) should implement your original idea in a correct way

String splitMessage( const String & message, const unsigned limit) {
  String newMessage = "";
  unsigned i = 0;
  while ( i+limit < message.length() ) {
    newMessage += message.substring(i, i+limit);
    newMessage += '\n';
    i += limit;
  }
  newMessage += message.substring(i);
  return newMessage;
}

Then you can do:

whatever.println(splitMessage(myMessage, 20));

Note that I retained the use of String from your original implementation, although, being in an embedded environment, it is likely better to avoid it in favor of stack-allocated c-strings.

I have found a substantial amount of pretty enlightening information in the various answers to this question: Is using malloc() and free() a really bad idea on Arduino?

DarioP
  • 142
  • 7
0

One issue with both your failed implementation and the previous answer is that they do loads of dynamic allocations and copies. Every time you use the String’s + or += operators you are allocating heap memory for a brand new String, copying the original character data into the newly allocated space, and eventually destroying the original Strings when you don’t need them anymore.

The simplest way to avoid all these copies and allocations is to not build the String you want. Instead, just write() the pieces one after the other on the display. Here is a zero-copy, zero-dynamic allocation solution:

void printMessage(const char *message) {
    size_t length = strlen(message);
    while (length > 20) {
        oled.write(message, 20);
        oled.write('\n');
        message += 20;  // point to the rest of the message
        length  -= 20;  // remaining length
    }
    oled.write(message);
}

Note that the method Print::write(const char *, size_t) is used here to print a slice of the message without ever building it as a string in memory.

On these memory-constrained devices it is always preferable to avoid heap allocation, and thus String objects. However, if for whatever reason you really need to print a String object, then you can use the following overload to print it’s internal buffer without making any extra copy:

void printMessage(const String &message) {
    printMessage(message.c_str());
}
Edgar Bonet
  • 44,999
  • 4
  • 42
  • 81