我需要比较两个"版本"可能会或可能不会以.0
结尾的字符串,以便(例如)10.3.8.9.2
和10.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.2
和10.3.8.9.20.0
视为相等,这是不正确的。我尝试更新代码,如下所示,但由于strncmp()
成功返回0
,因此无法提供所需的结果。
似乎我没有在三元运算符内正确处理这个条件。可能是将两个表达式的返回值存储在单独的变量中可以解决此问题,但是想知道如何使用三元运算符实现这一点。
答案 0 :(得分:1)
您需要首先比较str1
和str2
的最短公共子字符串,然后检查每个字符串的剩余部分。这是一个不使用三元运算符进行字符串比较的解决方案:
#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