Breaking text into lines without splitting words

Hi everybody,

because of my limited coding experience I hope to get some feedback and help.

For my project I need to process text messages with an maximum of 200 characters. To display the text on dot matrix displays, I need to break the message into lines (in my example 5 lines, max. 20 character per line) without splitting the words. I tried something with strtok() which works so far. But I'm sure that my script is not very eloquent and consumes a lot of sRAM. And there is still a problem to solve: there should be an exception that very long words have to get split anyway.

Please excuse my "dirty code", I started with Arduino and scripting just a couple of months ago...

Here is what I did, working so far:

String lineOne;
String lineTwo;
String lineThree;
String lineFour;
String lineFive;

char str[] ="Hello World! Here is some text. I need them to split into multiple lines without breaking the words.";
char * pch;


void setup() {
  
  Serial.begin(9600);
  Serial.println("Start splitting");
  
  pch = strtok (str," ");

  
       // First Line
        while (pch != NULL)
         {
           String stringPch = pch;          
           if (lineOne.length() + stringPch.length() < 21)
           {
            lineOne = lineOne + pch + " ";
            pch = strtok (NULL, " ");
           }
           else
            {
             break;
            }
         }
   
   
       // Second Line
        while (pch != NULL)
         {
           String stringPch = pch;
           if (lineTwo.length() + stringPch.length() < 21)
           {
            lineTwo = lineTwo + pch + " ";
            pch = strtok (NULL, " ");
           }
           else
            {
             break;
            }
         }
 
 
       // Third Line
        while (pch != NULL)
         {
           String stringPch = pch;
           if (lineThree.length() + stringPch.length() < 21)
           {
            lineThree = lineThree + pch + " ";
            pch = strtok (NULL, " ");
           }
           else
            {
             break;
            }
         }
 
       
        // Fourth Line
         while (pch != NULL)
         {
           String stringPch = pch;
           if (lineFour.length() + stringPch.length() < 21)
           {
            lineFour = lineFour + pch + " ";
            pch = strtok (NULL, " ");
           }
           else
            {
             break;
            }
         }
         
         
          // Fith Line
         while (pch != NULL)
         {
           String stringPch = pch;
           if (lineFive.length() + stringPch.length() < 21)
           {
            lineFive = lineFive + pch + " ";
            pch = strtok (NULL, " ");
           }
           else
            {
             break;
            }
         }
 

 Serial.println(lineOne);
 Serial.println(lineTwo);  
 Serial.println(lineThree); 
 Serial.println(lineFour);  
 Serial.println(lineFive);  

}


void loop() {
  
}

I advise you to not use String, they can be memory hogs.

Please note that in versions of the IDE up to and including 1.0.3, the String library has bugs as discussed here and here.

In particular, the dynamic memory allocation used by the String class may fail and cause random crashes.

I recommend reworking your code to manage without String. Use C-style strings instead (strcpy, strcat, strcmp, etc.), as described here for example.

Alternatively, install the fix described here: Fixing String Crashes

Preferably upgrade your IDE to version 1.0.4 or above at: http://arduino.cc/en/Main/Software


If you case you could do a reverse search for a space, from position 20. If found, that is where you break the line. If not, use the whole 20 characters. Start the new line at where you broke the old one. Repeat.

Here is some example code to get you started. You should start writing functions and not just copy and paste the same code 5 times because you want to do 5 lines. What if you wanted to do 100 lines? Wouldn't that get tedious?

char str[] ="Hello World! Here is some text. I need them to split into multiple lines without breaking the words.";
const int wantedLength = 20;

const char * split (const char * s, const int length)
  {
  // if it will fit return whole thing
  if (strlen (s) <= length)
    return s + strlen (s);

  // searching backwards, find the last space
  for (const char * space = &s [length]; space != s; space--)
    if (*space == ' ')
      return space;
    
  // not found? return a whole line
  return &s [length];        
  } // end of split
  
  
void setup ()
  {
  Serial.begin (115200);
  Serial.println ();

  const char * p = str;
  
  // keep going until we run out of text
  while (*p)
    {
    // find the position of the space
    const char * endOfLine = split (p, wantedLength);  
    
    // display up to that
    while (p != endOfLine)
      Serial.print (*p++);
      
    // finish that line
    Serial.println ();
    
    // if we hit a space, move on past it
    if (*p == ' ')
      p++;
    }
  }  // end of setup
  
void loop () { }

Note I use 115200 baud rate because it is faster.

Most of the work is done in the split function, which looks for 3 conditions:

  • The line is already short enough to fit, so no splitting is needed.
  • If not, search backwards from position 20 (or whatever number you choose) looking for a space, if found use that as the split point.
  • If no space found, use 20 characters.

Then the printing loop prints the characters, moves past the space (if any), and does it again.

Output:

Hello World! Here is
some text. I need
them to split into
multiple lines
without breaking the
words.

Great! Thank you very much. I definitely can work with that especially when it comes to larger messages.

With your comments I can understand every single step. Thank you for helping me learn that easy.

1 Like

Hello multigrade,

is your display project open source and hosted somewhere? I currently have a similar issue where I have to break a large string into multiple lines for an epaer display.

multigrade last posted in 2016 so the chances of an answer are small.

I suggest that you start your own topic on the subject