{"id":4212,"date":"2020-06-27T00:01:50","date_gmt":"2020-06-27T07:01:50","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=4212"},"modified":"2020-06-27T08:26:08","modified_gmt":"2020-06-27T15:26:08","slug":"i-o-in-almost-any-base","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=4212","title":{"rendered":"I\/O in [Almost] Any Base"},"content":{"rendered":"<p>After climbing the ternary I\/O mountain, and crafting functions that both input and output base 3 values, the next step is obvious: Combine both functions into a single program. The step after that is less obvious: Change the code so that any base can be used to process input or generate output.<br \/>\n<!--more--><br \/>\nWell, almost any base.<\/p>\n<p>As the functions are written, then work best to translate bases that use digits 0 through 9. I assume base 11 would use &#8216;A&#8217; to represent the decimal 10, just as hexadecimal does. This modification could be made to my code, but I was in a hurry to see whether it worked.<\/p>\n<p>From <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=4207\">last week&#8217;s Lesson<\/a>, I crafted the <em>base_in()<\/em> function.<\/p>\n<p>From the <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=4192\">week before&#8217;s Lesson<\/a>, I created the <em>base_out()<\/em> function.<\/p>\n<p>To make both work with any base (as opposed to base 3), I created the defined constant <code>BASE<\/code>, which can be set to a value from 2 to 9:<\/p>\n<p><code>#define BASE 5<\/code><\/p>\n<p>The changes in each function include building the powers table:<\/p>\n<pre class=\"screen\">\r\n<span class=\"comments\">\/* create the powers table *\/<\/span>\r\n    powers[0] = 1;\r\n    for(x=1;x&lt;12;x++)\r\n    {\r\n        powers[x] = powers[x-1]*BASE;\r\n    }<\/pre>\n<p>And the test for a valid digit in the input function:<\/p>\n<pre class=\"screen\">\r\n<span class=\"comments\">\/* bail on invalid digit *\/<\/span>\r\n        if( *(t+x)&lt;'0' || *(t+x)&gt;(BASE+'0') )\r\n            return(-1);<\/pre>\n<p>Otherwise, the functions are pretty-much the same as shown in earlier Lessons for my ternary I\/O functions. Here is the full code, which works with base 5:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2020_06_27-Lesson.c\" rel=\"noopener noreferrer\" target=\"_blank\">2020_06_27-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\n#define BASE 5\r\n\r\n<span class=\"comments\">\/* translate value to string *\/<\/span>\r\nchar *base_out(unsigned n)\r\n{\r\n    static char tstring[12];\r\n    char *t;\r\n    int powers[12];\r\n    int x,r;\r\n\r\n    <span class=\"comments\">\/* check for overflow *\/<\/span>\r\n    if( n&lt;0 || n&gt;65535 )\r\n    {\r\n        fprintf(stderr,\"%d is out of range\\n\",n);\r\n        exit(1);\r\n    }\r\n\r\n    <span class=\"comments\">\/* create the powers table *\/<\/span>\r\n    powers[0] = 1;\r\n    for(x=1;x&lt;12;x++)\r\n    {\r\n        powers[x] = powers[x-1]*BASE;\r\n    }\r\n\r\n    <span class=\"comments\">\/* build the return string *\/<\/span>\r\n    tstring[11] = '\\0';\r\n    for(x=0;x&lt;11;x++)\r\n\r\n        r = n % powers[x+1];\r\n        n -= r;\r\n        tstring[10-x] = r\/powers[x] + '0';\r\n    }\r\n\r\n    <span class=\"comments\">\/* remove any leading zeros *\/<\/span>\r\n    t = tstring;\r\n    x = 0;\r\n    while( *t=='0' &amp;&amp; x&lt;10 )\r\n\r\n        t++;\r\n        x++;\r\n    }\r\n\r\n    return(t);\r\n}\r\n\r\n<span class=\"comments\">\/* translate string to value *\/<\/span>\r\nunsigned base_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 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]*BASE;\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;(BASE+'0') )\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    unsigned b;\r\n    char *bstring;\r\n\r\n    printf(\"Base %d I\/O\\n\",BASE);\r\n    <span class=\"comments\">\/* prompt for input *\/<\/span>\r\n    printf(\"Enter a decimal value: \");\r\n    scanf(\"%d\",&amp;b);\r\n\r\n    bstring = base_out(b);\r\n    printf(\"%d in base %d is %s\\n\",b,BASE,bstring);\r\n    printf(\"%s in decimal is %d\\n\",bstring,base_in(bstring));\r\n\r\n    return(0);\r\n}<\/pre>\n<p>The code outputs the base in the <em>main()<\/em> function, then prompts for an input value in decimal. This value is translated into the named base for output, then the base-whatever value string is translated back into decimal, proving that the thing works.<\/p>\n<p>Here&#8217;s your sample run:<\/p>\n<p><code>Base 5 I\/O<br \/>\nEnter a decimal value: 12345<br \/>\n12345 in base 5 is 343340<br \/>\n343340 in decimal is 12345<\/code><\/p>\n<p>Improvements to the code might include making the powers table dynamic. For example, the higher the base the more astronomical the values in the powers table. Further, this value can be keyed to an input cap for the <em>base_out()<\/em> function. In the current code, the input cap is set at Line 14 to 65535.<\/p>\n<p>Another obvious improvement would be to properly handle bases higher than 9. I almost made this improvement, but figured it would be a good exercise for you to try on your own.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Given the routines provided for ternary I\/O, you can easily write functions that input and output values in any base. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=4212\">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-4212","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\/4212","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=4212"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4212\/revisions"}],"predecessor-version":[{"id":4232,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4212\/revisions\/4232"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4212"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4212"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4212"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}