{"id":6678,"date":"2024-11-30T00:01:37","date_gmt":"2024-11-30T08:01:37","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=6678"},"modified":"2024-12-02T21:02:49","modified_gmt":"2024-12-03T05:02:49","slug":"sorting-the-hexwords-part-ii","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=6678","title":{"rendered":"Sorting the Hexwords, Part II"},"content":{"rendered":"<p>The problem with the code from <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6673\">last week&#8217;s Lesson<\/a> is obvious: The decimal value of FEED is 1,044,205, not 2,314,885,530,818,453,605 as shown in the output. Before I can sort the list numerically, this error must be addressed.<br \/>\n<!--more--><br \/>\nMy first guess was that the <em>strtol()<\/em> function overflowed &mdash; which it did so when I tried to calculate a <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6573\">Look-and-Say sequence<\/a>. But overflow isn&#8217;t the problem.<\/p>\n<p>Scoping out the values in the code, I could see that the proper string is being translated, but not stored. So it&#8217;s most likely a silly pointer error.<\/p>\n<p>Check out this line from the code:<\/p>\n<p><code>list = realloc( list, sizeof(struct entry) * count+1 );<\/code><\/p>\n<p>This statement seeks to increase the size of the <code>list<\/code> buffer by <code>count<\/code> items, plus one. But due to the order of precedence, the size is increased by <code>count<\/code> items <span style=\"text-decoration: underline\">plus one byte<\/span>. The proper statement is:<\/p>\n<p><code>list = realloc( list, sizeof(struct entry) * (count+1) );<\/code><\/p>\n<p>By enclosing <code>count+1<\/code> in parentheses, the calculation properly increases the size of buffer <code>list<\/code> by <code>count<\/code> items (<em>entry<\/em> structures), plus one. This new size creates enough room to store the next item in the dynamic array. The proper value is then saved, which makes the list valid. Problem solved.<\/p>\n<p>With the memory properly allocated, the next (and final) task is to sort the hexwords by their values. The <code>value<\/code> member of the <em>entry<\/em> structure is used. Here is <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=1258\">the <em>qsort()<\/em> function<\/a> from my code:<\/p>\n<p><code>qsort(list,count,sizeof(struct entry),compare);<\/code><\/p>\n<p>The items to sort are at address <code>list<\/code>. There are <code>count<\/code> items in the list. Each item is the size of an <em>entry<\/em> structure. The final argument is the <em>compare()<\/em> function, which can prove to be a bit of a pickle to code.<\/p>\n<p>The <em>qsort()<\/em> <em>compare()<\/em> function accepts two arguments, but <em>const void<\/em> pointers, <code>a<\/code> and <code>b<\/code>. In the function, the trick is to convert these <em>const void<\/em> pointers into <em>entry<\/em> structure pointers for comparison. I cover this technique in a <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5660\">blog post<\/a> from two years ago. Here&#8217;s the <em>compare()<\/em> function required:<\/p>\n<p><code>int compare(const void *a, const void *b)<br \/>\n{<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;struct entry *x,*y;<br \/>\n&nbsp;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;x = (struct entry *)a;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;y = (struct entry *)b;<br \/>\n&nbsp;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;return( x-&gt;value - y-&gt;value );<br \/>\n}<\/code><\/p>\n<p>Two <em>entry<\/em> structure pointers are declared, <code>*x<\/code> and <code>*y<\/code>. These are initialized to the <em>const void<\/em> pointers <code>a<\/code> and <code>b<\/code> (the address arguments), but typecast to <em>entry<\/em> structure pointers. The return value is the difference between <code>a<\/code> and <code>b<\/code>, but translated into the proper data type.<\/p>\n<p>Here is the full code:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2024_11_30-Lesson.c\" rel=\"noopener\" target=\"_blank\">2024_11_30-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n<span class=\"comments\">\/* Hex Words *\/<\/span>\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;string.h&gt;\r\n\r\n<span class=\"comments\">\/* this code assumes the following path is valid *\/<\/span>\r\n#define DICTIONARY \"\/usr\/share\/dict\/words\"\r\n#define SIZE 32\r\n\r\n<span class=\"comments\">\/* move this outside *\/<\/span>\r\nstruct entry {\r\n    char hex[SIZE];\r\n    long value;\r\n};\r\n\r\nint compare(const void *a, const void *b)\r\n{\r\n    struct entry *x,*y;\r\n\r\n    x = (struct entry *)a;\r\n    y = (struct entry *)b;\r\n\r\n    return( x-&gt;value - y-&gt;value );\r\n}\r\n\r\nint main()\r\n{\r\n    FILE *dict;\r\n    char word[SIZE],hexword[SIZE],*r,*w;\r\n    int count,x;\r\n    struct entry *list;\r\n\r\n    <span class=\"comments\">\/* open the dictionary *\/<\/span>\r\n    dict = fopen(DICTIONARY,\"r\");\r\n    if( dict==NULL )\r\n    {\r\n        fprintf(stderr,\"Unable to open %s\\n\",DICTIONARY);\r\n        exit(1);\r\n    }\r\n\r\n    <span class=\"comments\">\/* read the dictionary *\/<\/span>\r\n    count = 0;\r\n    while( !feof(dict) )\r\n    {\r\n        <span class=\"comments\">\/* read a word from the dictionary *\/<\/span>\r\n        r = fgets(word,SIZE,dict);\r\n        if( r==NULL )    <span class=\"comments\">\/* no word, done *\/<\/span>\r\n            break;\r\n\r\n        <span class=\"comments\">\/* remove newline *\/<\/span>\r\n        w = word;\r\n        while(*w)\r\n        {\r\n            if( *w=='\\n' )\r\n            {\r\n                *w = '\\0';\r\n                break;\r\n            }\r\n            w++;\r\n        }\r\n\r\n        <span class=\"comments\">\/* pull out only hex characters *\/<\/span>\r\n        sscanf(word,\"%[ABCDEFabcdef]\",hexword);\r\n\r\n        <span class=\"comments\">\/* compare hexword with original word *\/<\/span>\r\n        if( strcmp(word,hexword)==0 &amp;&amp; strlen(hexword)&gt;3 )\r\n        {\r\n            if( count==0 )\r\n            {\r\n                list = malloc( sizeof(struct entry) );\r\n                if( list==NULL )\r\n                {\r\n                    fprintf(stderr,\"Unable to allocate memory\\n\");\r\n                    exit(1);\r\n                }\r\n                strcpy( list-&gt;hex,hexword );\r\n                list-&gt;value = strtol(hexword,NULL,16);\r\n            }\r\n            else\r\n            {\r\n                list = realloc( list, sizeof(struct entry) * (count+1) );\r\n                if( list==NULL )\r\n                {\r\n                    fprintf(stderr,\"Unable to reallocate memory\\n\");\r\n                    exit(1);\r\n                }\r\n                strcpy( (list+count)-&gt;hex,hexword );\r\n                (list+count)-&gt;value = strtol(hexword,NULL,16);\r\n            }\r\n            count++;\r\n        }\r\n    }\r\n\r\n    <span class=\"comments\">\/* sort the list *\/<\/span>\r\n    qsort(list,count,sizeof(struct entry),compare);\r\n\r\n    <span class=\"comments\">\/* output the list *\/<\/span>\r\n    for( x=0; x&lt;count; ++x )\r\n        printf(\"%3d: %-10s %10ld\\n\",\r\n                x+1,\r\n                (list+x)-&gt;hex,\r\n                (list+x)-&gt;value\r\n              );\r\n\r\n    <span class=\"comments\">\/* clean-up *\/<\/span>\r\n    fclose(dict);\r\n    free(list);\r\n    return(0);\r\n}<\/pre>\n<p>And the output:<\/p>\n<p><code>&nbsp;&nbsp;1:&nbsp;abed&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;44013<br \/>\n&nbsp;&nbsp;2:&nbsp;aced&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;44269<br \/>\n&nbsp;&nbsp;3:&nbsp;babe&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;47806<br \/>\n&nbsp;&nbsp;4:&nbsp;bade&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;47838<br \/>\n&nbsp;&nbsp;5:&nbsp;bead&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;48813<br \/>\n...<br \/>\n&nbsp;38:&nbsp;efface&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;15727310<br \/>\n&nbsp;39:&nbsp;facade&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;16435934<br \/>\n&nbsp;40:&nbsp;acceded&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;181202413<br \/>\n&nbsp;41:&nbsp;defaced&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;233811181<br \/>\n&nbsp;42:&nbsp;effaced&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;251636973<\/code><\/p>\n<p>You can&#8217;t see it in the abbreviated output above, but the value for <code>feed<\/code> is properly translated. Though it&#8217;s the last value output alphabetically, numerically hexword <code>effaced<\/code> has the highest value.<\/p>\n<p>I truly enjoyed the process of creating this program. Finding and fixing the various puzzles and addressing the unintended errors was fun! This delight is why I enjoy programming. I hope that you do as well.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The final program reads valid hexwords and sorts them by their values. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6678\">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-6678","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\/6678","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=6678"}],"version-history":[{"count":9,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6678\/revisions"}],"predecessor-version":[{"id":6749,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6678\/revisions\/6749"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6678"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6678"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6678"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}