Wrap text to the next line when it exceeds a certain length?

社会主义新天地 提交于 2019-12-23 07:09:35

问题


I need to write different paragraphs of text within a certain area. For instance, I have drawn a box to the console that looks like this:

/----------------------\
|                      |
|                      |
|                      |
|                      |
\----------------------/

How would I write text within it, but wrap it to the next line if it gets too long?


回答1:


Split on last space before your row length?

int myLimit = 10;
string sentence = "this is a long sentence that needs splitting to fit";
string[] words = sentence.Split(new char[] { ' ' });
IList<string> sentenceParts = new List<string>();
sentenceParts.Add(string.Empty);

int partCounter = 0;

foreach (string word in words)
{
    if ((sentenceParts[partCounter] + word).Length > myLimit)
    {
        partCounter++;
        sentenceParts.Add(string.Empty);
    }

    sentenceParts[partCounter] += word + " ";
}

foreach (string x in sentenceParts)
    Console.WriteLine(x);

UPDATE (the solution above lost the last word in some cases):

int myLimit = 10;
string sentence = "this is a long sentence that needs splitting to fit";
string[] words = sentence.Split(' ');

StringBuilder newSentence = new StringBuilder();


string line = "";
foreach (string word in words)
{
    if ((line + word).Length > myLimit)
    {
        newSentence.AppendLine(line);
        line = "";
    }

    line += string.Format("{0} ", word);
}

if (line.Length > 0)
    newSentence.AppendLine(line);

Console.WriteLine(newSentence.ToString());



回答2:


I modified the version of Jim H such that it supports some special cases. For example the case when the sentence does not contain any whitespace character; I also noted that there is a problem when a line has a space at the last position; then the space is added at the end and you end up with one character too much.

Here is my version just in case someone is interested:

public static List<string> WordWrap(string input, int maxCharacters)
{
    List<string> lines = new List<string>();

    if (!input.Contains(" "))
    {
        int start = 0;
        while (start < input.Length)
        {
            lines.Add(input.Substring(start, Math.Min(maxCharacters, input.Length - start)));
            start += maxCharacters;
        }
    }
    else
    {
        string[] words = input.Split(' ');

        string line = "";
        foreach (string word in words)
        {
            if ((line + word).Length > maxCharacters)
            {
                lines.Add(line.Trim());
                line = "";
            }

            line += string.Format("{0} ", word);
        }

        if (line.Length > 0)
        {
            lines.Add(line.Trim());
        }
    }

    return lines;
}



回答3:


I modified Manfred's version. If you put a string with the '\n' character in it, it will wrap the text strangely because it will count it as another character. With this minor change all will go smoothly.

public static List<string> WordWrap(string input, int maxCharacters)
    {
        List<string> lines = new List<string>();

        if (!input.Contains(" ") && !input.Contains("\n"))
        {
            int start = 0;
            while (start < input.Length)
            {
                lines.Add(input.Substring(start, Math.Min(maxCharacters, input.Length - start)));
                start += maxCharacters;
            }
        }
        else
        {
            string[] paragraphs = input.Split('\n');

            foreach (string paragraph in paragraphs)
            {
                string[] words = paragraph.Split(' ');

                string line = "";
                foreach (string word in words)
                {
                    if ((line + word).Length > maxCharacters)
                    {
                        lines.Add(line.Trim());
                        line = "";
                    }

                    line += string.Format("{0} ", word);
                }

                if (line.Length > 0)
                {
                    lines.Add(line.Trim());
                }
            }
        }
        return lines;
    }



回答4:


I started with Jim H.'s solution and end up with this method. Only problem is if text has any word that longer than limit. But works well.

public static List<string> GetWordGroups(string text, int limit)
{
    var words = text.Split(new string[] { " ", "\r\n", "\n" }, StringSplitOptions.None);

    List<string> wordList = new List<string>();

    string line = "";
    foreach (string word in words)
    {
        if (!string.IsNullOrWhiteSpace(word))
        {
            var newLine = string.Join(" ", line, word).Trim();
            if (newLine.Length >= limit)
            {
                wordList.Add(line);
                line = word;
            }
            else
            {
                line = newLine;
            }
        }
    }

    if (line.Length > 0)
        wordList.Add(line);

    return wordList;
}



回答5:


This is a more complete and tested solution.

  • The bool overflow parameter specifies, whether long words are chunked in addition to splitting up by spaces.
  • Consecutive whitespaces, as well as \r, \n, are ignored and collapsed into one space.
  • Edge cases are throughfully tested

public static string WrapText(string text, int width, bool overflow)
{
    StringBuilder result = new StringBuilder();

    int index = 0;
    int column = 0;

    while (index < text.Length)
    {
        int spaceIndex = text.IndexOfAny(new[] { ' ', '\t', '\r', '\n' }, index);

        if (spaceIndex == -1)
        {
            break;
        }
        else if (spaceIndex == index)
        {
            index++;
        }
        else
        {
            AddWord(text.Substring(index, spaceIndex - index));
            index = spaceIndex + 1;
        }
    }

    if (index < text.Length) AddWord(text.Substring(index));

    void AddWord(string word)
    {
        if (!overflow && word.Length > width)
        {
            int wordIndex = 0;
            while (wordIndex < word.Length)
            {
                string subWord = word.Substring(wordIndex, Math.Min(width, word.Length - wordIndex));
                AddWord(subWord);
                wordIndex += subWord.Length;
            }
        }
        else
        {
            if (column + word.Length >= width)
            {
                if (column > 0)
                {
                    result.AppendLine();
                    column = 0;
                }
            }
            else if (column > 0)
            {
                result.Append(" ");
                column++;
            }

            result.Append(word);
            column += word.Length;
        }
    }

    return result.ToString();
}



回答6:


This code will wrap the paragraph text. It will break the paragraph text into lines. If it encounters any word which is even larger than the line length, it will break the word into multiple lines too.

private const int max_line_length = 25;

private string wrapLinesToFormattedText(string p_actual_string) {

    string formatted_string = "";
    int available_length = max_line_length;

    string[] word_arr = p_actual_string.Trim().Split(' ');

    foreach (string w in word_arr) {

        string word = w;
        if (word == "") {
            continue;
        }


        int word_length = word.Length;

        //if the word is even longer than the length that the line can have
        //the large word will get break down into lines following by the successive words 
        if (word_length >= max_line_length)
        {
            if (available_length > 0)
            {
                formatted_string += word.Substring(0, available_length) + "\n";
                word = word.Substring(available_length);
            }
            else
            {
                formatted_string += "\n";
            }
            word = word + " ";
            available_length = max_line_length;
            for (var count = 0;count<word.Length;count++) {
                char ch = word.ElementAt(count);

                if (available_length==0) {
                    formatted_string += "\n";
                    available_length = max_line_length;
                }

                formatted_string += ch;
                available_length--;
            }                    
            continue;
        }




        if ((word_length+1) <= available_length)
        {
            formatted_string += word+" ";
            available_length -= (word_length+1);
            continue;
        }
        else {
            available_length = max_line_length;
            formatted_string += "\n"+word+" " ;
            available_length -= (word_length + 1);
            continue;                    
        }

    }//end of foreach loop

    return formatted_string;
}
//end of function wrapLinesToFormattedText

Blockquote




回答7:


Here's one that is lightly tested and uses LastIndexOf to speed things along (a guess):

    private static string Wrap(string v, int size)
    {
        v = v.TrimStart();
        if (v.Length <= size) return v;
        var nextspace = v.LastIndexOf(' ', size);
        if (-1 == nextspace) nextspace = Math.Min(v.Length, size);
        return v.Substring(0, nextspace) + ((nextspace >= v.Length) ? 
        "" : "\n" + Wrap(v.Substring(nextspace), size));
    }


来源:https://stackoverflow.com/questions/10541124/wrap-text-to-the-next-line-when-it-exceeds-a-certain-length

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!