Run-length encoding/C: Difference between revisions
Content added Content deleted
(now the sample compiles with gcc-4.4.1 on Ubuntu) |
(→[[Run-length encoding/C#Unbuffered - generative: The following code sample is experimental as it implements python style iterators.) |
||
Line 1: | Line 1: | ||
{{collection|Run-length encoding}} |
{{collection|Run-length encoding}} |
||
=== Unbuffered - Generative === |
|||
'''Using GNU Compiler Collection gcc extensions''' |
|||
{{trans|ALGOL 68}} |
|||
{{works with|gcc|gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)}} |
|||
Note: The following code sample is experimental as it implements python style iterators for (potentially) infinite sequences. The code also uses "macro magic", C is not normally written this way, and in the case of this sample it requires the GCC "nested procedure" extension to the C language. |
|||
Also: In this implementation, '''string'''s are assumed to be null terminated. Hence cannot contain the ''null'' character as data. |
|||
<lang c>#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
char *input = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW"; |
|||
char *output = "12W1B12W3B24W1B14W"; |
|||
typedef void (*YIELDCHAR)(); /* yields via yield_init */ |
|||
typedef void (*GENCHAR) (); |
|||
/* #include <macro.h> :-) */ |
|||
typedef enum{FALSE=0, TRUE=1}BOOL; |
|||
#ifdef NEED_GOTO |
|||
#include <setjmp.h> |
|||
/* declare label otherwise it is not visible in sub-scope */ |
|||
#define LABEL(label) jmp_buf label; if(setjmp(label))goto label; |
|||
#define GOTO(label) longjmp(label, TRUE) |
|||
#endif |
|||
/* the following line is the only time I have ever required "auto" */ |
|||
#define FOR(i,iterator) auto BOOL lambda(i); yield_init = (void *)λ iterator; BOOL lambda(i) |
|||
#define DO { |
|||
#define YIELD(x) if(!yield(x))return |
|||
#define BREAK return FALSE |
|||
#define CONTINUE return TRUE |
|||
#define OD CONTINUE; } |
|||
/* Warning: _Most_ FOR(,){ } loops _must_ have a CONTINUE as the last statement. |
|||
* Otherwise the lambda will return random value from stack, and may terminate early */ |
|||
typedef BOOL ITERATOR; |
|||
static volatile void *yield_init; /* not thread safe */ |
|||
#define YIELDS(type) BOOL (*yield)(type) = yield_init |
|||
ITERATOR gen_char_seq (char *s){ |
|||
YIELDS(char); |
|||
fflush(stdout); |
|||
int upb_s = strlen(s); |
|||
int i; for(i = 0; i <= upb_s; i++) YIELD(s[i]); |
|||
} |
|||
void input_seq (){ YIELDS(char); FOR(char c, gen_char_seq(input))DO yield(c); OD; } |
|||
void output_seq (){ YIELDS(char); FOR(char c, gen_char_seq(output))DO yield(c); OD; } |
|||
ITERATOR gen_encode (GENCHAR gen_char){ |
|||
YIELDS(char); |
|||
int count = 0; |
|||
char prev; |
|||
FOR(char c, gen_char())DO |
|||
if(count == 0){ |
|||
count = 1; |
|||
prev = c; |
|||
} else if(c != prev){ |
|||
char str_count[32]; sprintf(str_count, "%d", count); |
|||
FOR(char c, gen_char_seq(str_count))DO YIELD(c); OD; |
|||
count = 1; |
|||
YIELD(prev); prev = c; |
|||
}else{ |
|||
count +=1; |
|||
} |
|||
OD; |
|||
if(count != 0){ |
|||
char str_count[32]; sprintf(str_count, "%d", count); |
|||
FOR(char c, gen_char_seq(str_count))DO YIELD(c); OD; |
|||
YIELD(prev); |
|||
} |
|||
} |
|||
char *zero2nine = "0123456789"; |
|||
ITERATOR gen_decode (GENCHAR gen_char){ |
|||
YIELDS(char); |
|||
int repeat = 0; |
|||
FOR(char c, (*gen_char)())DO |
|||
if(strchr(zero2nine, c)){ |
|||
repeat = repeat*10 + c - '0'; |
|||
}else{ |
|||
int i; for(i=1; i <= repeat; i++ ){ YIELD(c); } |
|||
repeat = 0; |
|||
} |
|||
OD |
|||
} |
|||
main(){ |
|||
/* iterate through input string */ |
|||
printf("Encode input: "); |
|||
FOR(char c, gen_encode(input_seq))DO |
|||
putchar(c); |
|||
OD; |
|||
printf("\n"); |
|||
/* iterate through output string */ |
|||
printf("Decode output: "); |
|||
FOR(char c, gen_decode(output_seq))DO |
|||
putchar(c); |
|||
OD; |
|||
printf("\n"); |
|||
}</lang> |
|||
Output: |
|||
<pre> |
|||
Encode input: 12W1B12W3B24W1B14W1 |
|||
Decode output: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW |
|||
</pre> |
|||
=== Buffered === |
|||
These functions have no check for the size of the output buffers. |
These functions have no check for the size of the output buffers. |
||