LabASD - Formattazione di testo

Moreno Marzolla moreno.marzolla@unibo.it

Ultimo aggiornamento: 2021-05-01

Scrivere un programma che legga un file di testo da standard input (oppure da file), e stampi su standard output la sequenza di parole che lo compongono in modo che ogni riga abbia lunghezza massima di Lmax caratteri, con Lmax parametro passato dalla riga di comando.

Più in dettaglio, il programma deve scomporre il testo in sequenza di parole, dove per "parola" si intende una qualunque sottosequenza massimale di caratteri che non includa alcun carattere c per cui l'espressione isspace(c) restituisce un valore diverso da zero.

Il programma deve stampare le parole su standard output, ciascuna separata dalla successiva con un singolo spazio. Gli eventuali "a capo" nell'input devono essere trattati come se fossero spazi. La lunghezza di una riga è data dalla somma delle lunghezze delle parole e degli spazi che le separano, e deve essere minore o uguale a Lmax. Si può assumere che le parole abbiano sempre lunghezza strettamente minore di WORDLEN.

Ad esempio, il comando

    ./formatter 65 < divina-commedia-canto1.in

produrrà un risultato le cui ultime cinque righe sono:

ivi elegge!>>. E io a lui: <<Poeta, io ti richeggio per quello
Dio che tu non conoscesti, a cio ch'io fugga questo male e
peggio, che tu mi meni la dov' or dicesti, si ch'io veggia la
porta di san Pietro e color cui tu fai cotanto mesti>>. Allor si
mosse, e io li tenni dietro.

Può essere utile leggere il prossimo carattere dal file usando la funzione int fgetc(FILE*), definita in <stdio.h>; la funzione restituisce il simbolo EOF se si è raggiunta la fine del file.

Per riconoscere gli spazi è possibile usare la funzione int isspace(int c) definita in <ctype.h>, che ritorna un intero diverso da zero se c è uno spazio o simile (sono considerati spazi anche i caratteri form-feed '\f', newline '\n', carriage return '\r', tabulazione '\t', e tabulazione verticale '\v').

Questo esercizio può essere risolto mediante una strategia greedy: si aggiungono parole alla riga corrente fin quando possibile.

Per compilare:

    gcc -std=c90 -Wall -Wpedantic formatter.c -o formatter

Per eseguire:

    ./formatter 65 < divina-commedia.in

Suggerimenti

Questo esercizio è più complesso di quanto sembri, perché deve gestire numerosi casi particolari. In particolare:

Curiosità

Questo programma è una versione molto semplificata del programma fmt del sistema operativo Unix. fmt formatta i paragrafi di un file di testo in modo da rispettare una ampiezza massima definita dall'utente. Su distribuzioni Linux basate su Debian, questo comando fa parte del pacchetto coreutils. Si noti che il programma richiesto in questo esercizio, a differenza di fmt, compatta una sequenza di spazi contigui in un singolo spazio e tratta gli "a capo" come se fossero spazi.

Per approfondire

File