Industrial manufacturing
Industrial Internet of Things | Industrial materials | Equipment Maintenance and Repair | Industrial programming |
home  MfgRobots >> Industrial manufacturing >  >> Industrial programming >> C Language

Four Proven Patterns for User‑Defined Functions in C

Four Proven Patterns for User‑Defined Functions in C

Explore four distinct ways to implement a user‑defined function that checks whether a number is prime, and learn which approach offers the greatest clarity and reusability.

Below, four complete programs demonstrate how the same logical task can be expressed with different function signatures. All four outputs are identical, yet the design choices vary, illustrating key trade‑offs in function design.


Example 1: No Arguments, No Return Value

#include <stdio.h>

void checkPrimeNumber();

int main()
{
    checkPrimeNumber();    // argument is not passed
    return 0;
}

// return type is void meaning it doesn't return any value
void checkPrimeNumber()
{
    int n, i, flag = 0;

    printf("Enter a positive integer: ");
    scanf("%d",&n);

    for(i=2; i <= n/2; ++i)
    {
        if(n%i == 0)
        {
            flag = 1;
        }
    }
    if (flag == 1)
        printf("%d is not a prime number.", n);
    else
        printf("%d is a prime number.", n);
}

The checkPrimeNumber() function is responsible for reading user input, performing the prime test, and printing the result. Because its return type is void, it communicates the outcome solely through side effects.


Example 2: No Arguments, But a Return Value

#include <stdio.h>
int getInteger();

int main()
{
    int n, i, flag = 0;

    // no argument is passed
    n = getInteger();    

    for(i=2; i<=n/2; ++i)
    {
        if(n%i==0){
            flag = 1;
            break;
        }
    }

    if (flag == 1)
        printf("%d is not a prime number.", n);
    else
        printf("%d is a prime number.", n);

    return 0;
}

// returns integer entered by the user
int getInteger()       
{
    int n;

    printf("Enter a positive integer: ");
    scanf("%d",&n);

    return n;
}

Here, getInteger() encapsulates the input routine and returns the value to main, which then handles the prime‑checking logic. This separation makes the input step reusable across different contexts.


Example 3: Argument Passed, No Return Value

#include <stdio.h>
void checkPrimeAndDisplay(int n);

int main()
{
    int n;

    printf("Enter a positive integer: ");
    scanf("%d",&n);

    // n is passed to the function
    checkPrimeAndDisplay(n);

    return 0;
}

// return type is void meaning it doesn't return any value
void checkPrimeAndDisplay(int n) 
{
    int i, flag = 0;

    for(i=2; i <= n/2; ++i)
    {
        if(n%i == 0){
            flag = 1;
            break;
        }
    }
    if(flag == 1)
        printf("%d is not a prime number.",n);
    else
        printf("%d is a prime number.", n);
}

In this pattern, the responsibility of displaying the result is shifted into the helper function. While this keeps main lean, the function now couples the algorithm with I/O, reducing its reusability.


Example 4: Argument Passed and a Return Value

#include <stdio.h>
int checkPrimeNumber(int n);

int main()
{
    int n, flag;

    printf("Enter a positive integer: ");
    scanf("%d",&n);

    // n is passed to the checkPrimeNumber() function
    // the returned value is assigned to the flag variable
    flag = checkPrimeNumber(n);

    if(flag == 1)
        printf("%d is not a prime number",n);
    else
        printf("%d is a prime number",n);

    return 0;
}

// int is returned from the function
int checkPrimeNumber(int n)
{
    int i;

    for(i=2; i <= n/2; ++i)
    {
        if(n%i == 0)
            return 1;
    }

    return 0;
}

This design keeps the algorithm isolated and returns a simple status flag. The caller decides how to present the result, which makes the function highly reusable in libraries or larger applications.


Choosing the Optimal Pattern

While all four implementations produce the same output, the most maintainable and testable approach is Example 4: passing the number as an argument and returning a Boolean‑style flag. This pattern adheres to the single‑responsibility principle, allows unit testing of checkPrimeNumber without I/O dependencies, and can be easily integrated into more complex systems.

Ultimately, the choice depends on your project’s architecture. If the function must interact directly with the user, Example 3 might suffice. For library code or services where I/O is handled elsewhere, Example 4 offers the greatest flexibility.


C Language

  1. C++ Default Function Arguments: How They Work & Best Practices
  2. C Data Types Explained: int, float, char, and More – A Complete Guide
  3. Mastering C Programming Operators: A Comprehensive Guide
  4. Mastering User-Defined Functions in C: A Step‑by‑Step Guide
  5. Master C Functions: Practical Examples of Recursion & Inline Techniques
  6. Pointers in C: A Comprehensive Guide to Types, Usage, and Best Practices
  7. Function Pointers in C: Practical Examples and Best Practices
  8. Mastering C Functions: Structure, Declaration, and Best Practices
  9. Mastering PWM in Arduino: Comprehensive Guide & Key Functions
  10. Differential Types Explained: Functions & Benefits for Vehicles