LabASD - Formattazione di testo

Moreno Marzolla

Ultimo aggiornamento: 2024-04-10

By NYC Wanderer (Kevin Eng) - originally posted to Flickr as Gutenberg Bible, CC BY-SA 2.0, https://commons.wikimedia.org/w/index.php?curid=9914015
By NYC Wanderer (Kevin Eng) - originally posted to Flickr as Gutenberg Bible, CC BY-SA 2.0, https://commons.wikimedia.org/w/index.php?curid=9914015

Scrivere un programma che legga un file di testo e stampi a video la sequenza di parole che lo compongono in modo che ogni riga abbia lunghezza massima di Lmax caratteri. Il valore di Lmax e il nome del file di testo vengono passati come parametri sulla riga di comando.

Per “parola” si intende una sottosequenza massimale di caratteri per cui la funzione isspace(c) restituisca zero. Ciò significa che consideriamo “parola” qualunque sequenza di caratteri diversi da spazi, ritorno a capo, tabulazioni e simili1.

Il programma deve stampare le parole a video, separando ogni parola dalla successiva con un singolo spazio; gli eventuali “a capo” nell’input devono essere trattati come se fossero spazi. La lunghezza di una riga di output è 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 minore di WORDLEN. Si può inoltre assumere che il valore Lmax sia sempre scelto in modo da essere maggiore o uguale della massima lunghezza delle parole nel testo.

Ad esempio, il comando

    ./formatter 65 divina-commedia-canto1.in

produrrà il seguente risultato (vengono mostrate solo le prime e le ultime cinque righe; si noti che la prima riga non compare nel file di input e viene stampata solo come riferimento per verificare visivamente la lunghezza delle righe):

---------|---------|---------|---------|---------|---------|-----
Nel mezzo del cammin di nostra vita mi ritrovai per una selva
oscura, che la diritta via era smarrita. Ahi quanto a dir qual
era e cosa dura esta selva selvaggia e aspra e forte che nel
pensier rinova la paura! Tant' e amara che poco e piu morte; ma
per trattar del ben ch'i' vi trovai, diro de l'altre cose ch'i'

...

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 codice ASCII del carattere successivo presente nel file, oppure il valore EOF se si è raggiunta la fine del file.

Per riconoscere gli spazi si usi la funzione int isspace(int c) definita in <ctype.h>, che ritorna true (un intero diverso da zero) se e solo se il carattere di codice ASCII c rappresenta uno spazio o simile; sono considerati spazi anche i caratteri form-feed '\f', newline '\n', carriage return '\r', tabulazione '\t', e tabulazione verticale '\v'.

Per compilare:

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

Per eseguire in ambiente Linux/MacOSX:

    ./formatter 65 divina-commedia.in

Per eseguire in ambiente Windows:

    .\formatter 65 divina-commedia.in

Suggerimenti

Questo esercizio può essere risolto mediante una strategia greedy, aggiungendo parole alla riga corrente fin quando possibile.

Assicurarsi che il programma gestisca correttamente i casi particolari; ad esempio:

Curiosità

Il programma da realizzare è una versione molto semplificata di fmt. fmt formatta i paragrafi di un file di testo in modo che ogni riga abbia lunghezza minore o uguale a un valore definito dall’utente. Su distribuzioni Linux basate su Debian, questo comando fa parte del pacchetto coreutils. Si noti che il programma da realizzare si comporta in modo diverso da fmt, perché deve compattare una sequenza di spazi adiacenti nell’input in un singolo spazio in output, e deve trattare gli “a capo” come se fossero spazi. fmt invece non compatta gli spazi e tratta gli “a capo” nell’input come “a capo” nell’output.

Per approfondire

File


  1. Ciò è leggermente diverso da quanto abbiamo visto in altri esercizi, in cui consideravamo parole solo le sequenze di lettere alfabetiche. Di conseguenza, chi vuole riutilizzare le funzioni usate in precedenza dovrà adattarle alla nuova definizione di “parola”.