When you first begin modularizing your pattern programs using functions, you naturally start by passing a single argument—usually representing the number of rows or the size of the shape. While this is a massive upgrade from monolithic code, it still leaves your functions somewhat rigid. What if you want to print a rectangle instead of a square, requiring separate height and width parameters? What if you want to swap out the classic star (*) for a hash (#), a dollar sign ($), or even a letter?
To build truly versatile, enterprise-grade utility functions in C, you need to master passing multiple parameters to control dimensions and characters dynamically. In this post, we will explore how to design flexible pattern functions that accept height, width, and custom symbols as arguments.
1. The Limitations of Single-Parameter Functions
Consider a standard function designed to print a square:
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("* ");
}
printf("\n");
}
}
While printSquare(5) works fine, it forces a strict $5 \times 5$ grid using only asterisks. It cannot handle rectangles (where height $\neq$ width), nor can it adapt if your user interface requires a different rendering character.
By expanding our parameter list, we hand complete control over to the caller.
2. Designing a Multi-Parameter Function
To make our pattern generator fully dynamic, our function signature needs to accept three distinct arguments:
int height: Controls the vertical scope (number of outer loop iterations / rows).int width: Controls the horizontal scope (number of inner loop iterations / columns).char symbol: The character used to render the pattern itself.
Code Implementation: Dynamic Rectangle Generator
// Function that accepts height, width, and a custom symbol
void printRectangle(int height, int width, char symbol) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
printf("%c ", symbol);
}
printf("\n");
}
}
int main() {
// Printing a 3x6 grid using '#'
printf("Rectangle 1 (#):\n");
printRectangle(3, 6, '#');
printf("\n");
// Printing a 4x4 grid using '$'
printf("Rectangle 2 ($):\n");
printRectangle(4, 4, '$');
return 0;
}
Output
# # # # # #
# # # # # #
# # # # # #
Rectangle 2 ($):
$ $ $ $
$ $ $ $
$ $ $ $
$ $ $ $
3. Applying Dynamic Arguments to Triangles
Triangles present a unique challenge because their width changes dynamically depending on the row. However, we can still use parameters to control the total height and the rendering symbol.
Code Implementation: Custom Triangle
#include <stdio.h>
void printCustomTriangle(int height, char symbol) {
for (int i = 1; i <= height; i++) {
// Inner loop runs up to 'i', scaling width with the row
for (int j = 1; j <= i; j++) {
printf("%c ", symbol);
}
printf("\n");
}
}
int main() {
int rows = 4;
printf("Triangle using '&':\n");
printCustomTriangle(rows, '&');
return 0;
}
Output
&
& &
& & &
& & & &
Best Practices for Parameterized Functions
Use Descriptive Parameter Names: When writing functions with multiple arguments like
printShape(int h, int w, char s), it is easy to mix up the order. Use clear names likeheight,width, andsymbolto make your code self-documenting.Validate Your Inputs: Always guard against invalid arguments (such as negative heights or widths) by adding simple validation checks at the beginning of your function:
printf("Error: Dimensions must be greater than zero.\n"); return; }Leverage Character Literals: Remember to pass characters using single quotes (e.g.,
'*','@') when calling your functions, as characters in C are processed as ASCII integer values under the hood.
By passing height, width, and symbols dynamically, you transform rigid, hardcoded scripts into flexible, reusable building blocks. This modular mindset is an essential trait of professional C software engineering!
For all Pattern Programs list click here:
…till the next post, bye-bye & take care
