Re: [问题] 版本字串比较

楼主: gn00618777 (非常念旧)   2020-10-02 22:55:31
※ 引述《gn00618777 (非常念旧)》之铭言:
: release 版本格式: x.x.xxx
: 目的 : 1.1.066 以及 1.1.66 ,程式都能认定同一版本。
: (为了防止开发者少填1个0,也就是1.1.66)
: (少填1个0,会使strncmp 1.1.66 > 1.1.066)
: (我是觉得公司都已经规定格式了,1.1.66不就不被允许吗..)
: (但上层总是想得比我们下面的人多拉~)
: (所以我用了每小数点为分隔来求出每个数字来比)
: (因此就能认定1.1.066 == 1.1.66了)
: version 会存在既定 array(a_version, b_version)因为到时写成 fun传入来源指标
: 用strtok系列会改变来源位址,所以用a_version, b_version既定来存
: char a_version[] = "1.1.066";
: char b_version[] = "1.1.66";
: char *a_ptr = NULL;
: char *b_ptr = NULL;
: char *p,*q;
: int i = 0;
: int result = 0;
: p = strtok_r(a_version, ".", &a_ptr);
: q = strtok_r(b_version, ".", &b_ptr);
: while(p != NULL && q != NULL) {
: if((int)strtoul(p, NULL, 10) > (int)strtoul(q, NULL, 10)) {
: result = 1;
: break;
: } else if((int)strtoul(p, NULL, 10) < (int)strtoul(q, NULL, 10)) {
: result = -1;
: break;
: } else {
: //do nothing
: }
: p = strtok_r(NULL, ".", &a_ptr);
: q = strtok_r(NULL, ".", &b_ptr);
: }
: return result; //1: a>b -1:a<b 0: a==b
要用一个 buffer 的写法我放弃了,我觉得应该还是要用两个空间去存比较安全
原因 1 strtok 会改到source
原因 2 确保source 进来结尾能是'\0'
有些大大热心提供的程式我还未消化完,非常感谢。我先提供自己的完整写法
有些环境编译器没有 strtok_r的header,我是使用 https://reurl.cc/bRVono
glibc porting过来的。
并搭配 leetcode 165 的测试题 https://reurl.cc/GrjYVG 验证。另外我比leetcode
要求的回传1 or -1 or 0 更进一步,我的不只回传1 -1 0 ,可以回传大多少小多少
有觉得更好的建议再多多指教囉。
int compare_version(const char *str1_version, const char *str2_version) {
char a_version[FW_VERSION_SIZE+1] = {0};
char b_version[FW_VERSION_SIZE+1] = {0};
char *a_ptr = NULL, *b_ptr = NULL;
char *p = NULL, *q = NULL;
int a = 0, b = 0;
if(str1_version)
strncpy(a_version, str1_version, FW_VERSION_SIZE);
if(str2_version)
strncpy(b_version, str2_version, FW_VERSION_SIZE);
p = strtok_r(a_version, ".", &a_ptr);
q = strtok_r(b_version, ".", &b_ptr);
if(p) a = atoi(p);
if(q) b = atoi(q);
if(a != b) return a - b;
while(a == b) {
p = strtok_r(NULL, ".", &a_ptr);
q = strtok_r(NULL, ".", &b_ptr);
p != NULL ? (a = atoi(p)) : (a = 0);
q != NULL ? (b = atoi(q)) : (b = 0);
if(p == NULL && q == NULL)
return 0;
}
return a - b;
}
作者: loveme00835 (发箍)   2020-10-03 09:27:00
你的问题在于还没分析完全就开始实作, C 语言有两种字串, 一种是 C-style string, 另一种不是用内容来分而是用 (char*,size_t) 这样的 tuple描述, 前者无法支援巢状结构, 所以 strtok() 是用截断的方式, 但我们如果要想拿出子字串, 应该使用后者, 这样既不用改变输入字串内容, 也可以更有系统的描述问题, 在你的问题里, 目标即是将输入的字串拆成 3 个 tuple, 分别为: (a_version, 1), (a_version + 2, 1), (a_version + 4, 3) 只要给你任何字串都有办法拆出 n 个 tuple那版本字串的比对问题就转变为 n 的 tuple 各自去比较的问题了, 比较 tuple 甚至也不一定要先转成整数,类似像 strncmp() 的逻辑甚至是反方向地比对字符也是原文推文已经提供可以客制化的实作了, 核心概念就是两个 while 循环去萃取 tuple 而已, 剩下就看你理解程度
作者: annheilong (方格子)   2020-10-05 10:07:00
想知道C语言第二种字串的型别是...?
作者: LPH66 (-6.2598534e+18f)   2020-10-05 10:19:00
std::string 内部即是这种结构, 只除了 char* 也是他管而已这种表示法的好处是字串长度是 O(1) 操作, 不像 strlen 是O(n) 操作; 另外就是如果 char* 不是自己管的 (例子像是std::string_view) 那就能如上面推文进行更有弹性的操作以上是 C++ 的东西, 但 C 也不是不能自己自订一个结构来用那因为这种做法是因为一种 Pascal 的实作所推广的因此一般会称这种做法的字串叫 pascal string
作者: loveme00835 (发箍)   2020-10-05 11:13:00
另一种字串即是在标准函式库里抽象化存在, 但语言上没有明确定义的, 如 strncmp()/strncpy() 等, 从接口上会衍伸一个问题: 如果 C-style 字串只复制前面 n个字符, 不包含 '\0', 那复制而来的算不算字串? 虽然它和 C-style 字串不同, 但却已经是字串处理很基本的元件

Links booklink

Contact Us: admin [ a t ] ucptt.com