1. 前言
本文简单介绍了IMEI的编码规则,然后引出IMEI校验的一个小程序,可作为C/C++编码爱好者的练手素材。
2. IMEI编码规则
2.1 IMEI组成
IMEI是由15个十进制数字组成的一个字符串,其中包括一个校验位(CD, Check Digit)。下面是3GPP TS23.003的几个截图:
简单地讲,IMEI一个15位,其中最后一位是CD(Check Digit)校验位。
2.2 CD位的计算方法
协议还提供了一个例子:
3. Luhn算法
在协议中,已经提到CD的计算方法是Luhn Algorithm。下面是维基百科对此的介绍:
- 中文:http://zh.wikipedia.org/wiki/Luhn_algorithm
- 英文:http://en.wikipedia.org/wiki/Luhn_algorithm
其中,英文链接中给出了Python语言的校验代码。
4. C/C++语言的校验程序
4.1 原型
在给出了上述背景知识之后,我们提出如下问题:用C/C++语言,写一个函数来检查IMEI号是否合法。原型如下:
/* 0: fail 1: ok */ int is_imei_valid(const char *imei);
4.2 参考代码
#include <stdio.h> #include <ctype.h> #include <string.h> const int IMEI_LENGTH = 15; /* Get the check digit of Luhn algorithm. data: the digits to be checked. The last digit is the CD. len: the length of data/digits. return: -1: error occurs others('0'..'9'): the check digit */ int luhn_checksum(const char *data, int len) { if (data == NULL || len < 2) return -1; int even = 1; int sum = 0; int double_digit; char p; int i; for (i = len - 2; i >= 0; i--) { p = data[i]; if (!isdigit(p)) return -1; p -= '0'; if (even) { double_digit = p + p; sum += double_digit / 10 + double_digit % 10; } else { sum += p; } even = !even; } return sum * 9 % 10; } /* return: -1: error occurs others('0'..'9'): the check digit */ int get_imei_cd(const char *imei) { if (imei == NULL) return -1; if (strlen(imei) != IMEI_LENGTH) return -1; int cd = luhn_checksum(imei, IMEI_LENGTH); return cd == -1 ? -1 : cd + '0'; } /* 0: fail 1: ok */ int is_imei_valid(const char *imei) { int cd = get_imei_cd(imei); if (cd == -1) return 0; return imei[IMEI_LENGTH - 1] == cd; } void test_is_imei_valid(const char *testcaseName, const char *imei, int expect) { printf("TESTCASE----%s: ", testcaseName); int result = is_imei_valid(imei); if (result == expect) { printf("PASS\n"); } else { printf("FAIL. expect=%d, real=%d\n", expect, result); } } void test_get_imei_cd(const char *testcaseName, const char *imei, int expect) { printf("TESTCASE----%s: ", testcaseName); int result = get_imei_cd(imei); if (result == expect) { printf("PASS\n"); } else { printf("FAIL. expect=0x%02x, real=0x%02x\n", expect, result); } } int main() { printf("test_is_imei_valid\n"); test_is_imei_valid("valid imei 000000000000000", "000000000000000", 1); test_is_imei_valid("valid imei 0164", "0164", 1); test_is_imei_valid("valid imei 4564", "4564", 1); test_is_imei_valid("null imei", NULL, 0); test_is_imei_valid("invalid imei", "4567", 0); test_is_imei_valid("invalid imei", "456", 0); test_is_imei_valid("invalid imei", "45678", 0); printf("test_get_imei_cd\n"); test_get_imei_cd("valid imei 000000000000000", "000000000000000", '0'); test_get_imei_cd("valid imei 0164", "0164", '4'); test_get_imei_cd("valid imei 4564", "4564", '4'); test_get_imei_cd("null imei", NULL, -1); test_get_imei_cd("invalid imei", "456", -1); test_get_imei_cd("invalid imei", "45678", -1); return 0; }
运行结果:
flying-bird@flyingbird:~/docs/The_Road_to_Cpp/src/imei$ gcc imei.c flying-bird@flyingbird:~/docs/The_Road_to_Cpp/src/imei$ ./a.out test_is_imei_valid TESTCASE----valid imei 000000000000000: PASS TESTCASE----valid imei 0164: PASS TESTCASE----valid imei 4564: PASS TESTCASE----null imei: PASS TESTCASE----invalid imei: PASS TESTCASE----invalid imei: PASS TESTCASE----invalid imei: PASS test_get_imei_cd TESTCASE----valid imei 000000000000000: PASS TESTCASE----valid imei 0164: PASS TESTCASE----valid imei 4564: PASS TESTCASE----null imei: PASS TESTCASE----invalid imei: PASS TESTCASE----invalid imei: PASS flying-bird@flyingbird:~/docs/The_Road_to_Cpp/src/imei$
今天的文章 谈谈IMEI合法性判断方法分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/83489.html