c – Decode alphabet encoded message

Inspired by another Q I finally made a version that groups permutable regions into parentheses. Non-ambigous sequences are outside of parens.

Alphabet Code: `A=1, B=2, ..., Z=26`

Output (4 examples):

``````1234567891011121314151617181920212223242526 (Code)

314159265358979323846 (Code)

11011 (Code)
AJ(AA) (Decoded: single, grouped)

22202 (Code)
(BB)TB (Decoded: single, grouped)

18446744073709551616 (Code)
(AH)DDFGD******* Error: zero 30-90
``````

The code is quite long and complicated. The parens seem to be correct now.

Is there a simpler way to achieve this?

The basic idea still seems straight forward, but I end up with two screens full of ifs. (But it is done in one pass)

Or is it silly to decode / reconstruct the message when it is scrambled like that?

``````/*
Decode Fawlty 0x10-shift code (leading zeros lost)
A=1, B=2, ..., Z=26
"111" can thus be "AAA", "AK" or "KA"
Orig. Q. was:
How to count the possible combinations in a message?
This puts freely permutable regions into parentheses,
giving only the single-digit interpretation.
For above "111", output would be "(AAA)"
*/

#include <stdio.h>

void parse_msg(char *msg) {

char c, cprev, cnext;
int i;
/* Start in a state like after a high digit 3..9 */
cprev = '9';
for (i = 0; msg(i) != ''; i++) {

c     = msg(i);
cnext = msg(i+1);

/* Make sure 'cnext' is all the look-ahead that is needed */
/* pull a far ahead "10" or "20" into cnext as '' */
if (cnext != '')
if (msg(i+2) == '0')
cnext = '';

/* "10" and "20" are special cases, get rid of them */
if (cnext == '0') {
if (cprev <= '2')
printf(")");
if (c == '1')
printf("J");
if (c == '2')
printf("T");
if (c >= '3') {
printf("******* Error: zero 30-90n");
return;
}
cprev = '9'; // reset to outside-of-group
i++;         // extra skip in msg
continue;
}

/* ONE: Always open a "(" group, unless cnext is the (fake or real) null byte */
if (c == '1') {
if (cprev >= '3')
if (cnext == '')
cprev = '9';
else {
printf("(");
cprev = c;
}
printf("A");
continue;
}

/* TWO: Maybe open before, or close after, plus set cprev */
if (c == '2') {
/* 32*: is closed, can open */
if (cprev >= '3') {
/* 32: dont open, but mark as closed */
if (cnext == '') {
printf("B");
cprev = '9';
continue;
}
/* 321-926: open before */
if (cnext <= '6')
printf("(");
}

printf("B");

/* "127", "229": is open, must close */
if (cprev <= '2' && cnext >= '7' ) {
printf(")");
cprev = '9';
continue;
}

cprev = c;
continue;
}

/* c == '3' or higher are left */
/* THREE+: No opening */
printf("%c", c + 0x10 );

/* if open, then close group ")" after printing */
if (cprev == '1' || cprev == '2' && c <= '6' )
printf(")");

/* 3..9 marks state as "closed" */
cprev = c;
}

/* End of 'msg' reached: close if opened */
if (cprev <= '2')
printf(")");
printf(" (Decoded: single, grouped) n");

return;
}

int main(void) {

char *msg = "1234567891011121314151617181920212223242526";
printf("%s (Code)n", msg);
parse_msg(msg);

msg = "314159265358979323846";
printf("n%s (Code)n", msg);
parse_msg(msg);

msg = "11011";
printf("n%s (Code)n", msg);
parse_msg(msg);

msg = "22202";
printf("n%s (Code)n", msg);
parse_msg(msg);

msg = "18446744073709551616";
printf("n%s (Code)n", msg);
parse_msg(msg);

return 0;
``````