2015-05-20 4 views
6

Sto implementando l'algoritmo RLE in C e sto riscontrando un grosso problema. Sto usando @ come identificatore per la compressione/decompressione. Mi permetta di utilizzare esempi:Distinguere la lettura del carattere dal numero intero

0 0 0 0 1 2 0 0 0 0 = @ 0 4 1 2 0 4 @

Tipo di @ X = Y ripetizione X, Y volte. E i numeri variano da 0 a 255 (carattere senza segno). Ma il numero 64 mi sta fregando, perché è lo stesso di "@".

Il programma legge 64 0 5

mi aspetto: 64 0 5 (non è necessaria alcuna decompressione)

Cosa ottengo: 0 0 0 0 0 (64 è memorizzato in una variabile char, e poi , il programma usa come '@')

if (var == '@') { 
    // decompress 
} 
+2

In Insomma, è necessario implementare un meccanismo di escape per distinguere i marker dai dati. –

+0

Come si converte il 'carattere non firmato 'in numeri interi? – kaylum

risposta

1

Credo che si stia utilizzando qualche scanf -come la funzione per analizzare il vostro input.

no. Non funzionerà in questo caso.

Invece, basta leggere la stringa di input, divisi si da spazi bianchi in token (esempi: "@ 0 4 1 2 @ 0 4" ->"@", "0", "4", "1", "2", "@", "0", "4" e "64 0 5" ->"64", "0", "5").

Il passo successivo è l'analisi. Qui puoi estirpare lo @-s.Sarà facile distinguerli dai 64 -s come strlen("@") == 1 e strlen("64") == 2, si vede;)

E quando si incontra una stringa puramente numerico, è possibile usare qualcosa come atoi per convertirlo in un numero intero (e dopo questo sei libero di convertirlo in unsigned char).

+0

Grazie! La tua soluzione ha funzionato come un fascino. –

1

è necessario selezionare una sequenza di caratteri che non è assolutamente intenzione di essere utilizzato come un meccanismo di fuga. Se stai trasformando l'input in @ <character> <count> se ci sono almeno 3 occorrenze consecutive dello stesso carattere, l'input peggiore che non si trasforma ha 2 caratteri consecutivi @.

Un altro caso peggiore in input è 64 @ caratteri, che produce @ @ @. Quindi, siamo sicuri che l'output non può contenere più di 3 consecutive @.

Alla luce di ciò, è possibile rappresentare un singolo carattere @ come @@@@, che produce 4 caratteri. Come visto in precedenza, l'uscita del RLE non può avere 4 s '(o di qualsiasi altro 4 caratteri consecutivi, in quel modo)

Ma invece, se si sempre trasformare @ in @ @ <count>, è possibile risparmiare un byte @ consecutiva e dovrai solo modificare le parti di creazione RLE del tuo progetto, poiché questo formato è perfettamente a posto con un parser RLE.

0

Questo potrebbe non essere il modo migliore per risolvere il problema, ma fa il lavoro. Il compilatore c converte automaticamente int in char e char in int al bisogno. Se riesci a trovare un modo per limitare questo comportamento, il problema è risolto. Ho limitato il comportamento convertendo il carattere in respective ASCII e confrontandolo con ASCII value di @.

L'ovvio problema con il programma è che legge i singoli caratteri e non verrà mai visualizzato nel suo insieme, ma anche se modifichiamo il programma per dividere i numeri con lo spazio come delimitatore, non penso che sarebbe qualsiasi problema

#include<stdio.h> 
    #include<string.h> 
    int main() 
    { 
     char s[]= "64 0 5 @ 0 5"; 
     int length = strlen(s); 
     int i = 0; 
     char ch; 
     while((ch = s[i]) != '\0') 
     { 
      int charASCII = ch; 
      if(charASCII == 64) 
       printf("Perform Algorithm\n"); 
      else 
       printf("Do not Perform Algorithm\n"); 
      i++; 
     } 
     return 0; 
    } 
0

Una soluzione molto semplice per l'escaping dell'istruzione di ripetizione ha un carattere ripetuto.

Mi spiego:

codificare 0 0 0 0 come 0 0 2 (2 significato di ripetere altre 2 volte il carattere precedente)

Basta essere attenti per 2 volte ripetizioni:

3 4 4 5 devono essere codificati come 3 4 4 0 5 ,

0 significa che non segue più "4".

Durante la decodifica è sufficiente cercare un carattere ripetuto e, quando trovato, ottenere il carattere successivo come numero di volte per ripeterlo.

esempio testato:

int input_char(void); 
void output_char(int); 

void encode(void) { 
    int c, previous_c = EOF; 
    int repeating = 0, repetitions; 

    while ((c = input_char()) != EOF) { 
     if (repeating) { 
      if (c == previous_c && repetitions < 255) { 
       ++repetitions; 
      } else { 
       output_char(repetitions); 
       output_char(c); 
       repeating = 0; 
      } 
     } else { 
      output_char(c); 
      if (previous_c == c) { 
       repeating = 1; 
       repetitions = 0; 
      } 
     } 
     previous_c = c;    
    } 
} 

void decode(void) 
{ 
    int c, previous_c = EOF; 

    while ((c = input_char()) != EOF) { 
     output_char(c); 
     if (c == previous_c) { 
      int repetitions = (unsigned char) input_char(); 

      while (repetitions--) { 
       output_char(c); 
      } 
     } 
     previous_c = c;    
    } 
} 
0

Guardando questa ascii table: è possibile vedere la gamma che è per i numeri, l'uso che per determinare se si sta leggendo un numero o no:

if (var >= 48 && var <= 57) {/* I'm an integer */}