课后自主练习(字符串)1051. 排版 medium《编程思维与实践》个人学习笔记

该博客讨论了一个字符串排版问题,要求根据特定规则对包含单词、标点和数字的字符串进行排列,确保行宽限制和空格分布。算法涉及字符串遍历、条件判断和空格填充策略,旨在最小化行数并使空格均匀分布于右侧。

题目

给定一行由英文单词、标点符号、数字和空格组成的字符串,对其进行排版输出,要求:

1、原文中由空格分开的连续非空字符串视为一个单词。单词不能分割或跨行输出,同一行的相邻单词由一个或多个空格分开,每行行首和行尾不能为空格,排版后行数尽可能少;

2、除最后一行外,每行长度为 M,长度不足 M 的由空格补足,空格在所有单词之间尽可能均匀分布,在满足上述条件下,空格尽可能置于靠右的位置;

3、最后一行长度不能超过 M,每两个单词之间由一个空格分开,根据实际长度输出,长度不足 M 的不用补足。

输入格式
第 1 行:一个整数 () 为问题数。

接下来共有 2*T 行,每个问题包含 2 行数据,其中:

第 1 行是一个正整数 M (10≤M≤70)为排版后每行长度;

第 2 行是一个待排版字符串,字符串长度 L (1≤L≤2000),至少包含一个单词,每个单词长度 < M/2。

输出格式
对于每个问题,输出一行问题的编号(0 开始编号,格式:case #0: 等)

然后在接下来的数行中,依次输出排版后的文本。
在这里插入图片描述
数据
3
10
abc 123 de fg hi, jkl mn “o p” qq rs t uvwx yz.
10
a bb c d dddd e f ghhh ijkl m nop
20
abc
答案
case #0:
abc 123 de
fg hi, jkl
mn “o p”
qq rs t
uvwx yz.
case #1:
a bb c d
dddd e f
ghhh ijkl
m nop
case #2:
abc

思路

这个题也是挺为难人的
跟消除注释的情况差不多
①先把所有的内容放在一个字符串里面
②然后进行判断,一行中是否还能继续插入新的单词?能就插入并+1个单词,增加多一个空格,如果不能就按规则直接输出一整行(注意空格的处理)
③怎么输出一整行也有大问题
要求输出的空格尽可能分布在右边而且要均匀(注意空格的处理)
int j = 0; for(;word_anum && j < empty / word_anum; j++)
这个是看了答案才知道要用除法来进行操作,左边分的少,盈余的就放在右边

代码

#include<iostream>

using namespace std;

int main()
{
    int t;
    cin >> t;
    for(int z = 0; z < t; z++)
    {
        int line_len;
        cin >> line_len;
        getchar();//有换行符且用getline要记得getchar
        string all;
        getline(cin,all);
        int all_len = all.length();

        
        cout << "case #" << z << ":"<<endl;

        int i = 0;//遍历all的变量
        while(i < all_len)
        {
            
            for(; all[i] == ' '; i++);//处理开头的空格
            int line_loc = i;//每一行的开头
            int word_alen = 0;//记录一行的单词字母数
            int word_anum = 0;//记录单词数,对应的也是最 少空格数+1
            
            for(; word_alen + word_anum <= line_len && i < all_len ;) /*i越界问题。。。*/
            {
                int j = 0, k = i;
                while(all[k] != ' ' && k < all_len) /*l越界问题。。。*/
                {
                    j++;k++;//j记录下一个单词长度
                }
                if(j + word_alen + word_anum <= line_len)
                {
                    word_alen += j;
                    word_anum++;
                    //满足就放进去这一行
                    for(i = k; all[i] == ' '; i++);//继续下一个单词
                }
                else
                    break;
            }
            int empty = line_len - word_alen;//空格数量
            word_anum--;




            while(line_loc < i)
            {
                while(all[line_loc] != ' ' && line_loc < i)
                    cout << all[line_loc++];
                while(all[line_loc] ==' '&& line_loc < i)/*越界问题。。。*/
                    line_loc++;

                if(i == all_len && word_anum)
                    cout << ' ' ;//最后一行输出单个空格
                else
                {
                    int j = 0;//否则让一行的空格尽可能均分在右边
                    for(;word_anum && j < empty / word_anum; j++)
                    {
                        //首先你得输出,然后均分在右边用empty/word数量来操作
                        cout << " " ;
                    }
                    empty -= j;//对应也要减少
                }
                word_anum--;
            }
            cout << endl;
        }
    }

    return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值