{"id":7312,"date":"2025-12-27T00:01:26","date_gmt":"2025-12-27T08:01:26","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=7312"},"modified":"2025-12-20T10:36:10","modified_gmt":"2025-12-20T18:36:10","slug":"a-colorful-hexdump","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=7312","title":{"rendered":"A Colorful Hexdump"},"content":{"rendered":"<p>By combining the code page 437 data from <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7301\">last week&#8217;s Lesson<\/a> into my colorful <em>hexdump<\/em> utility, I&#8217;m finally able to wrap up the code and produce a program that outputs a more interesting file dump.<br \/>\n<!--more--><br \/>\nAs a filter, the program accepts standard input or redirected input to examine the contents of any file. Data is read and output in 16 byte chunks, set by using the defined constant <code>WIDTH<\/code>.<\/p>\n<p>This program uses ANSI colors to show non-printable characters: <span style=\"color:red;\">RED<\/span> is used for ASCII control codes 0 through 31 and 127, and <span style=\"color:green;\">GREEN<\/span> is used for character codes 128 through 255. Unicode characters for these codes are output, both the control characters as well as code page 437 characters.<\/p>\n<p>Here is the C code:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2025_12_27-Lesson.c\" rel=\"noopener\" target=\"_blank\">2025_12_27-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;locale.h&gt;\r\n#include &lt;wchar.h&gt;\r\n\r\n#define RED \"\\e[31m\"\r\n#define GREEN \"\\e[32m\"\r\n#define NORMAL \"\\e[m\"\r\n#define WIDTH 16\r\n\r\nint main()\r\n{\r\n    wchar_t    extended_ASCII[] = {\r\n        0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0,\r\n        0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF,\r\n        0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6,\r\n        0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,\r\n        0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5,\r\n        0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA,\r\n        0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310,\r\n        0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,\r\n        0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561,\r\n        0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557,\r\n        0x255D, 0x255C, 0x255B, 0x2510, 0x2514, 0x2534,\r\n        0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,\r\n        0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550,\r\n        0x256C, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559,\r\n        0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518,\r\n        0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,\r\n        0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3,\r\n        0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4,\r\n        0x221E, 0x03C6, 0x03B5, 0x2229, 0x2261, 0x00B1,\r\n        0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248,\r\n        0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2,\r\n        0x25A0, 0x00A0\r\n    };\r\n    unsigned char buffer[WIDTH];\r\n    int offset,r,x;\r\n\r\n    <span class=\"comments\">\/* set the locale for wide characters *\/<\/span>\r\n    setlocale(LC_ALL,\"\");\r\n\r\n    <span class=\"comments\">\/* main dumping loop *\/<\/span>\r\n    offset = 0;\r\n    while( !feof(stdin) )\r\n    {\r\n        r = fread(buffer,sizeof(unsigned char),WIDTH,stdin);\r\n        <span class=\"comments\">\/* break on EOF *\/<\/span>\r\n        if( r==0 )\r\n            break;\r\n        <span class=\"comments\">\/* print offset *\/<\/span>\r\n        wprintf(L\"%04X \",offset);\r\n        <span class=\"comments\">\/* print hex values *\/<\/span>\r\n        for( x=0; x&lt;r; x++ )\r\n        {\r\n            if( buffer[x]&lt;32 )\r\n                wprintf(L\" %s%02X%s\",RED,buffer[x],NORMAL);\r\n            else if( buffer[x]==127 )\r\n                wprintf(L\" %s%02X%s\",RED,buffer[x],NORMAL);\r\n            else if( buffer[x]&gt;127 )\r\n                wprintf(L\" %s%02X%s\",\r\n                        GREEN,\r\n                        buffer[x],\r\n                        NORMAL\r\n                       );\r\n            else\r\n                wprintf(L\" %02X\",buffer[x]);\r\n            if( x==7 )\r\n                wprintf(L\" -\");\r\n        }\r\n        <span class=\"comments\">\/* fill in the rest of a blank row *\/<\/span>\r\n        if( r&lt;WIDTH )\r\n        {\r\n            for( x=r; x&lt;WIDTH; x++ )\r\n            {\r\n                wprintf(L\"   \");\r\n                if( x==7 )\r\n                    wprintf(L\"  \");\r\n            }\r\n        }\r\n\r\n        <span class=\"comments\">\/* print ASCII *\/<\/span>\r\n        wprintf(L\"   \");\r\n        for( x=0; x&lt;r; x++)\r\n        {\r\n            if( buffer[x]&lt;32 )\r\n                wprintf(L\"%s%lc%s\",RED,buffer[x]+9216,NORMAL);\r\n            else if( buffer[x]==127 )\r\n                wprintf(L\"%s%lc%s\",RED,9249,NORMAL);\r\n            else if( buffer[x]&gt;127 )\r\n                wprintf(L\"%s%lc%s\",\r\n                        GREEN,\r\n                        extended_ASCII[buffer[x]-128],\r\n                        NORMAL\r\n                       );\r\n            else\r\n                putwchar((wchar_t)buffer[x]);\r\n        }\r\n        putwchar(L'\\n');\r\n        offset += r;\r\n    }\r\n    wprintf(L\" %d total bytes\\n\",offset);\r\n\r\n    return 0;\r\n}<\/pre>\n<p>To test the program, I created a file <code>ASCII.BIN<\/code>, which contains character values 0 through 255. A dump of this file outputs all the values properly output. Figure 1 shows how it looks by using my colorful <em>hexdump<\/em> utility.<\/p>\n<div id=\"attachment_7314\" style=\"width: 594px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-7314\" src=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/12\/1227-figure1-1024x478.png\" alt=\"colortful hexdump output\" width=\"584\" height=\"273\" class=\"size-large wp-image-7314\" srcset=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/12\/1227-figure1-1024x478.png 1024w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/12\/1227-figure1-300x140.png 300w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/12\/1227-figure1-768x358.png 768w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/12\/1227-figure1-500x233.png 500w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/12\/1227-figure1.png 1219w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><p id=\"caption-attachment-7314\" class=\"wp-caption-text\">Figure 1. Output from my <em>hexdump<\/em> utility.<\/p><\/div>\n<p>For contrast, below is output generated by using the traditional <em>hexdump<\/em> utility with the <code>-C<\/code> (canonical) switch active:<\/p>\n<div id=\"attachment_7315\" style=\"width: 594px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-7315\" src=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/12\/1227-figure2-1024x462.png\" alt=\"hexdump output\" width=\"584\" height=\"263\" class=\"size-large wp-image-7315\" srcset=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/12\/1227-figure2-1024x462.png 1024w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/12\/1227-figure2-300x135.png 300w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/12\/1227-figure2-768x347.png 768w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/12\/1227-figure2-500x226.png 500w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2025\/12\/1227-figure2.png 1280w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><p id=\"caption-attachment-7315\" class=\"wp-caption-text\">Figure 2. Output from the traditional <em>hexdump<\/em> utility.<\/p><\/div>\n<p>As you can see by comparing the two figures, my program doesn&#8217;t exactly match the text output from the traditional <em>hexdump<\/em> utility, which is okay. But I like having characters in the far right column as opposed to dots. Further, I find it helpful to have the colors match the hex bytes as well as their corresponding characters. Some users may feel that this presentation is too busy, but I&#8217;m a fan.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>At long last, here is my colorful version of the <em>hexdump<\/em> utility. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7312\">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-7312","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\/7312","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=7312"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7312\/revisions"}],"predecessor-version":[{"id":7327,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7312\/revisions\/7327"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7312"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7312"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7312"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}