【问题标题】:C - Comparing numeric stringsC - 比较数字字符串
【发布时间】:2011-09-17 09:49:55
【问题描述】:

出于专业的好奇,在 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;
}

【问题讨论】:

  • “比较”到底是什么意思?您的示例仅包含 == 运算符,但不包含 &lt;。请举出更多例子。

标签: c strcmp atoi strtol


【解决方案1】:

strcmp () 在我看来,因为它不需要任何数字转换。但在这种情况下,您需要确保其中一个存储一个仅包含数字字符的字符串。

你也可以在字符串上做memcmp ()

EDIT1

正如其他人关于前导零的指出,您可以手动扫描前导零并通过将指针传递给第一个非零数字来调用 strcmp ()memcmp ()

EDIT2

下面的代码告诉我想说什么。这仅适用于整数,不适用于浮点数。

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;
}

对于浮点数,应手动删除小数点后的尾随零。

或者手动完成所有工作。

EDIT4

我还希望你看看这个浮点代码。这将检测小数点前的前导零和小数点后的尾随零。例如

00000000000001.100000000000001.1 将是 Equal 用于以下代码

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;
}

使用前需要进行一些测试。

【讨论】:

  • 谢谢。这是我一直使用的方法,因为我非常依赖 str* 系列函数。看起来这实际上是常态。很高兴知道!
  • @Valdogg21:看看我更新的代码,现在可以根据您设置的协议比较浮点数。
【解决方案2】:

str(n)cmp 是最快最安全的。

【讨论】:

  • str(n)cmp 在具有不同数量前导零的整数字符串上失败。
  • @JAB:你是说字符串“002”和“0002”是一样的吗?
  • @cnicutar:你在说什么?我指的是比较1000100这样的情况。比较将失败,因为strcmpstrncmp 在所需值为 0 时返回非零值,表示相等。
  • @Chris:不,我是说字符串“002”和“0002”所代表的数字是一样的。
  • 我以为你在想别的东西 :-) 事实上,我并没有考虑前导零。
【解决方案3】:

假设您正在寻找它们是相同的,strncmp 将是最快和最安全的,因为它可以进行直接比较而无需任何转换。它通常也被认为比strcmp 更安全。

但是,如果您希望 000 相等,或者以其他方式表示相同的数字略有不同,则需要使用 atoi

【讨论】:

  • " atoi() 函数已被 strtol() 弃用,不应在新代码中使用。"
【解决方案4】:

在我看来,“最安全”的方法可能是将两个参数都转换为整数然后进行测试,因为这样可以避免潜在的前导零问题。不过,这可能不是最快或最有效的方法。

【讨论】:

  • 要正确执行此操作,您需要一个任意大小的整数类型,这在标准 C 中不可用。
【解决方案5】:

您可以简单地使用以下内容:

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

{

  printf("The strings are equal");

}

其他

{

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

}

在我看来它应该可以工作。

【讨论】:

  • 询问者想要匹配字符串中表示的两个数字是否相等
【解决方案6】:

我建议对整数采用这种方式:

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;
}

【讨论】:

  • atoi 已弃用
猜你喜欢
  • 2021-11-19
  • 2016-02-08
  • 2013-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-06
相关资源
最近更新 更多