使用C中的三元运算符进行版本字符串比较

时间:2014-12-23 14:39:04

标签: c ternary-operator

我需要比较两个"版本"可能会或可能不会以.0结尾的字符串,以便(例如)10.3.8.9.210.3.8.9.2.0被认为是相等的。

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

int main()    
{

   char str1[20];
   char str2[20];
   int ret;

   strcpy(str1, "10.3.8.9.2");
   strcpy(str2, "10.3.8.9.2.0");
   // strcpy(str2, "10.3.8.9.20.0");  This case are invalid case and need to handle properly inside ternary operator

   ret=(strlen(str1)> strlen(str2))? strncmp( str1,str2,strlen(str2)):(strncmp( str1,str2,strlen(str1))&&( strlen(str2)==strlen(str1)+2 ));

   //printf("ret=%d", ret);

   //ret=(strlen(str1)> strlen(str2))? strncmp( str1,str2,strlen(str2)):(strncmp( str1,str2,strlen(str1)));

   printf("ret_value=%d", ret);

   return 0;

}

上面的代码将10.3.8.9.210.3.8.9.20.0视为相等,这是不正确的。我尝试更新代码,如下所示,但由于strncmp()成功返回0,因此无法提供所需的结果。

似乎我没有在三元运算符内正确处理这个条件。可能是将两个表达式的返回值存储在单独的变量中可以解决此问题,但是想知道如何使用三元运算符实现这一点。

4 个答案:

答案 0 :(得分:1)

您需要首先比较str1str2的最短公共子字符串,然后检查每个字符串的剩余部分。这是一个不使用三元运算符进行字符串比较的解决方案:

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

int compare_versions(const char *a, const char *b)
{

    size_t len1, len2, shortest;

    // Return a negative value for invalid inputs.
    if (!a || !b) { return -1; }

    //First, get the length of the shortest string.
    len1 = strlen(a);
    len2 = strlen(b);
    shortest = len1 < len2 ? len1 : len2;

    // If the first sections of the strings are different, they do not match.    
    if (strncmp(a, b, shortest) != 0) { return 0; }

    // Otherwise, check each string: if an "extension" exists, it must be ".0".
    if (a[shortest] && strcmp(&a[shortest], ".0") != 0) { return 0; }
    if (b[shortest] && strcmp(&b[shortest], ".0") != 0) { return 0; }

    // If both strings end with ".0" or nothing, they match.
    return 1;

}

int main(int argc, char *argv[])    
{
    printf("Return value: %d\n", compare_versions("10.3.8.9.2", "10.3.8.9.2"));
    printf("Return value: %d\n", compare_versions("10.3.8.9.2.0", "10.3.8.9.2.0"));
    printf("Return value: %d\n", compare_versions("10.3.8.9.2.0", "10.3.8.9.2"));
    printf("Return value: %d\n", compare_versions("10.3.8.9.2", "10.3.8.9.2.0"));
    printf("Return value: %d\n", compare_versions("10.3.8.9.20", "10.3.8.9.2"));
    return 0;
}

您可以在线here运行上述代码。如果你真的需要使用三元运算符,可以重新组织字符串比较逻辑,但我不确定它是否可读。

答案 1 :(得分:1)

你可以试试这个:

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

int main()
{
   int a[10],b[10];

   char str1[20];
   char str2[20];

   int kase;
   printf("Enter number of cases : ");
   scanf("%d",&kase);
   getchar();

   while(kase--)
   {
       // initialize array values to 0 if you have to do this checking more than once
       memset(a,0,sizeof(a));
       memset(b,0,sizeof(b));

       //strcpy(str1, "10.3.8.09.2.0");
       //strcpy(str2, "10.3.8.9.02.0");
       printf("Enter first string : ");
       gets(str1);
       printf("Enter second string : ");
       gets(str2);

       int ind1=0,ind2=0;

       char *token=strtok(str1,".");
       while(token!=NULL)
       {
           a[ind1++]=atoi(token); // separating the first string with respect to '.'
           token=strtok(NULL,".");
       }

       token=strtok(str2,".");
       while(token!=NULL)
       {
           b[ind2++]=atoi(token); // separating the 2nd string with respect to '.'
           token=strtok(NULL,".");
       }

       int same=1,n=ind1;
       if(ind2>n)  // selecting maximum values between str1 and str2
         n=ind2;
       for(int i=0;i<n;i++)
       {
           if(a[i]!=b[i])
           {
               same=0;
               break;
           }
       }

       if(same)
         printf("value = 1 . Strings are same\n");
       else
         printf("value = 0 . Strings not same\n");
   }
   return 0;
}

这里每个字符串值都转换为整数,因此很容易在它们之间进行比较。

这也适用于这样的案例:

10.03.8.09.2.00
10.3.8.09.002

这是数字可以有前导零的地方:)

答案 2 :(得分:0)

一种算术方法,也将版本验证为数字集。

每个字段可以是0到9999,前导0可选。

int ValidateVersion(const char *src, unsigned long long *number) {
  unsigned u[5];
  int n4 = 0;
  int n5 = 0;
  sscanf(src,"%4u.%4u.%4u.%4u %n.%4u %n", 
    &u[0], &u[1], &u[2], &u[3], &n5, &u[4], &n5);

  if (n5 > 0) {
    if (src[n5] != '\0' || u[4] != 0) return -1; // invalid
  } else if (n4 != 0) {
    return -1; // invalid
  }  
  *number = u[0] * 1000000000000u + u[1] * 100000000u + u[2] * 10000u + u[3];
}

const char *sample() {
  const char *str1 = "10.3.8.9.2";
  unsigned long long n1;
  if (ValidateVersion(str1, &n1) return "1 Invalid";

  const char *str2 = "10.3.8.9.2.0";
  unsigned long long n2;
  if (ValidateVersion(str2, &n2) return "2 Invalid";

  if (n1 == n2) return "Equal";
  return "Different";
}

答案 3 :(得分:0)

天真的实施。注意:我使用strcmp()等于字符串的标准返回值约定:返回值=零)

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

int compare_versions(const char *a, const char *b)
{
size_t lena, lenb, len;
int rc;

            /* handle NULL pointer arguments gracefully */
if (!a || !b) { return (a) ? 1 : (b) ? -1: 0; }

while(1) {
            /* find the length of the non-numerical prefix */
    lena = strcspn(a, "0123456789" );
    lenb = strcspn(b, "0123456789" );

    len = (lena <lenb) ? lena : lenb;
    rc = (len) ? memcmp(a,b, len): 0;
    if (rc) return rc;

            /* Skip leading zeros */
    for(a += lena; *a == '0'; a++) {;}
    for(b += lenb; *b == '0'; b++) {;}
    if (!*a || !*b) break;

            /* find the length of the numerical prefix */
    lena = strspn(a, "0123456789" );
    lenb = strspn(b, "0123456789" );
    if (lena != lenb) return lena-lenb;

    rc = (len) ? memcmp(a,b, lena): 0;
    if (rc) return rc;

    a += lena; b += lenb;
    }

return *a - *b;
}


struct pair {
    char *l;
    char *r;
    } pairs[] = {
    {"10.3.8.9.2", "10.3.8.9.2"},
    {"10.3.8.9.2.0", "10.3.8.9.2.0"},
    {"10.3.8.9.2.0", "10.3.8.9.2"},
    {"10.3.8.9.2", "10.3.8.9.2.0"},
    {"10.3.8.9.2", "10.3.8.9.02"},
    {"10.3.8.9.20", "10.3.8.9.2"},
    {"10.3.8.9.2", "10.3.8.9.03"},
    {"10.3.8.9.2", "10.3.8.9.01"},
    {"10.3.8.9.02", "10.3.8.9.3"},
    {"10.3.8.9.02", "10.3.8.9.1"},
    {"10.3.8.9.02", "10.3.8.9.03"},
    {"10.3.8.9.02", "10.3.8.9.01"},
        };

int main(int argc, char *argv[])
{
int ii;

for (ii=0; ii < 12; ii++) {
    int rc;
    rc = compare_versions(pairs[ii].l ,pairs[ii].r  );
    printf("(%s <-->> %s)  compare value= %d\n"
        , pairs[ii].l ,pairs[ii].r  , rc);
        }
return 0;
}

输出:

$ ./a.out
(10.3.8.9.2 <-->> 10.3.8.9.2)  compare value= 0
(10.3.8.9.2.0 <-->> 10.3.8.9.2.0)  compare value= 0
(10.3.8.9.2.0 <-->> 10.3.8.9.2)  compare value= 0
(10.3.8.9.2 <-->> 10.3.8.9.2.0)  compare value= 0
(10.3.8.9.2 <-->> 10.3.8.9.02)  compare value= 0
(10.3.8.9.20 <-->> 10.3.8.9.2)  compare value= 1
(10.3.8.9.2 <-->> 10.3.8.9.03)  compare value= -1
(10.3.8.9.2 <-->> 10.3.8.9.01)  compare value= 1
(10.3.8.9.02 <-->> 10.3.8.9.3)  compare value= -1
(10.3.8.9.02 <-->> 10.3.8.9.1)  compare value= 1
(10.3.8.9.02 <-->> 10.3.8.9.03)  compare value= -1
(10.3.8.9.02 <-->> 10.3.8.9.01)  compare value= 1