View Full Version : [C] compressione file con tecnica rle
tecno789
18-12-2011, 17:45
Salve a tutti, dovrei scrivere un programma che comprimi un file .txt e che sarà chiamato con l'estensione .rle, mediante la tecnica dell'rle. Credo di aver capito all'incirca come l'algoritmo è definito, ma non riesco ad implementarlo, cioè non riesco a prendere l'input di tutto il file ( in byte ) e contare e vedere se si ripetono, qualcuno potrebbe darmi un consiglio?
tecno789
19-12-2011, 17:26
nessuno può darmi una mano a capire??
Per contare se i caratteri si ripetono potresti usare un array con 255 posizioni, una per ogni carattere.
int NumeroCaratteri[ 255 ];
A quel punto quando leggi un carattere, puoi fare qualcosa del tipo:
while( EsistonoCaratteriDaLeggere )
{
char CarattereCorrente = EstraiCarattereCorrente();
NumeroCaratteri[ CarattereCorrente ] += 1;
}
Comunque esplicita meglio qual è il tuo problema... cos'è che non riesci a fare esattamente? La lettura da file? Il conteggio? L'output? (sono solo esempi).
tecno789
19-12-2011, 20:11
Per contare se i caratteri si ripetono potresti usare un array con 255 posizioni, una per ogni carattere.
int NumeroCaratteri[ 255 ];
A quel punto quando leggi un carattere, puoi fare qualcosa del tipo:
while( EsistonoCaratteriDaLeggere )
{
char CarattereCorrente = EstraiCarattereCorrente();
NumeroCaratteri[ CarattereCorrente ] += 1;
}
Comunque esplicita meglio qual è il tuo problema... cos'è che non riesci a fare esattamente? La lettura da file? Il conteggio? L'output? (sono solo esempi).
contare i byte che si ripetono, proprio non capisco come si faccia....
tecno789
19-12-2011, 21:02
leggere i byte uno alla volta e vedere se si ripetono o no? :mbe:
1 byte = 1 char
vorresti dire che è la stessa cosa delle stringhe?
tecno789
20-12-2011, 18:28
scusate un altra cosa non riesco a fare.... come faccio a cambiare l'estensione del file??
rename(argv[1]".rle",fp2);
questa funzione non vale, come faccio?
poi l'algoritmo deve anteporre il numero di volte davanti al carattere che si ripete, ma come diavolo faccio?? :D
è un pò che sbatto la testa su questo programma ma sinceramente non riesco proprio a scriverlo... una mano sarebbe più che gradita.
tecno789
20-12-2011, 20:58
si, 1 byte = 1 char, leggi con fread...
e ma dopo la lettura? come faccio a contare se si ripete ogni singolo carattere e poi inserirlo nel file stesso?!!
mmx[ngg]
20-12-2011, 21:51
rename(argv[1]".rle",fp2); ....ci sei quasi :sofico:
Che poi...scusa...perchè rinominare il file ? Non ha molto senso se lo devi comprimere, dovresti crearne uno nuovo con l'estensione diversa.
Prima di tutto come funziona l'RLE...comprime sostituendo le sequenze uguali di caratteri adiacenti con un marcatore di riconoscimento + il numero delle volte da ripete + il carattere da ripetere
Esempio :
- il file contiene AAAAACAAA
- il tuo marcatore sarà ?
- dopo la compressione avrai ?5AC?3A
...se qualcuno che mi conosce vede questo esempio mi prendono x il culo per decenni :D
Questa è la spiegazione più semplice che mi viene, lontana dall'essere perfetta visto che l'utilizzo di un marcatore in quel modo è da evitare ma non vedo soluzioni più eleganti.
Pseudo algoritmo :
NumeroRipetizioni = 0
Minimo = 3
Routine RLE
Se CharAttuale <> CharPrecedente
Se NumeroRipetizioni > Minimo
Scrivi marcatore
Scrivi NumeroRipetizioni
Scrivi CharPrecedente
NumeroRipetizioni = 0
FineSe
Ciclo NumeroRipetizioni > 0
Scrivi CharPrecedente
NumeroRipetizioni - 1
FineCiclo
CharPrecedente = CharAttuale
FileSe
FineRoutine
Ciclo !EOF
Leggi CharAttuale
Esegui RLE
NumeroRipetizioni + 1
FineCiclo
Esegui RLE
Grossolano ma la logica è quella. Ricorda che il marcatore, che decidi te, deve essere un carattere non presente nel file o la decompressione non funziona infatti al suo posto si utilizza la soglia minimi di caratteri ripetibili come segnale di inizio della compressione (ma mi sembra che sia fuori traccia altrimenti non potresti/dovresti scrivere il numero di volte prima).
P.S.
Spero per te che non dovrai mai vedertela con algoritimi di compressione aritmetica o peggio :D
tecno789
20-12-2011, 22:05
;36584867']rename(argv[1]".rle",fp2); ....ci sei quasi :sofico:
Che poi...scusa...perchè rinominare il file ? Non ha molto senso se lo devi comprimere, dovresti crearne uno nuovo con l'estensione diversa.
Prima di tutto come funziona l'RLE...comprime sostituendo le sequenze uguali di caratteri adiacenti con un marcatore di riconoscimento + il numero delle volte da ripete + il carattere da ripetere
Esempio :
- il file contiene AAAAACAAA
- il tuo marcatore sarà ?
- dopo la compressione avrai ?5AC?3A
...se qualcuno che mi conosce vede questo esempio mi prendono x il culo per decenni :D
Questa è la spiegazione più semplice che mi viene, lontana dall'essere perfetta visto che l'utilizzo di un marcatore in quel modo è da evitare ma non vedo soluzioni più eleganti.
Pseudo algoritmo :
NumeroRipetizioni = 0
Minimo = 3
Routine RLE
Se CharAttuale <> CharPrecedente
Se NumeroRipetizioni > Minimo
Scrivi marcatore
Scrivi NumeroRipetizioni
Scrivi CharPrecedente
NumeroRipetizioni = 0
FineSe
Ciclo NumeroRipetizioni > 0
Scrivi CharPrecedente
NumeroRipetizioni - 1
FineCiclo
CharPrecedente = CharAttuale
FileSe
FineRoutine
Ciclo !EOF
Leggi CharAttuale
Esegui RLE
NumeroRipetizioni + 1
FineCiclo
Esegui RLE
Grossolano ma la logica è quella. Ricorda che il marcatore, che decidi te, deve essere un carattere non presente nel file o la decompressione non funziona infatti al suo posto si utilizza la soglia minimi di caratteri ripetibili come segnale di inizio della compressione (ma mi sembra che sia fuori traccia altrimenti non potresti/dovresti scrivere il numero di volte prima).
P.S.
Spero per te che non dovrai mai vedertela con algoritimi di compressione aritmetica o peggio :D
mhm ok infatti la rinomina mi sembra sbagliata, ma aprendo un nuovo file, non riesco a dargli un'estensione diverse in quanto, puoi passare per argomento solo il file di input e non quello di output, cioè non si può decidere a priori il nome del file compresso.
L'RLE ormai l'avevo capito come algoritmo ma ti ringrazio per la spiegazione, il problema è proprio implementarlo con i file, ora provo meglio, visto che mi hai scritto anche in pseudocodice e mi hai dato una mano grandissima, anche se ho ancora numerosissimi dubbi a riguardo, a partire proprio dall'estensione che viene cambiata del file!
mmx[ngg]
20-12-2011, 23:07
Sono secoli che non uso più il C quindi magari è sbagliato ma ricordo una roba tipo :
strcpy(OutputFileName, argv[1]); -- Aggiungge l'estensione al file
strcat(OutputFileName, ".rle");
pos = strrchr(argv[1], '.')-argv[1]; -- Cambia l'estensione al file
strncpy(OutputFileName, argv[1], pos);
OutputFileName[pos + 1] = '\0';
strcat(OutputFileName, ".rle");
Ho qualche dubbio sul secondo perchè non ricordo se terminava le stringhe in automatico o meno comunque prova e vedi che ti dice. Ovviamente questo è il file che devi andare ad aprire in scrittura senza rinominare l'altro.
tecno789
21-12-2011, 08:20
;36585248']Sono secoli che non uso più il C quindi magari è sbagliato ma ricordo una roba tipo :
strcpy(OutputFileName, argv[1]); -- Aggiungge l'estensione al file
strcat(OutputFileName, ".rle");
pos = strrchr(argv[1], '.')-argv[1]; -- Cambia l'estensione al file
strncpy(OutputFileName, argv[1], pos);
OutputFileName[pos + 1] = '\0';
strcat(OutputFileName, ".rle");
Ho qualche dubbio sul secondo perchè non ricordo se terminava le stringhe in automatico o meno comunque prova e vedi che ti dice. Ovviamente questo è il file che devi andare ad aprire in scrittura senza rinominare l'altro.
bravissimo ecco cosa ci voleva, non ci ho proprio pensato, la concatenazione!! bravo!!
ora impresa difficile sarà continuare il programma :D
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.