{"id":9145,"date":"2026-01-29T11:39:34","date_gmt":"2026-01-29T19:39:34","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=9145"},"modified":"2026-01-29T19:40:23","modified_gmt":"2026-01-30T03:40:23","slug":"using-ai-to-simplify-c-c-code","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/ai\/thermostat\/04-simplifying\/","title":{"rendered":"Using AI to Simplify C\/C++ Code"},"content":{"rendered":"<p>This tutorial continues the series where we are using AI to turn a third-party <a href=\"https:\/\/gitlab.com\/slimhazard\/picow-http-example\">open-source HTTP server for Raspberry Pi Pico<\/a> into a smart thermostat. In the <a href=\"https:\/\/visualgdb.com\/tutorials\/ai\/thermostat\/03-adding-similar-code\">previous tutorial<\/a> we created functions for processing API calls from the browser, and invoking thermostat functions. However, this produced some duplicate code that can be simplified. In this tutorial we will use AI to refactor commonly used logic into separate functions, and will update the callers to use it.<\/p>\n<p>Before you begin this tutorial, follow the previous one, or check out the <strong>04-simplifying <\/strong>tag from the <a href=\"https:\/\/gitlab.com\/sysprogs-tutorials\/picow-http-example\">tutorial repository<\/a>.<\/p>\n<ol>\n<li>First of all, create files called <strong>http_utils.c<\/strong> and <strong>http_utils.h<\/strong> in the src directory and make sure the source file includes the header file:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/01-newfile.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9146\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/01-newfile.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/01-newfile.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/01-newfile-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/01-newfile-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/01-newfile-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/li>\n<li>If you take even a brief look at the <a href=\"https:\/\/gitlab.com\/sysprogs-tutorials\/picow-http-example\/-\/commit\/439013bc3c9e4b1863b58fcdc268700a0d1356db\"><strong>settemp_handler()<\/strong> function<\/a>, you will notice that more than half of it is dealing with getting an int32 out of the HTTP query string. It would make the main function much more readable, if instead of 3 function calls and 2 extra checks it just called something like\u00a0<strong>http_req_query_int()<\/strong>. AI can do this very easily if you start editing <strong>settemp_handler()<\/strong> and use this prompt:\n<pre>+http_req_query_int() in @http_utils.c &amp; use it<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/02-query-int.png\"> <img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9147\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/02-query-int.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/02-query-int.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/02-query-int-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/02-query-int-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/02-query-int-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/li>\n<li>Several seconds after we have the first draft:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/03-impl.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9148\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/03-impl.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/03-impl.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/03-impl-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/03-impl-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/03-impl-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a>While it does technically work, it has copied 2 inefficiencies from the original design: explicitly specified length of the field (e.g. 4 for &#8220;temp&#8221;) and an extra check for the result length.<\/li>\n<li>This can be fixed with a refinement prompt:\n<pre>no name_len arg\r\nenum kMaxIntLength inside func + single check on it<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/04-fix.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9149\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/04-fix.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/04-fix.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/04-fix-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/04-fix-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/04-fix-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/li>\n<li>Two seconds later the AI has applied the fixes, updating the function, the declaration and the call:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/05-fixed.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9150\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/05-fixed.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/05-fixed.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/05-fixed-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/05-fixed-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/05-fixed-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a>You can always brush it up further (e.g. using sizeof(temp_str) instead of the constant), but letting the AI do the bulk of the work is always faster than doing it by hand.<\/li>\n<li>The next huge redundancy is the way the handler functions send the HTTP replies. This requires <a href=\"https:\/\/gitlab.com\/sysprogs-tutorials\/picow-http-example\/-\/commit\/20857876f8f0899c20e3324f8a76af4595c935e9#line_3a4342a2a_651\">separate function calls<\/a> for formatting the reply, setting content type, cache policy, etc. This should be easily doable with one function call, and the AI can do that refactoring. Start another editing session with settemp_handler() and use this prompt:\n<pre>+http_format_and_send() with varargs in @http_utils.c . take contentType + enum http_format_flags (ffNoCache).\r\nmeasure with sprintf, then @pvPortMalloc + send + @vPortFree<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/06-send.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9151\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/06-send.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/06-send.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/06-send-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/06-send-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/06-send-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a>If <strong>pvPortMalloc()<\/strong> and <strong>pvPortFree()<\/strong> are not shown in the suggestion popups as you type the prompt, include &#8220;FreeRTOS.h&#8221; from the beginning of the file.<\/li>\n<li>Since VisualGDB automatically pulled all relevant declarations into the context window, the model had no problem getting a working function from the first try:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/07-simplified.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9152\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/07-simplified.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/07-simplified.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/07-simplified-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/07-simplified-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/07-simplified-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a>You may need to manually adjust includes (e.g. LLMs tend to include <strong>portable.h<\/strong> that defines <strong>pvPortMalloc()<\/strong> instead of <strong>FreeRTOS.h <\/strong>that has other definitions), but for the function itself should be just fine.<\/li>\n<li>Now we can start updating other functions. Without finishing the AI session, add<strong> getconfig_handler()<\/strong> to the context window and say &#8220;use here&#8221; in the prompt:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/08-func2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9153\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/08-func2.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/08-func2.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/08-func2-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/08-func2-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/08-func2-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/li>\n<li>You can do the same for the <a href=\"https:\/\/gitlab.com\/sysprogs-tutorials\/picow-http-example\/-\/commit\/20857876f8f0899c20e3324f8a76af4595c935e9\">other functions<\/a> that send the reply. Add them in the next steps (one per step, or all of them together) and the model should figure it out even without any prompt:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/09-further.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9154\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/09-further.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/09-further.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/09-further-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/09-further-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/09-further-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a>Note that continuing the same AI session would re-send all the previous conversation to the langauge model. It will give it more context (the exact edits it performed), but will require more time. Starting a new session would work faster, but the AI will have to guess what to do based on the declaration of <strong>http_format_and_send()<\/strong> and the preceding comments.<\/li>\n<li>You can use AI to brush up the code further. E.g. rssi_handler() relies on a couple of external variables that can be inlined:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/10-inline.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9155\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/10-inline.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/10-inline.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/10-inline-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/10-inline-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/10-inline-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/li>\n<li>A simple prompt of &#8220;inline fmt + use ?: for str&#8221; makes it a bit more readable in under 2 seconds:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/11-inlined.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9156\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/11-inlined.png\" alt=\"\" width=\"1216\" height=\"767\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/11-inlined.png 1216w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/11-inlined-300x189.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/11-inlined-1024x646.png 1024w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2026\/01\/11-inlined-768x484.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/a><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial continues the series where we are using AI to turn a third-party open-source HTTP server for Raspberry Pi<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[253],"tags":[254,133,231],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/9145"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=9145"}],"version-history":[{"count":3,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/9145\/revisions"}],"predecessor-version":[{"id":9159,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/9145\/revisions\/9159"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=9145"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=9145"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=9145"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}