使用stl以不同方式拆分字符串

splitting strings in different ways using stl

本文关键字:方式 拆分 字符串 stl 使用      更新时间:2023-10-16

我有一个字符串"子弹武器对装甲的伤害较小"。有一个条件是,这个字符串必须根据参数int width=20以不同的方式拆分成多个部分。

1.将给定宽度的文本换行。

"子弹武器对装甲的伤害较小。"成为

"Bullet weapons do le"
"ss damage against ar"
"mor."
  1. 将给定宽度的文本换行,但除非绝对必要,否则不会拆分单词。

    "子弹武器对装甲的伤害较小。"成为

    "子弹武器可以"较少的损坏"装甲。"

3.将文本包装成特定的宽度,除非绝对必要,否则不得拆分单词。包装时,此函数将尝试使线条在宽度方面尽可能均匀。

"Bullet weapons do less damage against armor." becomes
"Bullet weapons "
"do less damage "
"against armor."

对于情况1:我编写了如下逻辑:

     int len=text.length();   where text is string text= "Bullet weapons do less damage     against armor."
int last=0,first=0;
    vector<string> output;

int max=ceil((double)len/width);
cout<<max<<endl;

for(int i=0;i<max;i++)
{
    first=width*i;
    if(len<(width+(width*i)))
    {
        last=len;
    }
    else
    {
        last=width+(width*i);
    }

    string s(text,first,last);
    output.push_back(s);

}

但它给我的结果是:

子弹武器ss对护甲的伤害。莫。在第二行中,它应该达到"ss对ar的伤害",其中逻辑错误;

情况(2)和(3)如何。

请帮我解决

感谢

构造函数的第三个参数是要构造的字符串的长度,而不是最后一个字符的偏移量。

  1. 您应该更改

    string s(text,first,last); --> string s(text,first,width);
    
  2. 您应该考虑将字符串拆分为单词,然后将这些单词添加到另一个检查长度的字符串中。

    int i = -1;
    string word = "";
    string part = "";
    do
    {
        i = text.find(' ');
        if (i != -1)
        {
            word = text.substr(0, i);
            text = text.substr(i + 1);
            if (word.length() + part.length() < width)
            {
                part += " " + word;
            }
            else
            {
                output.push_back(part);
                cout << part << endl;
                part = word;
            }
        }
        else
        {
            word = text;
            if (word.length() + part.length() < width)
            {
                part += " " + word;
                output.push_back(part);
                cout << part << endl;
            }
            else
            {
                output.push_back(part);
                cout << part << endl;
                output.push_back(word);
                cout << word << endl;
            }
        }
    } while (i != -1);
    
  3. 在进行类似情况2 的操作之前,您应该重新计算宽度

案例1:正如其他人已经指出的,您的示例中的字符串构造函数有点错误,行应该是:

string s(text,first,width);

案例2:我建议从一个等于最大允许宽度的子字符串开始,然后向后搜索空白,如下所示:

while (!text.empty())
{
    // Search backwards for a space. If we don't find one, break at the
    // maximum width.
    size_t line_width = text.rfind(' ', width - 1);
    if (line_width == string::npos)
    {
        line_width = width;
    }
    string current_line(text, 0, line_width);
    text = text.substr(line_width + 1);
    cout << current_line << endl;
}

案例3:为此,你似乎需要弄清楚什么样的宽度才能使线条的长度最规则。可能有几种方法可以做到这一点,但我想到的解决方案是多次运行算法,每次都减小宽度,每次都跟踪每条线比该宽度短多少(称之为"宽度差")。解决方案是具有最小总宽度差的一组线。

vector<string> best_line_set;
size_t best_total_width_difference = std::numeric_limits<size_t>::max();
for (j = width; j > 4; --j)
{
    string original_text(text);
    vector<string> current_line_set;
    size_t current_total_width_difference = 0;
    while (!text.empty())
    {
        // Search backwards for a space. If we don't find one, break at the
        // maximum width.
        size_t line_width = text.rfind(' ', j - 1);
        if (line_width == string::npos)
        {
            line_width = j;
            string current_line(text, 0, line_width);
            text = (line_width < text.size())
                ? text.substr(line_width)
                : "";
            current_line_set.push_back(current_line);
        }
        else
        {
            current_total_width_difference += j - line_width;
            string current_line(text, 0, line_width);
            text = (line_width + 1  < text.size())
                ? text.substr(line_width + 1)
                : "";
            current_line_set.push_back(current_line);
        }
    }
    if (current_total_width_difference < best_total_width_difference)
    {
        best_line_set = current_line_set;
        best_total_width_difference = current_total_width_difference;
    }
    text = original_text;
}

注意,我为j选择了一个最小值5——如果最小值为1,它几乎总是获胜,因为它的总宽度差总是0。您还可以考虑在总和中包含某种"足够好"的阈值,这样您就不会为了改进已经"足够好的"解决方案而多次运行循环。