Main menu

Tag Archives: newline

I’v been tinkering in C++ and decided to start making an old fashioned “text adventure” game as a nice little project to grasp the language.

As I started writing the game it quickly became clear that formatting all the strings manually with “new line” characters (\n) to get the text to not breakup mid-sentence in the console was going to be hassle. I fancied a challenge and rather than grabbing some pre-written code from the web (how not to learn anything) I decided to work on an algorithm and make my own function that can deal with any string size and wrap the text neatly to the console.

I thought I’d make this little tutorial for anyone who wants to use it in their program but also wants to understand how the code works.

Here’s the function:

Note: Functionality has been gradually added, the updates further down detail the changes. I’ve included a Visual Studio code solution zip with the latest code at the bottom of this page.

Although the function is written here in C++, the algorithm can easily be applied to C# and other languages with just a few syntax changes. I was in two minds whether to go a route of splitting a string at the end of the line and then adding a newline character on the end, then “glueing” the strings together and repeating for each line, or whether to do it the way I did it which was by finding the last character on each line and then looping back through the line until it gets to a space and simply inserting “whitespace” on the end.

I’ll go through exactly what the function is doing:

for (unsigned int i = 1; i <= s.length() ; i++)

Here we are preparing to loop through each character in the string to find where we want the line breaks.

if ((i % BUFFER_SIZE) == 0)

This bit of modulo arithmetic checks the current loop iteration value to see if it is a multiple of the console window buffer width (80 default) and thus the character in the strings length that would be at the end of a line. By checking if it’s a multiple it allows us to apply this function to any size string. You’ll need to define BUFFER_SIZE in your program or simply replace it with the number value you want i.e 80.

BUFFER_SIZE could easily be changed via a variable and set to whatever buffer width your console window is using (see bottom of this article on how to get the current console buffer width value).

int spaceCount = 0;

I initialise this variable for later use to keep track of the number of characters the loop has backtracked through in the string to find a space. (We’ll need to insert this number of whitespace into the string).

if (s[(i-1)] != ' ')

Here we are establishing whether the character at the end of the line is already a space. If it is, we don’t need to do anything and it’ll skip to the next loop iteration. Note “(i-1)” here, we do this because “i” is looking at the string based on it’s length with the lowest possible length obviously being 1. However when it comes to looking at the character array of the string “s”, arrays in C languages start at 0, thus we need to subtract 1 from the total length of the string to balance it. I could have adjusted the “for” loop to start at 0 instead and end at (s.length()-1) however this would have meant adjusting the modulo statement and personally it made more sense to me this way.

for (int j = (i-1); j > -1 ; j--)

Once we have the character at the end of a line in “i” and know it’s not already a space, we loop backwards from this position in the string until we find a space i.e the end of a word.

As stated above, we check if each character we loop through is a space (‘ ‘). If it is then we have found the end of the last whole word on the line that fits and thus where we need to insert whitespace. We know how many spaces to insert because each time a character is checked and isn’t a space, we increment the “spaceCount” variable so we know how many spaces to insert to fill the line to the end.

std::cout << s << std::endl;

We then output the newly word wrapped string to the console!

It’s great for text adventures or any program that outputs large strings since you can just call this function with any size string (within memory limits!) and it’ll do the rest. I tried to keep the solution as neat and minimal as I could.

Update (14/08/2012): Retrieving the console buffer width value

I thought I’d add in addition a way to get the console buffer width from the console each time text is output. This allows users to change the console window size and the text will wrap to it on the next output.

As you see here I have added at the top a function call “GetBufferWidth()”. This will return an integer with a value of the currently set console buffer width and store it in the bufferWidth variable that the OutputText function uses.

It’s a relatively simple function that makes use of the CONSOLE_SCREEN_BUFFER_INFO class. You will need the ensure you have “#include” for windows.h specifically for the “wincon.h” child library containing the console services.

“dwsize.X” gives us the max number of available character “columns” in the window (by default 80), Note* “dwsize.Y” isn’t needed here but would give us the max number of available character lines for the window so by default it would return a value of 300 since that’s the default limit for console output (it would not give us the value of lines within the visible portion of the window).

I recently had a comment mentioning the problem with using this algorithm with paragraphed text. I had already come across this issue and had added some additional code to allow it to work with strings with “\n” (newline) characters in. I’ve been meaning to do a blog post update with it for quite a while. I appreciate comments from people because it means people are using the code I’ve put on here and gives me an incentive to update this post so thanks.

Below is the full modified code. As can be seen from line 11, I have added a new block of code to check for any “\n” characters (you could extract this into a separate function for neatness). If a “\n” is found it inserts spaces into the string before the “\n” character filling to the end of the line and jumps the loop iteration to the first character on the next line. I’ve also added a new char declaration on line 7.

By adding whitespace before the “\n” character and thus moving it right to the end of the line, we are effectively countering all that extra space that the console window needs to generate when it hits a newline character. This would completely mess up our algorithms positioning in the console window if it wasn’t at the end of the line.

Here if the current character in the string array is a “\n” then it enters the new block. It then declares a new temporary variable for use later that contains the characters position within the line (defined by the width of your console window).

spaceCount = bufferWidth - charNumOnLine;

Next we calculate the number of spaces we will need to insert into the string from the “\n” characters position to move it to the end of the line. We do this by finding the difference between the position of the current character in the line and the last position on the line.

s.insert((i-1), (spaceCount), ' ');

We then insert just before the “\n” character the calculated number of spaces.

i+=(spaceCount);
continue;
}

Then we increment the current loop iteration by the number of spaces we just added which should set the loop index to the first character on the next line and “continue;” which will take us straight to execute the next loop iteration, repeating the process and checking every subsequent character for any more line breaks. If it doesn’t find one, it carries on as normal.

Here’s a screenshot of it in action with double “/n/n” line breaks inserted randomly into the string: