Zeilenumbruch programmieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

nfehren hat geschrieben:Ich möchte die Sache verstehen.
Dann habe ich hier mal einen Codeschnipsel zum experimentieren und erweitern.

Code: Alles auswählen

def get_first_part(text, max_length):
    if len(text) <= max_length:
        return text
    for pos in range(max_length - 1, 0, -1):
        if text[pos] == ' ':
            return text[:pos]
BlackJack

Ähm, um die Position eines Zeichens zu finden gibt es auch Methoden auf Zeichenketten-Objekten.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Und ich werfe jetzt mal `''.partition()` in den Ring:

Code: Alles auswählen

>>> text = 'A long sentence, really long.'
>>> text.partition(' ')
('A', ' ', 'long sentence, really long.')
Ich könnte mir vorstellen, dass man sich damit Wort für Wort geben lässt und diese zusammensetzt, bis der zusammengesetzte Text plus das kommende Wort länger als die 80 Zeichen sind. Dann geb' ich den zusammengesetzten Text zurück und mach' weiter...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Wäre es da nicht geschickter gleich mit `split()` alle Worte auf einmal zu trennen, anstatt das Wort für Wort zu machen?
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

BlackJack hat geschrieben:Ähm, um die Position eines Zeichens zu finden gibt es auch Methoden auf Zeichenketten-Objekten.
Der Fragesteller wollte ja unbedingt so low-level wie möglich arbeiten.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

BlackJack hat geschrieben:@mutetella: Wäre es da nicht geschickter gleich mit `split()` alle Worte auf einmal zu trennen, anstatt das Wort für Wort zu machen?
Man könnte dann auch noch direkt eine Liste aus Tupeln mit Wort und Wortlänge bauen.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack
Ja, wäre geschickter. Aber ich wollte einfach mal das arme, vernachlässigte `partition()` aus seiner dunklen Kammer ans Licht bringen... :wink:

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich glaube einfache Lösungen werden hier nicht gesucht :P

Code: Alles auswählen

# -*- coding: utf-8 -*-
import re

TEXT = u"Das hier wird ein längerer Text der einem Test dienen soll, einen Zeilenumbruch zu machen. Die Zeilen dürfen 50 Zeichen breit sein und müssen danach ein newline vorweisen können. Im Nachhinein muss man das Programm so verbessern, dass es keine ganzen Wörter abschneidet. Viel Glück!"
print re.sub('(.{,80}) ',r'\1\n',TEXT)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

@Sirius3: Die Lösung ist wirklich hübsch.
Das Leben ist wie ein Tennisball.
nfehren
User
Beiträge: 98
Registriert: Donnerstag 31. Oktober 2013, 15:11

Also ich hab das jetzt mal soweit, dass er bei 50 abschneidet und mir sagt wie viele zeichen + das letzte Leerzeichen es noch gibt. Jetzt muss ich nur noch diese Anzahl der jeweiligen Zeile abziehen und an die untere vorne anhängen. Hier steh ich jetzt aber echt aufm Schlauch vor allem weil ich jetzt in einer Endlosschleife bin.

Code: Alles auswählen

while j <= len(s):
    line = ""
    for i in range (j -1 , j + z -1):
        if i < len(s):
            line += (s[i])
    if len(line) == z:
        for i in range(0, z):
            print(z -1 - i, len(line))
            if line[z -1 - i] == " ":
                break
        j += 50 - i -1
    print(i+1)
    print(line)
BlackJack

@nfehren: Die Zeilen 2 bis 5 (inklusive) sind äusserst umständlich. Den gleichen Effekt könntest Du durch eine einzige Zeile bekommen in der Du einfach den entsprechenden Ausschnitt per „slicing” kopierst. Also ``line = s[j - 1:j + z - 1]`` wenn ich das richtig sehe.

Aber vielleicht sollte man das Ende erst mal ermitteln statt zwingend `z` Zeichen an `line` zu binden. Ich bin mir auch nicht sicher ob ``j - 1`` so eine gute Idee ist, denn `j` wird man vor der Schleife ja an 0 binden.

Du hast da noch eine literale 50 im Quelltext die vielleicht noch durch `z` ersetzt werden sollte. Beziehungsweise alle `z` dann durch einen Namen der dem Leser auf den ersten Blick verrät was der Wert in dem Algorithmus bedeutet.

Ich würde zwei Indizes verwenden, einen für die Startposition und einen für die Endposition. Und das ausschneiden der Teilzeichenkette erst machen wenn beide stimmen. Also solange der Startindex noch kleiner als die Länge des Textes ist, den Endindex ermitteln, dann die Teilzeichenkette ausgeben und den Startindex anpassen. Start und Ende kann man auch entsprechend `start` und `end` nennen, statt `i` und `j`.
BlackJack

Ich hab's mal in JavaScript umgesetzt:

Code: Alles auswählen

#!/usr/bin/env node
'use strict';

String.prototype.wrap = function (maxWidth) {
    var lines, start, end;
    maxWidth = maxWidth || 80;
    lines = [];
    start = 0;
    while (start < this.length) {
        end = start + maxWidth;
        if (end < this.length) {
            while (end > start && this[end] !== ' ') {
                end -= 1;
            }
        }
        if (start === end) {
            end += maxWidth;
        }
        lines.push(this.slice(start, end));
        start = end;
        if (this[start] === ' ') {
            start += 1;
        }
    }
    return lines.join('\n');
};

var main = function () {
    var text = 'Das hier wird ein längerer Text der einem Test dienen soll,'
        + ' einen Zeilenumbruch zu machen. Die Zeilen dürfen 50 Zeichen breit'
        + ' sein und müssen danach ein newline vorweisen können. Im Nachhinein'
        + ' muss man das Programm so verbessern, dass es keine ganzen Wörter'
        + ' abschneidet. Viel Glück! '
        + '=================================================='
        + '==================================================';
    
    console.log(text.wrap(50));
    console.log(text.wrap());
    console.log(''.wrap());
};

if (require.main === module) {
    main();
}
Antworten