I’m happy I chose to write the function that consumes a ternary value last, shown in last week’s Lesson. The process turns out to be not that big of a deal, though trepidations scurried around me as I wrote the code.

As with translating a decimal value to ternary, the reverse process starts with the powers of 3 table, which I borrowed from earlier code:

/* create the 3 powers table */ powers[0] = 1; for(x=1;x<11;x++) { powers[x] = powers[x-1]*3; } /* backup over the null character */ len--;

Because numbers are read from right to left, the next step is to locate the end of the string. The following loop does so, using integer `len`

to mark the last character offset in the string referenced by *char* pointer `*t`

.

/* translate the string */ /* find the end of the string */ len = 0; while(1) { if( *(t+len)=='\n' || *(t+len)=='\0' ) { break; } len++; /* limit to 11 digits */ if( len==11 ) break; }

An *if* statement in the loop guards against overflow. When it occurs, the input string is malformed because it’s longer than the powers of 3 table allows to translate a value. (The function should probably return -1 as an error, but I didn’t write this part of the code.)

With the offset obtained in variable `len`

, the final step is to process the string backwards while working through the `powers[]`

table forward. I chose a *for* loop for this operation, which allows me to manipulate both forward (`p`

) and backward (`x`

) variables at the same time:

/* process the string backward but process the powers table forward */ r = 0; for( x=len,p=0 ; x>=0 ; x--,p++) { /* bail on invalid digit */ if( *(t+x)<'0' || *(t+x)>'2' ) return(-1); r += ( (*(t+x)-'0') * powers[p] ); }

The loop initializes variable `x`

to the final character in the string (`len`

) and `p`

to zero, the first element in the `powers[]`

array:

`for( x=len,p=0 ; x>=0 ; x--,p++)`

The loop spins until `x`

is equal to zero. Along the way, `x`

is decremented, working backwards through the string; `p`

is incremented, working forward through the `powers[]`

array.

The loop terminates upon an invalid digit, when `*(t+x)`

is outside the range of `'0'`

, `'1'`

, or `'2'`

. This behavior is similar to traditional C input functions, though I believe C checks the input string from left-to-right.

Variable `r`

holds the return value, which starts as zero but increases with each valid digit found in the string, multiplied by its corresponding power of 3 from the `powers[]`

table:

`r += ( (*(t+x)-'0') * powers[p] );`

The ASCII value of the string character, `*(t+x)`

, is reduced by `'0'`

which makes its value 0, 1, or 2. This value is multiplied by a power of 3 from the `powers[]`

table.

Here is the full source code listing:

### 2020_06_20-Lesson.c

#include <stdio.h> #include <stdlib.h> unsigned ternary_in(char *t) { int powers[11]; int len,x,r,p; /* create the 3 powers table */ powers[0] = 1; for(x=1;x<11;x++) { powers[x] = powers[x-1]*3; } /* translate the string */ /* find the end of the string */ len = 0; while(1) { if( *(t+len)=='\n' || *(t+len)=='\0' ) { break; } len++; /* limit to 11 digits */ if( len==11 ) break; } /* backup over the null character */ len--; /* process the string backward but process the powers table forward */ r = 0; for( x=len,p=0 ; x>=0 ; x--,p++) { /* bail on invalid digit */ if( *(t+x)<'0' || *(t+x)>'2' ) return(-1); r += ( (*(t+x)-'0') * powers[p] ); } return(r); } int main() { char input[12]; int ternary; /* prompt for input */ printf("Enter a value in ternary: "); fgets(input,12,stdin); ternary = ternary_in(input); if( ternary==-1 ) puts("Invalid input"); else printf("This value is %d decimal\n",ternary_in(input)); return(0); }

Sample run:

`Enter a value in ternary: 210210210`

This value is 15897 decimal

The real test, however, is to run value 15897 through the other program, the one I wrote last week to translate decimal into ternary. Here’s how it goes:

`Enter a value: 15897`

15897 in ternary is 210210210

So everything works. And if I’m correct, it’s possible to merge both *ternary_in()* and *ternary_out()* functions into a single program. Further, if the code is solid, you can change the base. I explore this insanity in next week’s Lesson.