-3

好的,所以,在我的 C# Cosmos 操作系统中,我正在开发一个系统,该系统允许我输入字符串和所需的宽度,并根据宽度将字符串包装成行。

它的工作原理是这样的:输入字符串是“Hello beautiful world”。宽度为 6。算法将遍历字符串,如果 char 索引是宽度的索引,并且当前 char 是空格,它将获取从字符串开头到该点的所有内容,将其添加到一个列表,并将其从字符串本身中删除,并将字符索引重置为 0,然后重新开始。它会这样做,直到字符串为空或小于宽度。如果它小于宽度,则将其添加到列表中,并终止 for 循环。在外行,我们的输出字符串应该是这样的:

你好
美丽的
世界。

这是我的代码。

public static List<string> split_string(int width, string text)
    {
        List<string> text_lines = new List<string>();
        //Separate lines of text.
        for (int i = 0; i < text.Length; i++)
        {
            if (text.Length <= width)
            {
                text_lines.Add(text);
                i = text.Length + 5;
            }
            else
            {
                if (i >= width)
                {
                    if (text[i] == ' ')
                    {
                        text_lines.Add(text.Substring(0, i + 1));
                        text = text.Remove(0, i + 1);
                        i = 0;
                    }
                }
            }
        }
        return text_lines;
    }

问题是,有时,如果我最终不得不处理小于宽度的字符串,我们就会遇到问题。它似乎跳过了字符串的那一部分。哎呀!

例如,这是我的一个使用它的操作系统。它应该带有标题和消息,并在带有 OK 按钮的消息框中显示它。

public static void ShowMessagebox(string title, string text)
    {
        int splitWidth = 25;
        if(text.Length < splitWidth)
        {
            splitWidth = text.Length;
        }
        if(title.Length > splitWidth)
        {
            splitWidth = title.Length;
        }
        var lines = new List<string>();
        if(splitWidth > text.Length)
        {
            lines.Add(text);
        }
        else
        {
            lines = TUI.Utils.split_string(splitWidth, text);
        }
        foreach(var line in lines)
        {
            if(text.Contains(line))
            {
                text = text.Replace(line, "");
            }
        }
        if(text.Length > 0)
        {
            lines.Add(text);
        }
        int h = lines.Count + 4;
        int w = 0;
        foreach(var line in lines)
        {
            if(line.Length + 4 > w)
            {
                w = line.Length + 4;
            }
        }
        int x = (Console.WindowWidth - w) / 2;
        int y = (Console.WindowHeight - h) / 2;
        TUI.Utils.ClearArea(x, y, w, h, ConsoleColor.Green);
        TUI.Utils.ClearArea(x, y, w, 1, ConsoleColor.White);
        TUI.Utils.Write(x + 1, y, title, ConsoleColor.White, ConsoleColor.Black);
        for(int i = 0; i < lines.Count - 1; i++)
        {
            TUI.Utils.Write(x + 2, (y + 2) + i, lines[i], ConsoleColor.Green, ConsoleColor.White);
        }
        int xw = x + w;
        int yh = y + h;
        TUI.Utils.Write(xw - 6, yh - 2, "<OK>", TUI.Utils.COL_BUTTON_SELECTED, TUI.Utils.COL_BUTTON_TEXT);
        bool stuck = true;
        while (stuck)
        {
            var kinf = Console.ReadKey();
            if (kinf.Key == ConsoleKey.Enter)
            {
                stuck = false;
                Console.Clear();
            }
            else
            {

            }
        }
    }

很简单。以 25 个字符的默认宽度开始,如果标题较大,则将其设置为标题长度。如果文本长度小于宽度,它会设置宽度进行补偿。然后它从上面调用分离器算法,在“TUI.Utils”中找到,然后做一些事情打印到屏幕上。

这是我操作系统的“ConfigurationManager”的一部分,这是一个接受用户输入并使用它来生成配置文件的应用程序。非常正在进行中的工作。

                    Curse.ShowMessagebox("Memphis can't run properly this system.", "Memphis needs at least one FAT partition on a Master Boot Record to be able to store it's configuration and other files on. Please use a partition utility like GParted to partition your hard drive properly.");

但是看看我的屏幕上出现了什么......

来自上述方法调用的消息框

如您所见,这并不是我想要的。它缺少一些字符串!

4

1 回答 1

2

您不需要更改text,因为我们可以只存储原始子字符串的偏移量。我们做的字符串操作越少越好。

public static List<string> split_string(int width, string text)
{
    width = width - 1; //So we're not constantly comparing to width - 1
    var returnSet = new List<string>();
    var currLength = 0;
    var oldOffset = 0;
    for (var i = 0; i < text.Length; i++)
    {
        if (currLength >= width && text[i] == ' ')
        {
            returnSet.Add(text.Substring(oldOffset, i - oldOffset));
            oldOffset = i + 1;
            currLength = 0;
            continue;
        }
        currLength++;
    }
    if (oldOffset < text.Length)
        returnSet.Add(text.Substring(oldOffset));

    return returnSet;
}

测试:

split_string(25, "Memphis needs at least one FAT partition on a Master Boot Record to be able to store it's configuration and other files on. Please use a partition utility like GParted to partition your hard drive properly.");

给出:

孟菲斯至少需要一个
Master 上的 FAT 分区
引导记录能够
存储它的配置
和其他文件。请
使用分区实用程序,例如
GParted 对您的分区进行分区
硬盘驱动器正确。
split_string(6, "Hello beautiful world.")

你好
美丽的
世界。
于 2016-06-22T01:19:29.683 回答