From Switch-Case to Signals: My Journey Building a GTK Calculator in C

I have been brushing up my C concepts through The C language course by PyjamaBrah. In one of the sections, Piyush showed a basic CLI calculator that used a switch-case to evaluate the result of two operands and an operator.

Here’s what it looked like:

scanf("%f", &input1);
scanf("%f", &input1);
scanf("%c", &op);
switch (op){
	case '-':
		....
	case '+':
		...
	case '*':
		...
	case '/':
		...
}

Of course, this was just meant to demonstrate switch. So ..

  • No input validation (wrong input? crash.)
  • And definitely no support for full expressions like 3 + 5 * 2
  • Only decimal and floating point calculations

That got me thinking: how big is the gap between this and a basic GUI calculator?


Goals: What I Wanted My Calculator to Do

Before diving into code, I set some ground rules. My calculator should:

  1. Handle full expressions using BODMAS
  2. Gracefully handle invalid inputs
  3. Have a working GUI
  4. Be modular enough to add new operators easily in the future

Expressions, RPN & Shunting Yard

If you look up how calculators handle expression parsing, you’ll quickly run into a few terms:

  • Infix (e.g., 3 - 5 / 2) — what humans use
  • Postfix aka Reverse Polish Notation (RPN) (e.g., 3 5 2 / -) — what computers prefer
  • Shunting Yard Algorithm — invented by Dijkstra, used to convert infix to postfix

Why postfix? Because it lets you evaluate expressions without worrying about parentheses or operator precedence — you just process the tokens left to right using a stack.

If you’ve never heard of this, this video explains it well. Comp Sci in 5: Shunting Yard Algorithm - YouTube


Structs, Enums, and Stacks — Building the Engine

To implement all this in C, I needed to mimic:

  • A stack for operators
  • A queue for output
  • And a way to represent both operands and operators using enum + struct

Here’s the rough structure of the core:
core structure

With the tokenizer, RPN creator, and evaluator in place, I now had a CLI-based calculator that could handle proper math expressions.

Here's the first working version:
Initial program


Next Step: A GUI

I’ve never built GUI apps before, but I wanted something that felt “real.” I checked how GNOME Calculator worked and saw it used GTK. That seemed like a good path to follow.

So I installed GTK and started playing around.


Designing the UI: Glade to the Rescue

GTK lets you build UIs in two ways:

  1. Manually create widgets in C
  2. Use a UI definition file (.ui) written in XML

Even a simple calculator UI can get bloated fast. Creating each button and setting its properties in C would be a nightmare. So I used Glade — a drag-and-drop GUI builder that outputs ui.glade files for GTK.

Here’s what the initial UI skeleton looked like:
Initial program


Connecting Logic to UI

Once the layout was ready, I had to:

  • Load the .ui file using GtkBuilder
  • Connect buttons and keyboard inputs to callback functions
  • Wire up input/output using GtkEntry and GtkTextView

At this point, the UI was interactive but didn't actually evaluate anything.


Hooking Up the Backend

Now came the cool part: plug the CLI logic into the GUI.

Instead of reading from stdin, the evaluator now takes input from the GtkEntry when the user presses = or hits Enter. If the input is valid, we show the result in the same entry. If it’s not, the error goes to a GtkTextView.

Everything else stayed pretty much the same — just more visual.


Final Overview

Here’s how the calculator works under the hood:
Initial program


What I Learned

  • You can mimic OOP's concepts using structs, function pointers and opaque types.
  • Even though frameworks like GTK abstract away large part of GUI development, it's still complicated due to how elements interact with each other.
  • Spending some time to setup debug logs, and build automation (makefile/Cmake) saves a ton of time in long run.
  • Valgrind makes Segfualts feel less painful.

Possible Next Steps

  • Add expression history
  • Fix memory leaks that I ignored

For anyone interested here's link to source code