none
Make Console.WriteLine() wrap words instead of letters with methods RRS feed

  • Question

  • Hello there, the question i just asked was asked on stackoverflow (i cannot share links so please google the title i give for this if you want to find the original topic on stackoverflow) long time ago and the confirmed answer was:

    using System.Text.RegularExpressions;

    //////////////////////////////////////////////////////////////////

    public static void WordWrap(string paragraph) { paragraph = new Regex(@" {2,}").Replace(paragraph.Trim(), @" "); var left = Console.CursorLeft; var top = Console.CursorTop; var lines = new List<string>(); for (var i = 0; paragraph.Length > 0; i++) { lines.Add(paragraph.Substring(0, Math.Min(Console.WindowWidth, paragraph.Length))); var length = lines[i].LastIndexOf(" ", StringComparison.Ordinal); if (length > 0) lines[i] = lines[i].Remove(length); paragraph = paragraph.Substring(Math.Min(lines[i].Length + 1, paragraph.Length)); Console.SetCursorPosition(left, top + i); Console.WriteLine(lines[i]); } }

    ////////////////////////////////////////////////

     WordWrap("Seems like this is the first time you using abcdef or something wrong happened with the configuration file");

    When i try this the the output it separates the lines well however it separates the last word from all the lines for some reason.
    For example this is the output i want to get:
    Seems like this is the first time you using abcdef or something wrong happend 
    with the configuration file
    And this is what i get:
    Seems like this is the first time you using abcdef or something wrong happend 
    with the configuration 
    file
    For now i change the "if (length > 0) lines[i] = lines[i].Remove(length);" line with "if (length > Console.WindowWidth -10) lines[i] = lines[i].Remove(length);" of course that's a cheap solution and i cannot find a way to make it work legit.

    (ps: i don't own the privilege to comment on stackoverflow yet, if you want to ask why i ask it here instead of there)
    Sunday, January 6, 2019 1:14 AM

Answers

  • Using Regular Expressions:

    string text = "Seems like this is the first time you using abcdef or something wrong happened with the configuration file";

    int width = 30; // or Console.WindowWidth string pattern = @"(?<line>.{1," + width + @"})(?<!\s)(\s+|$)|(?<line>.+?)(\s+|$)";

    var lines = Regex.Matches( text, pattern ).Cast<Match>().Select( m => m.Groups["line"].Value ); foreach( var line in lines ) { Console.WriteLine( line ); }


    Words that are longer than width are not split.

    • Marked as answer by xanrer Sunday, January 6, 2019 1:58 PM
    Sunday, January 6, 2019 9:08 AM

All replies

  • Try this

    using System;
    using System.Text;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine(GetWordWrappedParagraph("Seems like this is the first time you using abcdef or" +
                                                          " something wrong happened with the configuration file"));
                Console.ReadLine();
            }
            /// <summary>
            /// https://rianjs.net/2016/03/line-wrapping-at-word-boundaries-for-console-applications-in-csharp
            /// </summary>
            /// <param name="paragraph"></param>
            /// <returns></returns>
            public static string GetWordWrappedParagraph(string paragraph)
            {
                if (string.IsNullOrWhiteSpace(paragraph))
                {
                    return string.Empty;
                }
    
                var approxLineCount = paragraph.Length / Console.WindowWidth;
                var lines = new StringBuilder(paragraph.Length + (approxLineCount * 4));
    
                for (var i = 0; i < paragraph.Length;)
                {
                    var grabLimit = Math.Min(Console.WindowWidth, paragraph.Length - i);
                    var line = paragraph.Substring(i, grabLimit);
    
                    var isLastChunk = grabLimit + i == paragraph.Length;
    
                    if (isLastChunk)
                    {
                        i = i + grabLimit;
                        lines.Append(line);
                    }
                    else
                    {
                        var lastSpace = line.LastIndexOf(" ", StringComparison.Ordinal);
                        lines.AppendLine(line.Substring(0, lastSpace));
    
                        //Trailing spaces needn't be displayed as the first character on the new line
                        i = i + lastSpace + 1;
                    }
                }
                return lines.ToString();
            }
        }
    }
    


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Sunday, January 6, 2019 2:01 AM
    Moderator
  • Using Regular Expressions:

    string text = "Seems like this is the first time you using abcdef or something wrong happened with the configuration file";

    int width = 30; // or Console.WindowWidth string pattern = @"(?<line>.{1," + width + @"})(?<!\s)(\s+|$)|(?<line>.+?)(\s+|$)";

    var lines = Regex.Matches( text, pattern ).Cast<Match>().Select( m => m.Groups["line"].Value ); foreach( var line in lines ) { Console.WriteLine( line ); }


    Words that are longer than width are not split.

    • Marked as answer by xanrer Sunday, January 6, 2019 1:58 PM
    Sunday, January 6, 2019 9:08 AM
  • Works like wonders! Thank you, i made it into a method so that's the complete answer.
            public static void wrpedTxt(string wrpd)
            {
                byte width = Convert.ToByte(Console.WindowWidth);
                string pattern = @"(?<line>.{1," + width + @"})(?<!\s)(\s+|$)|(?<line>.+?)(\s+|$)";
                var lines = Regex.Matches(wrpd, pattern).Cast<Match>().Select(m => m.Groups["line"].Value);
    
                foreach (var line in lines)
                {
                    Console.WriteLine(line);
                }
            }
    
    //////////////////////////////
    
    wrpedTxt("Seems like this is the first time you using abcdef or something wrong happened with the configuration file");
    Sunday, January 6, 2019 2:00 PM
  • Thank you for your answer, there is nothing wrong with it but its a bit too complex for me :) The user Viorel_ find the short solution in the end, but thank you for your response.
    Sunday, January 6, 2019 2:04 PM