7

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;
}
Valdogg21
  • 1,151
  • 4
  • 14
  • 24
  • What exactly do you mean by "comparison"? Your example contains only the `==` operator, but not `<`. Please give more examples. – Roland Illig Jul 29 '21 at 07:06

6 Answers6

9

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.

phoxis
  • 60,131
  • 14
  • 81
  • 117
  • Thank you. This is the method I always use, as I rely on the str* family of functions a lot. Looks like it's actually the norm. Good to know! – Valdogg21 Jun 17 '11 at 18:59
  • @Valdogg21: have a look at the code i updated, this now can compare floating point numbers, as per the protocol you have set. – phoxis Jun 17 '11 at 19:12
4

str(n)cmp is the fastest and safest.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • 2
    `str(n)cmp` fails on integer strings with a differing number of leading zeros. – JAB Jun 17 '11 at 18:12
  • 1
    @JAB: are you saying that the strings "002" and "0002" are the same? – Chris Eberle Jun 17 '11 at 18:14
  • @cnicutar: What are you talking about? I was referring to a situation such as comparing `100` and `0100`. The comparison will fail because both `strcmp` and `strncmp` would return non-zero values when the desired value would be 0, indicating equality. – JAB Jun 17 '11 at 18:15
  • @Chris: No, I'm saying that the numbers represented by the strings "002" and "0002" are the same. – JAB Jun 17 '11 at 18:15
  • I thought you were thinking of something else :-) Indeed, I wasn't thinking about leading zeros. – cnicutar Jun 17 '11 at 18:16
  • @JAB: I sure hope you're talking about the bit values, because the strings "100" and "0100" are emphatically NOT the same. – Chris Eberle Jun 17 '11 at 18:16
  • These are string comparisons, not numeric. I mean I see in his example that it's "123", but these are still string operations. – Chris Eberle Jun 17 '11 at 18:16
  • @Chris: Note the part saying "two fully numeric strings". – JAB Jun 17 '11 at 18:21
  • @JAB: D'oh. See figure of foot in mouth for further details. – Chris Eberle Jun 17 '11 at 19:20
0

Assuming you are looking for them to be idential, strncmp will be the fastest and safest since it can do a direct comparison without any conversions. It is also generally considered safer than strcmp.

However, if you want 00 and 0 to be equal, or other ways that you can represent the same number slightly differently, you will need to use atoi.

Alan Geleynse
  • 24,821
  • 5
  • 46
  • 55
-1

In my opinion, the "safest" way would likely be to convert both arguments to integers and then test, as that way you'll avoid the potential leading-zeros problem. It's probably not the fastest or most efficient method, though.

JAB
  • 20,783
  • 6
  • 71
  • 80
-1

You can simply use following :

if(strcmp("123","123") == 0)

{

  printf("The strings are equal");

}

else

{

  printf("The strings are not equal.");

}

In my opinion it should work.

Sanjay Rajpal
  • 498
  • 5
  • 4
-1

I suggest this way for integers:

int strcmp_for_integers(char *aa, char *bb){
    char aa2[11] = "";
    char bb2[11] = "";
    int answer;

    sprintf(aa2, "%010d", atoi(aa));
    sprintf(bb2, "%010d", atoi(bb));
    answer = strcmp(aa2, bb2);

    return answer;
}