Classes in C with struct: solved exercise step by step
If you are searching for classes in C with struct, this guide shows a practical object-like pattern in plain C: struct + functions + separated files.
The goal is to simulate encapsulation and clean responsibilities without native OOP features.
Problem statement
Design a Cuenta module that:
- defines an entity with owner name and balance,
- exposes functions to create, deposit, withdraw, and print state,
- separates interface (
cuenta.h) and implementation (cuenta.c), - uses
main.cto test the full workflow.
C solution
cuenta.h
#ifndef CUENTA_H
#define CUENTA_H
typedef struct {
char titular[64];
double saldo;
} Cuenta;
Cuenta cuenta_crear(const char *titular, double saldo_inicial);
int cuenta_depositar(Cuenta *c, double importe);
int cuenta_retirar(Cuenta *c, double importe);
void cuenta_imprimir(const Cuenta *c);
#endifcuenta.c
#include "cuenta.h"
#include <stdio.h>
#include <string.h>
Cuenta cuenta_crear(const char *titular, double saldo_inicial) {
Cuenta c;
strncpy(c.titular, titular, sizeof(c.titular) - 1);
c.titular[sizeof(c.titular) - 1] = '\0';
c.saldo = (saldo_inicial >= 0.0) ? saldo_inicial : 0.0;
return c;
}
int cuenta_depositar(Cuenta *c, double importe) {
if (!c || importe <= 0.0) return 0;
c->saldo += importe;
return 1;
}
int cuenta_retirar(Cuenta *c, double importe) {
if (!c || importe <= 0.0 || importe > c->saldo) return 0;
c->saldo -= importe;
return 1;
}
void cuenta_imprimir(const Cuenta *c) {
if (!c) return;
printf("Owner: %s | Balance: %.2f\n", c->titular, c->saldo);
}main.c
#include "cuenta.h"
#include <stdio.h>
int main(void) {
Cuenta c = cuenta_crear("Rodrigo", 1000.0);
cuenta_imprimir(&c);
cuenta_depositar(&c, 250.0);
cuenta_retirar(&c, 400.0);
cuenta_imprimir(&c);
if (!cuenta_retirar(&c, 2000.0)) {
printf("Withdrawal rejected due to insufficient funds.\n");
}
return 0;
}Build:
gcc -Wall -Wextra -std=c11 main.c cuenta.c -o cuenta_demoExpected output
Owner: Rodrigo | Balance: 1000.00
Owner: Rodrigo | Balance: 850.00
Withdrawal rejected due to insufficient funds.Common mistakes
- Putting all business logic in
main.cand losing modularity. - Skipping pointer and amount validation.
- Copying strings without bounds checks.
- Assuming this is full OOP: C still has no native inheritance or methods.
Practical use
This pattern helps you:
- design maintainable C modules,
- separate public API from implementation details,
- build cleaner foundations for larger projects.
It is a practical way to get object-like structure while staying in idiomatic C.
Recommended next exercise
- Struct in C: solved exercise with arrays of structures
- Malloc and free in C: solved exercises
- Pointer to pointer in C: solved exercise with reference updates
- All C exercises
Guided practice and next step
If you want a complete path with progressive difficulty:
FAQ
Can you build real object-oriented design in C?
Not natively. You can simulate parts of it with struct, function APIs, and pointers, but there is no built-in inheritance or method system.
Why separate .h and .c in this exercise?
Because it improves maintainability, reuse, and clarity of the module public contract.
Is this pattern useful for interviews or only large projects?
Both. In interviews it shows structured thinking, and in production it prevents monolithic code.