Search code examples
cstrcmpatoistrtol

C - Comparing numeric strings


Out of professional curiosity, what is the safest / fastest / most efficient way to compare two fully numeric strings in C?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void){

char str1[5] = "123";
char str2[5] = "123";
char *ptr;

if(atoi(str1) == atoi(str2))
    printf("Equal strings");

if(strtol(str1,&ptr,10) == strtol(str2,&ptr,10))
    printf("Equal strings");

if(strcmp(str1,str2)==0)
    printf("Equal strings");

return 0;
}

Solution

  • strcmp () in my opinion, as it does not need any numeric conversions. But in this case you need to make sure that one of them stores a string which contains only numeric characters.

    Also you can do memcmp () on the string

    EDIT1

    As pointed out by others about the leading zeros, you can manually scan through the leading zeros and call strcmp () or memcmp () by passing a pointer to the first non-zero digit.

    EDIT2

    The below code tells what i am trying to say. This is only for integers, not for floating point numbers.

    int main (void) {
      char s1[128], s2[128];
      char *p1 = s1, *p2 = s2;
    
      /* populate s1, s2 */
    
      while (*p1 && (*p1 == '0'))
        p1++;
    
      while (*p2 && (*p2 == '0'))
        p2++;
    
      if (strcmp (p1, p2) == 0)
        printf ("\nEqual");
      else
        printf ("\nNot equal");
    
      printf ("\n");
      return 0;
    }
    

    For floating point numbers, the trailing zeros after the decimal point should be chopped out manually.

    Or do the whole stuff manually.

    EDIT4

    I would also like you to have a look at this code for floating point. This will detect leading zeros before the decimal and trailing zeros after the decimal. For example

    00000000000001.10000000000000 and 1.1 will be Equal for the below code

    int main (void) {
      char s1[128], s2[128];
      char *p1, *p2, *p1b, *p2b;
    
      printf ("\nEnter 1: ");
      scanf ("%s", s1);
      printf ("\nEnter 2: ");
      scanf ("%s", s2);
    
      p1 = s1;
      p2 = s2;
      /* used for counting backwards to trim trailing zeros
       * in case of floating point
       */
      p1b = s1 + strlen (s1) - 1;
      p2b = s2 + strlen (s2) - 1;
    
    
      /* Eliminate Leading Zeros */
      while (*p1 && (*p1 == '0'))
        p1++;
    
      while (*p2 && (*p2 == '0'))
        p2++;
    
      /* Match upto decimal point */
      while (((*p1 && *p2) && ((*p1 != '.') && (*p2 != '.'))) && (*p1 == *p2))
      {
        p1++;
        p2++;
      }
    
      /* if a decimal point was found, then eliminate trailing zeros */
      if ((*p1 == '.') && (*p2 == '.'))
      {
        /* Eliminate trailing zeros (from back) */
        while (*p1b == '0')
          p1b--;
        while (*p2b == '0')
          p2b--;
    
        /* match string forward, only upto the remaining portion after
         * discarding of the trailing zero after decimal
         */
        while (((p1 != p1b) && (p2 != p2b)) && (*p1 == *p2))
        {
          p1++;
          p2++;
        }
      }
    
      /* First condition on the LHS of || will be true for decimal portion
       * for float the RHS will be . If not equal then none will be equal
       */
      if (((*p1 == '\0') && (*p2 == '\0')) ||  ((p1 == p1b) && (p2 == p2b)))
        printf ("\nEqual");
      else
        printf ("\nNot equal");
    
      printf ("\n");
      return 0;
    }
    

    Needs some testing before use.