主题:信用卡卡号验证程序
原帖 [url]http://bbs.pfan.cn/post-365659.html[/url]
[quote]该校验的过程:
1、从卡号最后一位数字开始,逆向将奇数位(1、3、5等等)相加。
2、从卡号最后一位数字开始,逆向将偶数位数字,先乘以2(如果乘积为两位数,则将其减去9),再求和。
3、将奇数位总和加上偶数位总和,结果应该可以被10整除。
[/quote]
想把代码发到原帖里,好像太长了,发不了,所以新开了一贴。
这个版本是32位,64位的没写了。
代码写得很乱,感觉不知道要怎么组织代码,写代码真的太累了,花了我2天多的时间。写的过程中总是出现一些奇怪的错误,到目前应该还有比较严重的错误没发现。
附件里面的 TEST*.IN文件全部是测试文件,是在网上下了一个信用卡生成器自动生成的。
可能代码(foo.c)里面有几个地方不好理解:
1. 求一个数字字符串的长度(strlen_inital函数):bruceteen大牛曾今说过,处理char类型的效率不会很高,在这里我是把char字符串转成int指针来处理的,如果字符串"12345678"它在内存中是这样的:31 32 33 34 35 36 37 38(16进制),用一个int指针来指向第一个字符31,然后读取一个int数据,得到 31 32 33 34.判断这4字节是不是全部为数字字符,因为字符'0'-'9'是0x30-0x39;也就是 加0x10绝对会是大于等于0x40,那么得到的结果和0x40 位与一定位 0x40; 同理,加0x06 是绝对会小于0x40的,但是还要考虑大于0x40的字符,既有加0x06 以后和0xc0位与一定会等于0.
0x31323334 + 0x10101010 = 0x41424344, 0x41424344 & 0x40404040 = 0x40404040;(相当于*s>='0';)
0x31323334 + 0x06060606 = 0x3738393a, 0x3738393a & 0xc0c0c0c0 = 0(相当于*s<='9')
2. 如果在1中的数据满足全部为数字,那么 减去 0x30303030将得到相应的数,0x31323334-0x30303030 = 0x01020304.在得到的这个数分别用0xff00ff00 0x00ff00ff这两个数 位与 ,既可以把它的 奇数位 和 偶数位(顺向) 分离出来了。然后把他分别保存到numbers1 numbers2这两个数组中。但是0xff00ff00 0x00ff00ff这要位与得到的数总有一半字节是0,因此可以通过左移和右移8位,这样让那些为0的字节也能利用起来。
3. 将偶数位数字,先乘以2(如果乘积为两位数,则将其减去9),再求和(process0函数)。这里,可以换一个思路来对待,如果偶数位数字大于等于5,先乘以2,然后在加1;否则乘以2,再加0.反正最后除以10的余数是一样的。这里并没用用if语句来实现。判读一个数是不是大于等于5,只要这个数 加3 ,它一定会大于等于8, 只要和 8位与,一定为8、如果这个数小于5, 加3 一定小于 8, 和 8位与 得 0、把和8位于得到的结果右移3位,将得到0或1,这个数有刚好是要加的数。如 偶数位数据为
0x03040506 + 0x03030303 = 0x06070809, 0x06070809 & 0x08080808 = 0x00000808;
0x00000808 >> 3 = 0x00000101;
0x03040506 << 1 = 0x06080a0c; 0x06080a0c + 0x00000101 = 0x06080b0d;
0x03040506本来应该是得到(6+8+10-9+12-9)=18;除以10的余数为8
而0x06080b0d将得到(6+8+11+13)=38,除以10的余数为8,和上面是一样的。
[quote]该校验的过程:
1、从卡号最后一位数字开始,逆向将奇数位(1、3、5等等)相加。
2、从卡号最后一位数字开始,逆向将偶数位数字,先乘以2(如果乘积为两位数,则将其减去9),再求和。
3、将奇数位总和加上偶数位总和,结果应该可以被10整除。
[/quote]
想把代码发到原帖里,好像太长了,发不了,所以新开了一贴。
这个版本是32位,64位的没写了。
代码写得很乱,感觉不知道要怎么组织代码,写代码真的太累了,花了我2天多的时间。写的过程中总是出现一些奇怪的错误,到目前应该还有比较严重的错误没发现。
附件里面的 TEST*.IN文件全部是测试文件,是在网上下了一个信用卡生成器自动生成的。
可能代码(foo.c)里面有几个地方不好理解:
1. 求一个数字字符串的长度(strlen_inital函数):bruceteen大牛曾今说过,处理char类型的效率不会很高,在这里我是把char字符串转成int指针来处理的,如果字符串"12345678"它在内存中是这样的:31 32 33 34 35 36 37 38(16进制),用一个int指针来指向第一个字符31,然后读取一个int数据,得到 31 32 33 34.判断这4字节是不是全部为数字字符,因为字符'0'-'9'是0x30-0x39;也就是 加0x10绝对会是大于等于0x40,那么得到的结果和0x40 位与一定位 0x40; 同理,加0x06 是绝对会小于0x40的,但是还要考虑大于0x40的字符,既有加0x06 以后和0xc0位与一定会等于0.
0x31323334 + 0x10101010 = 0x41424344, 0x41424344 & 0x40404040 = 0x40404040;(相当于*s>='0';)
0x31323334 + 0x06060606 = 0x3738393a, 0x3738393a & 0xc0c0c0c0 = 0(相当于*s<='9')
2. 如果在1中的数据满足全部为数字,那么 减去 0x30303030将得到相应的数,0x31323334-0x30303030 = 0x01020304.在得到的这个数分别用0xff00ff00 0x00ff00ff这两个数 位与 ,既可以把它的 奇数位 和 偶数位(顺向) 分离出来了。然后把他分别保存到numbers1 numbers2这两个数组中。但是0xff00ff00 0x00ff00ff这要位与得到的数总有一半字节是0,因此可以通过左移和右移8位,这样让那些为0的字节也能利用起来。
3. 将偶数位数字,先乘以2(如果乘积为两位数,则将其减去9),再求和(process0函数)。这里,可以换一个思路来对待,如果偶数位数字大于等于5,先乘以2,然后在加1;否则乘以2,再加0.反正最后除以10的余数是一样的。这里并没用用if语句来实现。判读一个数是不是大于等于5,只要这个数 加3 ,它一定会大于等于8, 只要和 8位与,一定为8、如果这个数小于5, 加3 一定小于 8, 和 8位与 得 0、把和8位于得到的结果右移3位,将得到0或1,这个数有刚好是要加的数。如 偶数位数据为
0x03040506 + 0x03030303 = 0x06070809, 0x06070809 & 0x08080808 = 0x00000808;
0x00000808 >> 3 = 0x00000101;
0x03040506 << 1 = 0x06080a0c; 0x06080a0c + 0x00000101 = 0x06080b0d;
0x03040506本来应该是得到(6+8+10-9+12-9)=18;除以10的余数为8
而0x06080b0d将得到(6+8+11+13)=38,除以10的余数为8,和上面是一样的。