Ultimo aggiornamento: 2024-04-10
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
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:
Il programma funziona correttamente se l’input è un file vuoto, o contenente solo spazi?
Il programma funziona correttamente se l’input contiene una singola parola, senza spazi né prima né dopo?
Il programma stampa correttamente la prima/l’ultima riga del file di input?
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.
Si modifichi il programma in modo da giustificare le righe stampate a video, inserendo spazi aggiuntivi nel modo più uniforme possibile in modo che la lunghezza di ogni riga uguale a Lmax
.
La soluzione che si chiede di realizzare tratta gli “a capo” come se fossero spazi. Modificare il programma per mandare a capo l’output ogni volta che si incontra un “a capo” nell’input.
./formatter 75 divina-commedia-canto1.in
dovrebbe produrre questo risultato; la prima riga, prodotta dalla funzione header()
, serve solo come riferimento.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”.↩