{ }codelper
子串连接字符串P0104

按宽度换行

第一行给出宽度 w,从下一行起直到输入结束给出正文。
正文中的单词是由非空白(空格、制表符、换行)字符连成的一段。
把单词依次放进行里输出。
同一行的单词之间只放一个空格,行首行尾不放空格。
如果把下一个单词连同一个空格接上后行长超过 w,就从这个单词开始新起一行。
正好等于 w 时写在同一行。
比 w 长的单词从前面开始每 w 个字符切成一段(最后一段可能较短),每一段都当作单词处理。
正文中的换行和空行不影响结果。

输入
1 ≤ w ≤ 80。
正文不超过 8,000 个字符,至少有一个单词。
单词由可打印 ASCII 字符组成
输出
换行后的各行
样例 1 · stdin
10
The quick  brown fox

jumps over a supercalifragilistic dog.
stdout
The quick
brown fox
jumps over
a
supercalif
ragilistic
dog.
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

把每行的单词收集到列表里,再用一个空格连接(join),行尾就不会留下空格:Python " ".join(line),JS·TS line.join(" "),Java String.join(" ", line),C# string.Join(" ", line)。
判断是否超出用 当前长度 + 1 + 单词长度 > w;写成 >= 的话,正好等于 w 的行也会提前一个词换行。
分割单词时 JS split(" ") 是陷阱:空格重叠处会产生空单词 "",也不按制表符分割。
trim().split(/\s+/)、Python split()、C# Split((char[])null, RemoveEmptyEntries)、C scanf("%s")、C++ >> 会一次跳过整段空白。
正文有多行,所以不要只读第一行,要读到输入结束。
切长单词时,Python word[i:i+w]、JS slice、C++ substr(i, w) 超过末尾就停在那里。
C# Substring(i, w) 和 Java substring(i, i + w) 会抛异常,所以用 Math.Min·Math.min 传入剩余长度。
不要不切长单词,也不要用 Python textwrap.wrap:textwrap 会把长单词从当前行剩余的位置开始填,与本题规则(每段 w 个字符)不同。
Craykon 截取(开始, 个数) 也像 C# 一样超过末尾就报错,所以传入 数学.较小值(w, word.长度 - i),行用 line.连接(" ") 连接。

Pythonmain.py · 18 行
import sys first, _, text = sys.stdin.read().partition("\n")w = int(first)pieces = []for word in text.split():  # 빈칸·탭·줄 바꿈이 몇 개든 한 번에 나눈다    for i in range(0, len(word), w):  # 긴 단어는 w글자씩 자른다(슬라이스는 끝을 넘어도 괜찮다)        pieces.append(word[i:i + w]) lines, line, length = [], [], 0for p in pieces:    if line and length + 1 + len(p) > w:  # 빈칸 하나 + 조각이 w를 넘으면 새 줄        lines.append(" ".join(line))        line, length = [], 0    length += len(p) + (1 if line else 0)    line.append(p)lines.append(" ".join(line))print("\n".join(lines))
JavaScriptmain.js · 22 行
const input = require("fs").readFileSync(0, "utf8");const nl = input.indexOf("\n");const w = Number(input.slice(0, nl));const words = input.slice(nl + 1).trim().split(/\s+/);const pieces = [];for (const word of words)  for (let i = 0; i < word.length; i += w) pieces.push(word.slice(i, i + w)); // slice는 끝을 넘어도 괜찮다 const lines = [];let line = [];let length = 0;for (const p of pieces) {  if (line.length > 0 && length + 1 + p.length > w) {    lines.push(line.join(" "));    line = [];    length = 0;  }  length += p.length + (line.length > 0 ? 1 : 0);  line.push(p);}lines.push(line.join(" "));console.log(lines.join("\n"));
TypeScriptmain.ts · 23 行
import { readFileSync } from "node:fs";const input: string = readFileSync(0, "utf8");const nl: number = input.indexOf("\n");const w: number = Number(input.slice(0, nl));const words: string[] = input.slice(nl + 1).trim().split(/\s+/);const pieces: string[] = [];for (const word of words)  for (let i = 0; i < word.length; i += w) pieces.push(word.slice(i, i + w)); // slice는 끝을 넘어도 괜찮다 const lines: string[] = [];let line: string[] = [];let length = 0;for (const p of pieces) {  if (line.length > 0 && length + 1 + p.length > w) {    lines.push(line.join(" "));    line = [];    length = 0;  }  length += p.length + (line.length > 0 ? 1 : 0);  line.push(p);}lines.push(line.join(" "));console.log(lines.join("\n"));
JavaMain.java · 35 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int w = Integer.parseInt(in.readLine().trim());        List<String> pieces = new ArrayList<>();        String row;        while ((row = in.readLine()) != null) {            for (String word : row.trim().split("\\s+")) {                if (word.isEmpty()) continue; // 빈 줄을 나누면 "" 하나가 나온다                for (int i = 0; i < word.length(); i += w)                    pieces.add(word.substring(i, Math.min(i + w, word.length()))); // 끝을 넘으면 예외            }        }        StringBuilder out = new StringBuilder();        List<String> line = new ArrayList<>();        int length = 0;        for (String p : pieces) {            if (!line.isEmpty() && length + 1 + p.length() > w) {                out.append(String.join(" ", line)).append('\n');                line.clear();                length = 0;            }            length += p.length() + (line.isEmpty() ? 0 : 1);            line.add(p);        }        out.append(String.join(" ", line)).append('\n');        System.out.print(out);    }}
C#Main.cs · 35 行
using System;using System.Collections.Generic;using System.Text; class Program{    static void Main()    {        int w = int.Parse(Console.ReadLine());        var pieces = new List<string>();        string row;        while ((row = Console.ReadLine()) != null)        {            foreach (string word in row.Split((char[])null, StringSplitOptions.RemoveEmptyEntries))                for (int i = 0; i < word.Length; i += w)                    pieces.Add(word.Substring(i, Math.Min(w, word.Length - i))); // 끝을 넘으면 예외        }        var sb = new StringBuilder();        var line = new List<string>();        int length = 0;        foreach (string p in pieces)        {            if (line.Count > 0 && length + 1 + p.Length > w)            {                sb.Append(string.Join(" ", line)).Append('\n');                line.Clear();                length = 0;            }            length += p.Length + (line.Count > 0 ? 1 : 0);            line.Add(p);        }        sb.Append(string.Join(" ", line)).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 24 行
#include <algorithm>#include <iostream>#include <string>#include <vector> int main() {    std::size_t w;    std::cin >> w;    std::vector<std::string> pieces;    std::string word;    while (std::cin >> word) // >>는 공백을 건너뛰고 한 단어씩, 입력이 끝나면 거짓        for (std::size_t i = 0; i < word.size(); i += w) pieces.push_back(word.substr(i, w)); // substr는 끝에서 멈춘다     std::string out, line;    for (const auto& p : pieces) {        if (!line.empty() && line.size() + 1 + p.size() > w) {            out += line + '\n';            line.clear();        }        line += (line.empty() ? "" : " ") + p;    }    out += line + '\n';    std::cout << out;}
Cmain.c · 26 行
#include <stdio.h>#include <string.h> int main(void) {    int w, length = 0; /* length: 지금 줄에 쓴 글자 수(0이면 빈 줄) */    static char word[20001];    scanf("%d", &w);    while (scanf("%20000s", word) == 1) { /* %s는 공백을 건너뛰고 한 단어씩 읽는다 */        int len = (int)strlen(word);        for (int i = 0; i < len; i += w) {            int k = len - i < w ? len - i : w; /* 이 조각의 길이 */            if (length > 0 && length + 1 + k > w) {                putchar('\n');                length = 0;            }            if (length > 0) {                putchar(' ');                length++;            }            fwrite(word + i, 1, k, stdout);            length += k;        }    }    putchar('\n');    return 0;}
Craykonmain.cray · 33 行
w = 控制台.读行().转数字();pieces = [];row = 控制台.读行();当 (row != 空){    遍历 (word 在 row.分割())    {        // 긴 단어는 w글자씩. 부분문자열은 끝을 넘으면 오류라서 남은 길이와 작은 쪽을 쓴다        循环 (i = 0; i < word.长度; i += w)        {            pieces.添加(word.截取(i, 数学.较小值(w, word.长度 - i)));        }    }    row = 控制台.读行();}line = [];length = 0;遍历 (p 在 pieces){    如果 (line.数量 > 0 && length + 1 + p.长度 > w)    {        控制台.输出(line.连接(" "));        line = [];        length = 0;    }    如果 (line.数量 > 0)    {        length += 1;    }    length += p.长度;    line.添加(p);}控制台.输出(line.连接(" "));