{"id":4207,"date":"2020-06-20T00:01:31","date_gmt":"2020-06-20T07:01:31","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=4207"},"modified":"2020-06-27T08:21:11","modified_gmt":"2020-06-27T15:21:11","slug":"eating-ternary-input","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=4207","title":{"rendered":"Eating Ternary Input"},"content":{"rendered":"<p>I&#8217;m happy I chose to write the function that consumes a ternary value last, shown in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=4192\">last week&#8217;s Lesson<\/a>. The process turns out to be not that big of a deal, though trepidations scurried around me as I wrote the code.<br \/>\n<!--more--><br \/>\nAs with translating a decimal value to ternary, the reverse process starts with the powers of 3 table, which I borrowed from earlier code:<\/p>\n<pre class=\"screen\">\r\n <span class=\"comments\">\/* create the 3 powers table *\/<\/span>\r\n    powers[0] = 1;\r\n    for(x=1;x&lt;11;x++)\r\n    {\r\n        powers[x] = powers[x-1]*3;\r\n    }\r\n    <span class=\"comments\">\/* backup over the null character *\/<\/span>\r\n    len--;<\/pre>\n<p>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 <code>len<\/code> to mark the last character offset in the string referenced by <em>char<\/em> pointer <code>*t<\/code>.<\/p>\n<pre class=\"screen\">\r\n    <span class=\"comments\">\/* translate the string *\/<\/span>\r\n        <span class=\"comments\">\/* find the end of the string *\/<\/span>\r\n    len = 0;\r\n    while(1)\r\n    {\r\n        if( *(t+len)=='\\n' || *(t+len)=='\\0' )\r\n        {\r\n            break;\r\n        }\r\n        len++;\r\n        <span class=\"comments\">\/* limit to 11 digits *\/<\/span>\r\n        if( len==11 )\r\n            break;\r\n    }<\/pre>\n<p>An <em>if<\/em> statement in the loop guards against overflow. When it occurs, the input string is malformed because it&#8217;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&#8217;t write this part of the code.)<\/p>\n<p>With the offset obtained in variable <code>len<\/code>, the final step is to process the string backwards while working through the <code>powers[]<\/code> table forward. I chose a <em>for<\/em> loop for this operation, which allows me to manipulate both forward (<code>p<\/code>) and backward (<code>x<\/code>) variables at the same time:<\/p>\n<pre class=\"screen\">\r\n    <span class=\"comments\">\/* process the string backward\r\n       but process the powers table forward *\/<\/span>\r\n    r = 0;\r\n    for( x=len,p=0 ; x&gt;=0 ; x--,p++)\r\n    {\r\n        <span class=\"comments\">\/* bail on invalid digit *\/<\/span>\r\n        if( *(t+x)&lt;'0' || *(t+x)&gt;'2' )\r\n            return(-1);\r\n        r += ( (*(t+x)-'0') * powers[p] );\r\n    }<\/pre>\n<p>The loop initializes variable <code>x<\/code> to the final character in the string (<code>len<\/code>) and <code>p<\/code> to zero, the first element in the <code>powers[]<\/code> array:<\/p>\n<p><code>for( x=len,p=0 ; x&gt;=0 ; x--,p++)<\/code><\/p>\n<p>The loop spins until <code>x<\/code> is equal to zero. Along the way, <code>x<\/code> is decremented, working backwards through the string; <code>p<\/code> is incremented, working forward through the <code>powers[]<\/code> array.<\/p>\n<p>The loop terminates upon an invalid digit, when <code>*(t+x)<\/code> is outside the range of <code>'0'<\/code>, <code>'1'<\/code>, or <code>'2'<\/code>. This behavior is similar to traditional C input functions, though I believe C checks the input string from left-to-right.<\/p>\n<p>Variable <code>r<\/code> 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 <code>powers[]<\/code> table:<\/p>\n<p><code>r += ( (*(t+x)-'0') * powers[p] );<\/code><\/p>\n<p>The ASCII value of the string character, <code>*(t+x)<\/code>, is reduced by <code>'0'<\/code> which makes its value 0, 1, or 2. This value is multiplied by a power of 3 from the <code>powers[]<\/code> table.<\/p>\n<p>Here is the full source code listing:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2020_06_20-Lesson.c\" rel=\"noopener noreferrer\" target=\"_blank\">2020_06_20-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n\r\nunsigned ternary_in(char *t)\r\n{\r\n    int powers[11];\r\n    int len,x,r,p;\r\n\r\n    <span class=\"comments\">\/* create the 3 powers table *\/<\/span>\r\n    powers[0] = 1;\r\n    for(x=1;x&lt;11;x++)\r\n    {\r\n        powers[x] = powers[x-1]*3;\r\n    }\r\n\r\n    <span class=\"comments\">\/* translate the string *\/<\/span>\r\n        <span class=\"comments\">\/* find the end of the string *\/<\/span>\r\n    len = 0;\r\n    while(1)\r\n    {\r\n        if( *(t+len)=='\\n' || *(t+len)=='\\0' )\r\n        {\r\n            break;\r\n        }\r\n        len++;\r\n        <span class=\"comments\">\/* limit to 11 digits *\/<\/span>\r\n        if( len==11 )\r\n            break;\r\n    }\r\n    <span class=\"comments\">\/* backup over the null character *\/<\/span>\r\n    len--;\r\n\r\n    <span class=\"comments\">\/* process the string backward\r\n       but process the powers table forward *\/<\/span>\r\n    r = 0;\r\n    for( x=len,p=0 ; x&gt;=0 ; x--,p++)\r\n    {\r\n        <span class=\"comments\">\/* bail on invalid digit *\/<\/span>\r\n        if( *(t+x)&lt;'0' || *(t+x)&gt;'2' )\r\n            return(-1);\r\n        r += ( (*(t+x)-'0') * powers[p] );\r\n    }\r\n\r\n    return(r);\r\n}\r\n\r\nint main()\r\n{\r\n    char input[12];\r\n    int ternary;\r\n\r\n    <span class=\"comments\">\/* prompt for input *\/<\/span>\r\n    printf(\"Enter a value in ternary: \");\r\n    fgets(input,12,stdin);\r\n\r\n    ternary = ternary_in(input);\r\n    if( ternary==-1 )\r\n        puts(\"Invalid input\");\r\n    else\r\n        printf(\"This value is %d decimal\\n\",ternary_in(input));\r\n\r\n    return(0);\r\n}<\/pre>\n<p>Sample run:<\/p>\n<p><code>Enter a value in ternary: 210210210<br \/>\nThis value is 15897 decimal<\/code><\/p>\n<p>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&#8217;s how it goes:<\/p>\n<p><code>Enter a value: 15897<br \/>\n15897 in ternary is 210210210<\/code><\/p>\n<p>So everything works. And if I&#8217;m correct, it&#8217;s possible to merge both <em>ternary_in()<\/em> and <em>ternary_out()<\/em> functions into a single program. Further, if the code is solid, you can change the base. I explore this insanity in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=4212\">next week&#8217;s Lesson<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Compared with my toil over the ternary output function from last week&#8217;s Lesson, converting ternary input was a snap. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=4207\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-4207","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4207","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4207"}],"version-history":[{"count":6,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4207\/revisions"}],"predecessor-version":[{"id":4231,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4207\/revisions\/4231"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4207"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4207"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4207"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}