# Eating Ternary Input

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 = 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;
int len,x,r,p;

/* create the 3 powers table */
powers = 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;
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.