morse.c (4144B)
1 #include <stdio.h> 2 #include <ctype.h> 3 #include <stdlib.h> 4 5 #include <stdio.h> 6 7 enum 8 { 9 START, 10 BAD, 11 TTTT, 12 TTTE, 13 EETT, 14 ETET, 15 EETTE, 16 TTEET, 17 TETET, 18 ETEET, 19 ETTET, 20 EEETE, 21 EEETEE, 22 }; 23 24 struct node 25 { 26 unsigned char seq, dit, dah; 27 } const nodes[] = 28 { 29 [START] = {0, 'E', 'T'}, 30 [BAD] = {0, BAD, BAD}, 31 32 [TETET] = {0, ';', '!'}, 33 [TTEET] = {0, BAD, ','}, 34 [TTTE] = {0, '8', BAD}, 35 [TTTT] = {0, '9', '0'}, 36 [EEETE] = {0, EEETEE, BAD}, 37 [EEETEE] = {0, BAD, '$'}, 38 [EETT] = {0, EETTE, '2'}, 39 [EETTE] = {0, '?', '_'}, 40 [ETEET] = {0, '"', BAD}, 41 [ETET] = {0, '+', BAD}, 42 [ETTET] = {0, '@', BAD}, 43 44 ['$'] = {0b10110111, BAD, BAD}, 45 ['!'] = {0b1001010, BAD, BAD}, 46 [','] = {0b1001100, BAD, BAD}, 47 [')'] = {0b1010010, BAD, BAD}, 48 ['_'] = {0b1010011, BAD, BAD}, 49 ['.'] = {0b1010101, BAD, BAD}, 50 ['='] = {0b101110, BAD, BAD}, 51 ['-'] = {0b1011110, BAD, BAD}, 52 ['\''] = {0b1100001, BAD, BAD}, 53 ['('] = {0b110010, BAD, ')'}, 54 ['@'] = {0b1101001, BAD, BAD}, 55 [';'] = {0b1101010, BAD, BAD}, 56 ['+'] = {0b110101, BAD, '.'}, 57 ['"'] = {0b1101101, BAD, BAD}, 58 ['/'] = {0b110110, BAD, BAD}, 59 ['?'] = {0b1110011, BAD, BAD}, 60 [':'] = {0b1111000, BAD, BAD}, 61 ['&'] = {0b111101, BAD, BAD}, 62 ['0'] = {0b100000, BAD, BAD}, 63 64 ['1'] = {0b100001, '\'', BAD}, 65 ['2'] = {0b100011, BAD, BAD}, 66 ['3'] = {0b100111, BAD, BAD}, 67 ['4'] = {0b101111, BAD, BAD}, 68 ['5'] = {0b111111, BAD, BAD}, 69 ['6'] = {0b111110, BAD, '-'}, 70 ['7'] = {0b111100, BAD, BAD}, 71 ['8'] = {0b111000, ':', BAD}, 72 ['9'] = {0b110000, BAD, BAD}, 73 74 ['A'] = {0b101, 'R', 'W'}, 75 ['B'] = {0b11110, '6', '='}, 76 ['C'] = {0b11010, BAD, TETET}, 77 ['D'] = {0b1110, 'B', 'X'}, 78 ['E'] = {0b11, 'I', 'A'}, 79 ['F'] = {0b11011, BAD, BAD}, 80 ['G'] = {0b1100, 'Z', 'Q'}, 81 ['H'] = {0b11111, '5', '4'}, 82 ['I'] = {0b111, 'S', 'U'}, 83 ['J'] = {0b10001, BAD, '1'}, 84 ['K'] = {0b1010, 'C', 'Y'}, 85 ['L'] = {0b11101, '&', ETEET}, 86 ['M'] = {0b100, 'G', 'O'}, 87 ['N'] = {0b110, 'D', 'K'}, 88 ['O'] = {0b1000, TTTE, TTTT}, 89 ['P'] = {0b11001, BAD, ETTET}, 90 ['Q'] = {0b10100, BAD, BAD}, 91 ['R'] = {0b1101, 'L', ETET}, 92 ['S'] = {0b1111, 'H', 'V'}, 93 ['T'] = {0b10, 'N', 'M'}, 94 ['U'] = {0b1011, 'F', EETT}, 95 ['V'] = {0b10111, EEETE, '3'}, 96 ['W'] = {0b1001, 'P', 'J'}, 97 ['X'] = {0b10110, '/', BAD}, 98 ['Y'] = {0b10010, '(', BAD}, 99 ['Z'] = {0b11100, '7', TTEET}, 100 101 // [1] = 0b101010, 102 // [2] = 0b101010, 103 // [3] = 0b1010111, 104 // [4] = 0b1010111, 105 // [6] = 0b110111, 106 }; 107 108 static char need_space; 109 110 void put_morse_char(unsigned dit) 111 { 112 putchar(dit ? '.' : '_'); 113 } 114 115 void put_morse_seq(unsigned seq) 116 { 117 if (need_space) 118 putchar(' '); 119 while (seq > 1) 120 { 121 put_morse_char(seq & 1); 122 seq >>= 1; 123 } 124 need_space = 1; 125 } 126 127 void put_morse(unsigned char c) 128 { 129 switch (c) 130 { 131 case ' ': 132 if (need_space) 133 putchar(c); 134 /*fallthrough*/ 135 case '\n': 136 putchar(c); 137 need_space = 0; 138 break; 139 default: 140 unsigned char m = nodes[c].seq; 141 if (m) 142 put_morse_seq(m); 143 } 144 } 145 146 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a)) 147 148 void encode() 149 { 150 for (;;) 151 { 152 int c = getchar(); 153 if (c == EOF) 154 break; 155 156 c = toupper(c); 157 if (c < (int)ARRAY_SIZE(nodes)) 158 put_morse(c); 159 } 160 } 161 162 void resolve(unsigned char c, int lower) 163 { 164 if (!nodes[c].seq) 165 return; 166 if (lower) 167 putchar(tolower(c)); 168 else 169 putchar(c); 170 } 171 172 void decode(int lower) 173 { 174 unsigned char out = START; 175 for (;;) 176 { 177 int in = getchar(); 178 switch (in) 179 { 180 case ' ': 181 resolve(out, lower); 182 if (out == START) 183 putchar(' '); 184 out = START; 185 continue; 186 case '\n': 187 resolve(out, lower); 188 out = START; 189 putchar('\n'); 190 continue; 191 case '.': 192 out = nodes[out].dit; 193 continue; 194 case '_': 195 case '-': 196 out = nodes[out].dah; 197 continue; 198 case EOF: 199 resolve(out, lower); 200 return; 201 default: 202 resolve(out, lower); 203 out = START; 204 continue; 205 } 206 } 207 } 208 209 void usage(int code) 210 { 211 fputs("Usage: morse [ e | d | D ]\n\n" 212 " e - encode ASCII to morse code\n" 213 " d - decode morse code to lowercase ASCII\n" 214 " D - decode morse code to uppercase ASCII\n", stderr); 215 exit(code); 216 } 217 218 int main(int argc, char* argv[]) 219 { 220 if (argc != 2) 221 usage(1); 222 223 char arg = argv[1][0]; 224 225 switch (arg) 226 { 227 case 'e': 228 encode(); 229 break; 230 case 'd': 231 case 'D': 232 decode(islower(arg)); 233 break; 234 default: 235 usage(1); 236 } 237 }