The Core Purpose Of This Article
The core purpose is relatively simple. I want to show how complicated (or not) things are regarding programming and how AI may assist (or not). I think there isn’t a better example than a simple calculator for this. The reader will see how a basic app is built barebones and should understand the “greatness” of more complex things like an OS, etc. You will “witness” the stripped code behind a basic calculator, a simple app that you might use daily, but ignore its “hidden charm.” You will also see if and how AI can assist you in coding, if you have well-built (or not) code. Long story short, while AI might prove to be a helpful assistant, it is still far away from being perfect. “Human intelligence” remains the most effective approach.
The calculator is written in C++, and the GUI is “designed” by Meta’s DeepAI. Why DeepAI instead of ChatGPT? For this article, DeepAI proved to be significantly better than ChatGPT. ChatGPT was making errors that would even render the app unusable. DeepAI wasn’t foolproof, but it managed to keep up with the task under appropriate guidance (and patience). It might not be the best, but it is something. If you would like, you can run the code in any IDE supporting C++ (I use CodeBlocks) and modify it as you wish. Knowledge is power!
JimCKD’s Code
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;int main() {
double firstint, secondint, result;
char operation, redo;cout << “Hello, welcome to JimCKD’s calculator! Please, add the numbers you wish to calculate…” << endl;
do {
cout << endl;
cout << “1st Number:” << endl;
while (!(cin >> firstint)) { // Check for valid first number
cout << “Error, please add a number or an appropriate operation…” << endl;
cin.clear(); // Clear errors
cin.ignore(numeric_limits<streamsize>::max(), ‘\n’); // Ignore incorrect
cout << “1st Number:” << endl;
}cout << “2nd Number:” << endl;
while (!(cin >> secondint)) { // Check for valid second number
cout << “Error, please add a number or an appropriate operation…” << endl;
cin.clear(); // Clear errors
cin.ignore(numeric_limits<streamsize>::max(), ‘\n’); // Ignore incorrect
cout << “2nd Number:” << endl;
}// operation time
do {
cout << “Please, choose a calculation (s for all types, + , – , * , / … )” << endl;
cin >> operation;
if (operation != ‘+’ && operation != ‘-‘ && operation != ‘*’ && operation != ‘/’ && operation != ‘s’) {
cout << “Error, please add a number or an appropriate operation…” << endl;
}
} while (operation != ‘+’ && operation != ‘-‘ && operation != ‘*’ && operation != ‘/’ && operation != ‘s’);switch (operation) {
case ‘+’:
result = firstint + secondint; // result
cout << “Result: ” << result << endl;
break;
case ‘-‘:
result = firstint – secondint; // result 2
cout << “Result: ” << result << endl;
break;
case ‘*’:
result = firstint * secondint; // result 3
cout << “Result: ” << result << endl;
break;
case ‘/’:
if (secondint != 0) {
result = firstint / secondint; // result 4
cout << “Result: ” << result << endl;
} else {
cout << “Error: Division by zero is not allowed.” << endl;
}
break;
case ‘s’:
result = firstint + secondint;
cout << “Result of +: ” << result << “, “;
result = firstint – secondint;
cout << “Result of -: ” << result << “, “;
result = firstint * secondint;
cout << “Result of *: ” << result << “, “;
if (secondint != 0) {
result = firstint / secondint;
cout << “Result of /: ” << result << endl;
} else {
cout << “Result of /: Error (division by zero)” << endl;
}
break;
default:
cout << “Unexpected Error… Please, try again…” << endl;
}cout << “Thank you for using JimCKD’s Calculator… Please, type y to continue/restart or any other key to exit…” << endl;
cin >> redo;// If user types sth other than ‘y’ or ‘Y’, exit.
if (redo != ‘y’ && redo != ‘Y’) {
exit(0); // Exit
}} while (true); // Continue until the break
return 0;
}
Keynotes
- I preferred using namespace std rather than std::cout. Programmers may freely “shoot” me.
- For those who don’t know, // are comments that might be helpful for the programmer or the user. They are not useful for the app’s development, and the compiler will ignore them.
- I attempted to eliminate coding errors, such as infinite execution, especially when a user enters a letter instead of an integer, whether intentionally or not.
- I added the option to start all over again (y) rather than restarting the program.
- It is not bulletproof.
AI-generated GUI (DeepAI)
#define UNICODE
#define _UNICODE#include <windows.h>
#include <sstream>
#include <string>
#include <iomanip> // for fixed and setprecision// Forward declarations
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
LRESULT CALLBACK ContinueInputProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);// Control IDs
#define ID_BTN_CALC 1
#define ID_BTN_EXIT 2
#define ID_CONTINUE_INPUT 3// Global control handles
HWND hwndEdit1, hwndEdit2, hwndOperation, hwndResult, hwndLabel4, hwndContinueInput;
HWND hwndButtonCalc, hwndButtonExit;
WNDPROC OldContinueInputProc; // for subclassing continue input
int resultBoxWidth = 430; // initial width// Helper function to convert double to string without unnecessary zeros
std::wstring DoubleToStringTrim(double value) {
std::wostringstream oss;
oss << std::fixed << std::setprecision(10) << value; // high precision
std::wstring str = oss.str();// Trim trailing zeros
size_t end = str.find_last_not_of(L’0′);
if (end != std::wstring::npos) {
// Remove trailing zeros
str.erase(end + 1);
// If the last character is ‘.’, remove it
if (str.back() == L’.’) {
str.pop_back();
}
} else {
// If all zeros or no decimal part, remove decimal point if exists
size_t dotPos = str.find(L’.’);
if (dotPos != std::wstring::npos) {
str.erase(dotPos);
}
}
return str;
}void ResizeResultBoxIfNeeded(HWND hwndResult, const std::wstring& text) {
const int charWidth = 8; // approximate width per character
int requiredWidth = (int)text.length() * charWidth + 20; // padding
if (requiredWidth > resultBoxWidth) {
RECT rect;
GetWindowRect(hwndResult, &rect);
MapWindowPoints(NULL, GetParent(hwndResult), (LPPOINT)&rect, 2);
MoveWindow(hwndResult, rect.left, rect.top, requiredWidth, rect.bottom – rect.top, TRUE);
resultBoxWidth = requiredWidth;
}
}void ClearInputsAndResult() {
SetWindowTextW(hwndEdit1, L””);
SetWindowTextW(hwndEdit2, L””);
SetWindowTextW(hwndOperation, L””);
SetWindowTextW(hwndResult, L””);
SetWindowTextW(hwndContinueInput, L””);
}void SetContinueControlsVisible(bool visible) {
ShowWindow(hwndLabel4, visible ? SW_SHOW : SW_HIDE);
ShowWindow(hwndContinueInput, visible ? SW_SHOW : SW_HIDE);
}// WinMain
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) {
// Register window class
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszClassName = L”CalculatorClass”;
wc.lpfnWndProc = WindowProcedure;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassExW(&wc);HWND hwnd = CreateWindowExW(
0,
L”CalculatorClass”,
L”JimCKD’s Calculator”,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 550, 370,
NULL, NULL, hInstance, NULL);if (!hwnd) return 0;
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);MSG msg;
while (GetMessageW(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return (int)msg.wParam;
}// Subclass for continue input edit box
LRESULT CALLBACK ContinueInputProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
if (msg == WM_KEYDOWN && wp == VK_RETURN) {
HWND hwndMain = GetParent(hwnd);
PostMessageW(hwndMain, WM_USER + 1, 0, 0);
return 0;
}
return CallWindowProcW(OldContinueInputProc, hwnd, msg, wp, lp);
}// Window procedure
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
static double firstNum, secondNum, result;
static std::wstring operation;switch (msg) {
case WM_CREATE: {
// Create static labels and input boxes
CreateWindowW(L”STATIC”, L”First Number:”, WS_VISIBLE | WS_CHILD, 20, 20, 100, 20, hwnd, NULL, NULL, NULL);
hwndEdit1 = CreateWindowW(L”EDIT”, L””, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 130, 20, 100, 20, hwnd, NULL, NULL, NULL);CreateWindowW(L”STATIC”, L”Second Number:”, WS_VISIBLE | WS_CHILD, 20, 50, 110, 20, hwnd, NULL, NULL, NULL);
hwndEdit2 = CreateWindowW(L”EDIT”, L””, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 130, 50, 100, 20, hwnd, NULL, NULL, NULL);CreateWindowW(L”STATIC”, L”Operation (+, -, *, /, s):”, WS_VISIBLE | WS_CHILD, 20, 80, 180, 20, hwnd, NULL, NULL, NULL);
hwndOperation = CreateWindowW(L”EDIT”, L””, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 200, 80, 50, 20, hwnd, NULL, NULL, NULL);// Buttons
hwndButtonCalc = CreateWindowW(L”BUTTON”, L”Calculate”, WS_VISIBLE | WS_CHILD, 20, 110, 100, 30, hwnd, (HMENU)ID_BTN_CALC, NULL, NULL);
hwndButtonExit = CreateWindowW(L”BUTTON”, L”Exit”, WS_VISIBLE | WS_CHILD, 130, 110, 100, 30, hwnd, (HMENU)ID_BTN_EXIT, NULL, NULL);// Result display static label
CreateWindowW(L”STATIC”, L”Result:”, WS_VISIBLE | WS_CHILD, 20, 150, 50, 20, hwnd, NULL, NULL, NULL);
hwndResult = CreateWindowW(L”STATIC”, L””, WS_VISIBLE | WS_CHILD | WS_BORDER, 80, 150, 430, 20, hwnd, NULL, NULL, NULL);
resultBoxWidth = 430; // initial width// Continue prompt controls
hwndLabel4 = CreateWindowW(L”STATIC”, L””, WS_VISIBLE | WS_CHILD, 20, 200, 400, 20, hwnd, NULL, NULL, NULL);
hwndContinueInput = CreateWindowW(L”EDIT”, L””, WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, 20, 230, 100, 20, hwnd, (HMENU)ID_CONTINUE_INPUT, NULL, NULL);
OldContinueInputProc = (WNDPROC)SetWindowLongPtrW(hwndContinueInput, GWLP_WNDPROC, (LONG_PTR)ContinueInputProc);SetContinueControlsVisible(false);
break;
}
case WM_COMMAND: {
int id = LOWORD(wp);
int event = HIWORD(wp);
if (id == ID_BTN_CALC && event == BN_CLICKED) {
// Get input strings
wchar_t buf1[100], buf2[100], bufOp[100];
GetWindowTextW(hwndEdit1, buf1, 100);
GetWindowTextW(hwndEdit2, buf2, 100);
GetWindowTextW(hwndOperation, bufOp, 100);// Convert to doubles
try {
firstNum = std::stod(std::wstring(buf1));
} catch (…) {
MessageBoxW(hwnd, L”Invalid first number.”, L”Error”, MB_OK | MB_ICONERROR);
return 0;
}
try {
secondNum = std::stod(std::wstring(buf2));
} catch (…) {
MessageBoxW(hwnd, L”Invalid second number.”, L”Error”, MB_OK | MB_ICONERROR);
return 0;
}operation = std::wstring(bufOp);
if (operation != L”+” && operation != L”-” && operation != L”*” && operation != L”/” && operation != L”s”) {
MessageBoxW(hwnd, L”Invalid operation. Use +, -, *, /, or s.”, L”Error”, MB_OK | MB_ICONERROR);
return 0;
}std::wstring resStr;
if (operation == L”+”) {
result = firstNum + secondNum;
resStr = L”Result: ” + DoubleToStringTrim(result);
} else if (operation == L”-“) {
result = firstNum – secondNum;
resStr = L”Result: ” + DoubleToStringTrim(result);
} else if (operation == L”*”) {
result = firstNum * secondNum;
resStr = L”Result: ” + DoubleToStringTrim(result);
} else if (operation == L”/”) {
if (secondNum == 0) {
MessageBoxW(hwnd, L”Division by zero.”, L”Error”, MB_OK | MB_ICONERROR);
return 0;
}
result = firstNum / secondNum;
resStr = L”Result: ” + DoubleToStringTrim(result);
} else if (operation == L”s”) {
std::wstringstream res;
res << L”Addition: ” << DoubleToStringTrim(firstNum + secondNum) << L”, “;
res << L”Subtraction: ” << DoubleToStringTrim(firstNum – secondNum) << L”, “;
res << L”Multiplication: ” << DoubleToStringTrim(firstNum * secondNum);
if (secondNum != 0)
res << L”, Division: ” << DoubleToStringTrim(firstNum / secondNum);
else
res << L”, Division: Error (division by zero)”;resStr = res.str();
}// Show result
SetWindowTextW(hwndResult, resStr.c_str());
ResizeResultBoxIfNeeded(hwndResult, resStr);// Show continue prompt after any calculation
SetContinueControlsVisible(true);
SetWindowTextW(hwndLabel4, L”Enter ‘y’ to continue or any other key to exit:”);
} else if (id == ID_BTN_EXIT && event == BN_CLICKED) {
PostQuitMessage(0);
}
break;
}
case WM_USER + 1: {
// Handle Enter in continue input
wchar_t contInput[100];
GetWindowTextW(hwndContinueInput, contInput, 100);
if (contInput[0] == L’y’ || contInput[0] == L’Y’) {
// Reset inputs
ClearInputsAndResult();
SetContinueControlsVisible(false);
} else {
PostQuitMessage(0);
}
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hwnd, msg, wp, lp);
}
return 0;
}
Keynotes
- DeepAI proved to be far better than ChatGPT for this task. Although it wasn’t the optimal experience, with appropriate guidance and patience, it managed to bring this project to life.
- It is not perfect or the most efficient way, but it just works.
Final Thoughts
As you may see, AI is still far from being perfect enough to trust blindly for coding, but it is at a reasonable level. Things are promising. You may use it as an assistant, but in the end, you can’t trust it blindly or for building an app from scratch (yet). The future is here, though. But what is your opinion on this matter? Would AI be all we need for programming soon, or a helpful assistant? Could Skynet be a possible scenario? Whatever your opinion is, one thing is for sure. AI is here to stay, whether we want it or not. We hope for the best!
Update: Because of some WP limitations, the provided codes might not work as expected. I wrote an explanatory comment, as well. Please, feel free to download and extract the zipped file below, named as files. The correct versions are there (please in the GUI version CreateWindow First number and Second Number delete everything and the space before :). Thanks in advance!
Because of WordPress view of coding, if you face any issues with the code provided, you should replace the ’ with ‘ (as well, ’’ with “) and – with -. It is not a fault by my side, but of WordPress. The code works as it should.