将15位一代身份证号转换成18位二代身份证号

原来的一代身份证号是15位的,现在用的二代身份证号是18位的,它们之间有一个转换规则。
一代:340524800101001
二代:34052419800101001X
可以看到它们之间的区别是二代在年份前多了19,最后面多了一位校验位

第十八位数字的计算方法为:
1.将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
2.将这17位数字和系数相乘的结果相加。
3.用加出来和除以11,看余数是多少?
4余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2。
5.通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。

以下代码VC6编译测试通过:

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

void id_card_convert(char * id)
{
  char tmp[20];
  int i, j ,sum = 0;
  char verify[11] = {'1','0','X','9','8','7','6','5','4','3','2'};//校验位
  int num[17] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};//系数

  //转换号码15位到18位
  memset(tmp, 0x00, sizeof(tmp));
  memcpy(tmp, id, 6);//复制前6位
  memcpy(&tmp[6], "19", 2);//前6位后补19
  memcpy(&tmp[8], id+6, 9);//复制后9位
  
  for (i = 0; i < 17; i++)//现在tmp有17位算第18位校验位
  {
    sum = sum + (tmp[i]-0x30)*num[i];
  }

  j = sum % 11;//从verify数组中找到第j位就是校验值

  tmp[17] = verify[j];
  
  memcpy(id, tmp, 20);  
}

void main()
{
  char id_card[20];
  memset(id_card, 0x00, sizeof(id_card));
  memcpy(id_card, "340524800101001", 15);
  printf("原身份证号:%s\n", id_card);
  id_card_convert(id_card);
  printf("转换后:%s\n", id_card); //显示34052419800101001X是正确值
}

参考资料:
http://blog.csdn.net/ylqmf/article/details/4904483