Geeks With Blogs

News

Google My Blog

Catch me at: The List!


My InstallScript Utility Belt My Amazon Wishlist
My Standard Disclaimer


Archives
Chris G. Williams Beware: I mix tech and personal interests here.

Recently I found myself working on some player messages (for HA!) and was less than thrilled with how words were getting chopped in half on the linebreak. I came up with this fairly tidy vb.net solution:

1. Build the sentence(s) as normal, with proper spacing and punctuation, and store them all in one long string variable. 

Dim strMessage As String
strMessage = "The smelly kobold swings his broken dagger at you. You see a door opening. You cleave the smelly kobold in two."


2. Dim a string array and split your message variable on the space character. 

Dim strMessageChop() As String
strMessageChop = Split(strMessage, " ")


3. Now we'll re-use the original message variable to contain our modified string. Check the length of the recreated message after each word and insert a linebreak before the word that would cause us to go over 80 characters.

strMessage = ""
Dim intCtr, intLine As Integer

For intCtr = 0 To strMessageChop.Length - 1
 
strMessage &= strMessageChop(intCtr) & " "

  ' add 1 to account for the space between each word
 
intLine += (strMessageChop(intCtr).Length + 1)

  If intCtr < strMessageChop.Length - 1 Then
   
If intLine + strMessageChop(intCtr + 1).Length >= 79 Then
     
strMessage &= vbCrLf
     
intLine = 0
   
End If
 
End If
Next


4. Then display your newly word-wrapped string however you like (i.e. Console.Writeline or whatever). You can also adjust the point where you word wrap by changing the 79 to something smaller.

 

Posted on Friday, January 21, 2005 8:59 AM Game Development , General Interest | Back to top


Comments on this post: word wrap in Console app

# re: word wrap in Console app
Requesting Gravatar...
How about this?

Dim strMessage As String
Dim iPos As Integer
strMessage = "The smelly kobold swings his broken dagger at you. You see a door opening. You cleave the smelly kobold in two."
iPos = strMessage.LastIndexOf(" ", 80)
strMessage = strMessage.Insert(iPos + 1, ControlChars.NewLine)
Console.WriteLine(strMessage)
Left by Sandeep on Jan 21, 2005 11:56 AM

# re: word wrap in Console app
Requesting Gravatar...
Hey that works great too, and is much smaller than my original code. Another guy sent me this:

string strMessage = "The smelly kobold swings his broken dagger at you. You see a door opening. You cleave the smelly kobold in two.";
int lastFound = 0;
int msgLength = strMessage.Length;
int lineLength = 80;

for( int ndx = 0; ndx < msgLength; ) {
ndx = strMessage.IndexOf(' ', ndx + 1);

if( ndx != -1 ) {
if( ( ndx % lineLength ) < ( lastFound % lineLength ) )
{
strMessage = strMessage.Remove(lastFound, 1);
strMessage = strMessage.Insert(lastFound, "\n");
}

lastFound = ndx;
}
else {
ndx = msgLength;
}
}

Console.WriteLine(strMessage);


unfortunately I'm semi-colon impaired so I ported it to VB.net real quick... and came up with this:

Dim strMessage As String
strMessage = "The smelly kobold swings his broken dagger at you. You see a door opening. You cleave the smelly kobold in two."

Dim lastFound As Integer = 0
Dim msgLength As Integer = strMessage.Length
Dim lineLength As Integer = 80

Dim ndx As Integer

For ndx = 0 To msgLength - 1

ndx = strMessage.IndexOf(" ", ndx + 1)

If ndx <> -1 Then
If (ndx Mod lineLength) < (lastFound Mod lineLength) Then
strMessage = strMessage.Remove(lastFound, 1)
strMessage = strMessage.Insert(lastFound, vbCrLf)
End If
lastFound = ndx
Else
ndx = msgLength
End If
Next

Console.WriteLine(strMessage)


which also works quite well... just goes to show there are MANY different ways to do things in .NET, and in this case mine was the least efficient. (Although probably easiest to read...) :)
Left by Chris on Jan 21, 2005 12:46 PM

# re: word wrap in Console app
Requesting Gravatar...
I think the second (super small) is really the most efficient. The strMessage.Remove and strMessage.Insert are really bad especially with large strings as new memory has to be allocated to move blocks around.
Left by Loren on Mar 08, 2005 6:55 PM

# re: word wrap in Console app
Requesting Gravatar...
what about one word being too long for the entire line :o

following c# method does all ;) - hope you find it usefull.

public static string Wrap(string myString,int max) {
StringBuilder sb = new StringBuilder();
string[] words = myString.Split(' ');
int p=0;
int bp=0;
int bl=1;
int wl;
string word;
for (int i=0;i<words.Length;) {
word = words[i];
p=0;
wl = word.Length;
if (wl>max) {

bp =0;
while (bp<wl&&bl!=0) {
bl =Math.Min(wl-bp,max);
sb.Append(word.Substring(bp,bl));
sb.Append(Environment.NewLine);
bp+=bl;
}
i++;
} else {
while (((wl+p)<max)&&(i<words.Length)) {
sb.Append(word);
p+=wl;
i++;
if (i<words.Length) {
sb.Append(" ");
p++;
word = words[i];
wl = word.Length;
}
}
}
sb.Append(Environment.NewLine);
}
return(sb.ToString());
}
Left by Chris herridge on Jan 17, 2006 7:52 AM

# re: word wrap in Console app
Requesting Gravatar...
This is a modified version of Chris Herridges warp function (VB.NET).

Known issue: Line breaks in the string are handled as words. They should be removed from the Words array, and added in the string builder when necessary.

Public Shared Function Wrap(ByVal Text As String, ByVal MaxWidth As Integer) As String

Dim sb As StringBuilder = New StringBuilder()
Dim Words() As String = Text.Split(" ")
Dim LinePosition As Integer = 0
Dim WordPosition As Integer = 0
Dim PartialWordLength As Integer = 1
Dim WordLength As Integer
Dim Word As String

' Loop trough every word.
For i As Integer = 0 To Words.Length - 1

' Get info for the current word.
Word = Words(i)
'LinePosition = 0
WordLength = Word.Length

' Check if the current word is longer than the
' maximum allowed width.
If WordLength > MaxWidth Then
' Break the word into one or more lines.

' Reset the positions.
LinePosition = 0
WordPosition = 0

' Loop until the whole word is written.
While WordPosition < WordLength And PartialWordLength <> 0

' Get the maximum length of the partial word
' according to the current word position.
PartialWordLength = Math.Min(WordLength - WordPosition, MaxWidth)

' Append the part of the word to the string.
sb.Append(Word.Substring(WordPosition, PartialWordLength))
LinePosition += PartialWordLength

' Update the positions.
WordPosition += PartialWordLength

' Check if the line has more space left.
If LinePosition < MaxWidth And _
WordPosition = WordLength And _
i < Words.Length And _
Words(i + 1).Length + LinePosition + 1 > MaxWidth Then

' The current line has space left, but the next word
' is to long to fit in this line. Append a line
' terminetor and reset the position.
sb.Append(Environment.NewLine)
LinePosition = 0

ElseIf LinePosition < MaxWidth And _
WordPosition = WordLength And _
i < Words.Length Then

' Append a space.
sb.Append(" ")
LinePosition += 1

i += 1
Word = Words(i)
WordLength = Word.Length

' Append the next words until there are no space left on the line.
While WordLength + LinePosition <= MaxWidth And i < Words.Length

' Append the word to the current line.
sb.Append(Word)

' Update the positions.
LinePosition += WordLength

' Check if the current word is not the last word.
If i < Words.Length Then

' Update the counter and get the information
' for the next word if the line has space left.
If i + 1 < Words.Length Then
If Words(i + 1).Length + LinePosition + 1 <= MaxWidth Then
i += 1
Word = Words(i)
WordLength = Word.Length

' Append a space after the last word
' if the current line has space left.
If LinePosition < MaxWidth Then
sb.Append(" ")
LinePosition += 1
End If
Else
' This line does not have any space left for the next
' word. Make sure no more words are written on this line.
LinePosition = MaxWidth + 1
End If
Else
' This line does not have any space left for the next
' word. Make sure no more words are written on this line.
LinePosition = MaxWidth + 1
End If

End If

End While

Else

' Append a line terminetor and reset the position.
sb.Append(Environment.NewLine)
LinePosition = 0

End If

End While

Else

' Loop until the current line is filled with words.
While (WordLength + LinePosition <= MaxWidth) And i < Words.Length

' Append the word to the current line.
sb.Append(Word)

' Update the positions.
LinePosition += WordLength

' Check if the current word is not the last word.
If i < Words.Length Then

' Update the counter and get the information
' for the next word if the line has space left.
If i + 1 < Words.Length Then
If Words(i + 1).Length + LinePosition + 1 <= MaxWidth Then
i += 1
Word = Words(i)
WordLength = Word.Length

' Append a space after the last word
' if the current line has space left.
If LinePosition < MaxWidth Then
sb.Append(" ")
LinePosition += 1
End If
Else
' This line does not have any space left for the next
' word. Make sure no more words are written on this line.
LinePosition = MaxWidth + 1
End If
Else
' This line does not have any space left for the next
' word. Make sure no more words are written on this line.
LinePosition = MaxWidth + 1
End If

End If

End While

End If

' Append a line terminator if the current word
' is not the last word. Or if LinePosition is
' out of range.
If i < Words.Length And LinePosition >= MaxWidth Then
sb.Append(Environment.NewLine)
LinePosition = 0
End If

Next

Return sb.ToString()

End Function
Left by Richard on Sep 22, 2006 11:54 AM

# re: word wrap in Console app
Requesting Gravatar...
Here's my way of doing it in C#:
private static string wrapForConsole(string message,
string firstLinePrefix,
string normalLinePrefix)
{
// Reset StringBuilder
consoleBuffer.Remove(0, consoleBuffer.Length);
int maxLength = Console.BufferWidth;
consoleBuffer.Append(firstLinePrefix);
int currentLineLength = consoleBuffer.Length;

string[] Words = message.Split(' ');

foreach (string currentWord in Words)
{
if ((currentLineLength + currentWord.Length) < maxLength)
{
consoleBuffer.Append(currentWord);
consoleBuffer.Append(' ');
currentLineLength += currentWord.Length + 1;
}
else
{
if (consoleBuffer[consoleBuffer.Length - 1] == ' ')
consoleBuffer.Remove(consoleBuffer.Length - 1, 1);
consoleBuffer.Append(Environment.NewLine);
consoleBuffer.Append(normalLinePrefix);
consoleBuffer.Append(currentWord);
consoleBuffer.Append(' ');
currentLineLength = normalLinePrefix.Length + currentWord.Length + 1;
}
}
return consoleBuffer.ToString();
}

/// <summary>
/// Console buffer, used by wrapForConsole method
/// </summary>
private static StringBuilder consoleBuffer = new StringBuilder(300);
Left by Raif on Nov 02, 2006 6:06 PM

# re: word wrap in Console app
Requesting Gravatar...
Richard, thanks so much for the VB. Excellent stuff!!
Left by Matt on Apr 04, 2007 12:25 PM

Your comment:
 (will show your gravatar)


Copyright © Chris G. Williams | Powered by: GeeksWithBlogs.net