Another implementation of strcmp and strncmp functions

amrith92 0 Tallied Votes 626 Views Share

My implementation of the strcmp and strncmp functions. I don't think that it is very efficient, but have managed to get both the functions' execution times to 0.01 s (At least, this is the value my profiler gives me). Enjoy! :)

/*
    Function(Fn I) compares two strings and
    returns (+1) if s1 > s2, (0) if s1 == s2,
    and (-1) if s1 < s2
    
    Note: (all comparisns are ASCII based)
*/
int aNew_strcmp(const char* s1, const char* s2)
{
    // Stores return value
    int retVal = 0;
    
    // This flag restricts the execution of the loop
    bool fFlag = true;
    
    // While s1 and s2 exist
    while(*s1++ && *s2++ && fFlag)
       (retVal != 0) ? fFlag = false : (*s1 > *s2) ? ++retVal : (*s1 < *s2) ? --retVal : retVal = retVal;
       /* What the above statement does:
               
          Condition 1:
                    
            retVal, if it has been modified to a value not equal to 0, then terminate the loop
            by setting the flag to be false. This will restrict the value retVal to 0, 1, or -1.
                       
          Condition 2:
                    
            If the (Condition 1) fails, then it checks whether the current character pointed by
            s1 is > the current character pointed by s2. If true, then increment value of retVal.
                       
          Condition 3:
            If (Condition 1) and (Condition 2) both fail, then decrement the value of retVal.
            If this condition fails as well, then leave retVal alone (as *s1 == *s2).
       */
    
    // Return retVal, which can be 0, 1, or -1
    return retVal;
}

/*
    Function(Fn II) compares two strings until
    (s1 or s2) terminates or uptil 'num' number of characters, &
    returns (+1) if s1 > s2, (0) if s1 == s2,
    and (-1) if s1 < s2
    
    Note: (all comparisns are ASCII based)
*/
int aNew_strncmp(const char* s1, const char* s2, int num)
{
    // Stores return value
    int retVal = 0;
    
    // This flag restricts the execution of the loop
    bool fFlag = true;
    
    while(*s1++ && *s2++ && --num > 0 && fFlag)
       (retVal != 0) ? fFlag = false : (*s1 > *s2) ? ++retVal: (*s1 < *s2) ? --retVal : retVal = retVal;
       // refer to the function above
    
    // Return retVal, which can be 0, 1, or -1
    return retVal;
}

Dani AI

Generated

Short, practical note about the two implementations in this thread.

The version posted by has a subtle pointer‑increment bug: the loop advances the pointers while checking the condition and then dereferences them inside the body, so the first character(s) end up being skipped and some comparisons can be wrong (for example, two one‑character strings that differ may be treated as equal). The heavy ternary nesting and a boolean flag make the control flow hard to follow and fragile. The compact alternative from is elegant, but it omits safety considerations (NULL checks and signedness) that matter in portable code.

Concrete correctness and portability tips

  • Compare bytes as unsigned values: cast to unsigned char before subtracting or comparing to avoid surprises on platforms where char is signed.
  • Use size_t for length limits in strncmp and treat n == 0 as immediate equality.
  • Standard strcmp/strncmp are undefined for NULL pointers; add checks only if your API must accept NULL.
  • If you want a normalized -1/0/+1 result, use the idiom (a > b) - (a < b); otherwise the standard returns any negative/zero/positive value (often the byte difference).

A clear, portable implementation (unsigned comparisons, size_t for the limit, normalized return):

#include <stddef.h>

int safe_strcmp(const char *s1, const char *s2)
{
    const unsigned char *a = (const unsigned char *)s1;
    const unsigned char *b = (const unsigned char *)s2;
    while (*a != '\0' && *a == *b) {
        ++a; ++b;
    }
    return (*a > *b) - (*a < *b);
}

int safe_strncmp(const char *s1, const char *s2, size_t n)
{
    if (n == 0) return 0;
    const unsigned char *a = (const unsigned char *)s1;
    const unsigned char *b = (const unsigned char *)s2;
    while (n-- > 1 && *a != '\0' && *a == *b) {
        ++a; ++b;
    }
    return (*a > *b) - (*a < *b);
}

Testing and perf notes: unit test equal strings, differing first byte, differing later byte, prefix vs longer string, n == 0, and non‑ASCII bytes. For high‑volume or binary comparisons consider memcmp or compiler intrinsics and profile with realistic inputs before micro‑optimizing.

tux4life 2,072 Postaholic

strcmp can also be written like this :D:

int strcmp(const char *s1, const char *s2) {
    while( ( *s1 && *s2 ) && ( *s1++ == *s2++ ) );
    return *( --s1 ) - *( --s2 );
}

However, I didn't include code to avoid a NULL-pointer in my code, but it might be wise to do so as well :)

amrith92 119 Junior Poster

Wow! Good code :) beats mine by a mile... :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.