手机归属地数据文件格式是自己定义的,格式描述如下:

手机号段数据导入程序 C++ 源代码:
1. 自定义工具库头文件Global.h

  1. #ifndef _MPGLOBAL_INCLUDED_
  2. #define _MPGLOBAL_INCLUDED_
  3. #pragma pack (1)
  4. //链表节点类
  5. class StringNode
  6. {
  7. public:
  8. char * value;
  9. int length;
  10. int offset;
  11. StringNode * next;
  12. StringNode(const char * val);
  13. StringNode();
  14. ~StringNode();
  15. };
  16. //索引表节点类
  17. class IndexNode
  18. {
  19. public:
  20. int NumStart;
  21. int NumEnd;
  22. StringNode * Address;
  23. IndexNode * next;
  24. IndexNode();
  25. IndexNode(int ns, int ne, StringNode * ad=NULL);
  26. };
  27. //索引记录结构体
  28. typedef struct _IndexStruct
  29. {
  30. int NumStart;
  31. int NumEnd;
  32. int Offset;
  33. } IndexStruct;
  34. //手机归属地结构体类型
  35. typedef struct _MpLocation
  36. {
  37. int NumStart;
  38. int NumEnd;
  39. char * Location;
  40. } MpLocation;
  41. //更改文件扩展名
  42. char * ChangeFileExt(const char * fn, const char * fext);
  43. //判断字符串是否为数字
  44. bool IsNumeric(const char * val);
  45. #endif

2. 自定义工具库程序文件Global.cpp

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "Global.h"
  4. StringNode::StringNode(const char * val)
  5. {
  6. this->length=strlen(val);
  7. this->value=new char[this->length+1];
  8. strcpy(this->value,val);
  9. this->next=NULL;
  10. }
  11. StringNode::StringNode()
  12. {
  13. value=NULL;
  14. length=0;
  15. next=NULL;
  16. }
  17. StringNode::~StringNode()
  18. {
  19. if(value) delete[] value;
  20. }
  21. IndexNode::IndexNode()
  22. {
  23. NumStart=NumEnd=0;
  24. Address=NULL;
  25. next=NULL;
  26. }
  27. IndexNode::IndexNode(int ns, int ne, StringNode * ad)
  28. {
  29. NumStart=ns; NumEnd=ne; Address=ad;
  30. next=NULL;
  31. }
  32. char * ChangeFileExt(const char * fn, const char * fext)
  33. {
  34. int l=strlen(fn);
  35. int le=strlen(fext);
  36. for(int i=l-1; fn[i]!='.' && fn[i]!='//' && fn[i]!='/' && fn[i]!=':' && i>=0; i--);
  37. char * fnext;
  38. //如果没扩展名
  39. if(i<=0||fn[i]=='/-:special:2:-||fn[i]=='/'||fn[i]==':')
  40. {
  41. fnext=new char[l+le+2];
  42. strcpy(fnext,fn);
  43. fnext[l]='.';
  44. l++;
  45. strcpy(fnext+l,fext);
  46. }
  47. else
  48. {
  49. l=i+1;
  50. fnext=new char[l+le+1];
  51. strcpy(fnext,fn);
  52. strcpy(fnext+l,fext);
  53. }
  54. //申请新文件名的存储空间
  55. return fnext;
  56. }
  57. bool IsNumeric(const char * val)
  58. {
  59. for(int i=0;val[i]!='/0';i++)
  60. {
  61. if(val[i]<'0'||val[i]>'9')
  62. return false;
  63. }
  64. return true;
  65. }

3. 主程序源文件 Mps.cpp

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <conio.h>
  4. #include <windows.h>
  5. #include "Global.h"
  6. #define LINE_BUFFER_SIZE 256
  7. //在字符串链表中搜索字符串,返回节点指针
  8. inline StringNode * FindString(StringNode * st, const char * str)
  9. {
  10. for(StringNode * ps=st; ps!=NULL; ps=ps->next)
  11. {
  12. if(strcmp(ps->value,str)==0)
  13. return ps;
  14. }
  15. return NULL;
  16. }
  17. //文本数据 -> 二进制数据文件
  18. void MpDataConvert(const char * fnin, const char * fnout)
  19. {
  20. FILE * fpin=fopen(fnin,"rb");     //输入文件
  21. if(!fpin)
  22. {
  23. printf("打开文件失败!/n");
  24. return;
  25. }
  26. printf("正在导入文件 [%s] 到 [%s] ... ",fnin,fnout);
  27. StringNode * stringTable;
  28. IndexNode * indexTable;
  29. StringNode * ps;
  30. IndexNode * p;
  31. int numLast;   //上一行的号码
  32. int numRead;   //当前读取的号码
  33. char * addrRead=new char[LINE_BUFFER_SIZE];
  34. int sfCount=0; //源文件记录计数
  35. bool isFirst=true;
  36. while(!feof(fpin))
  37. {
  38. fscanf(fpin,"%d,%s",&numRead,addrRead); sfCount++;
  39. //首记录处理
  40. if(isFirst)
  41. {
  42. ps=stringTable=new StringNode(addrRead);
  43. ps->next=NULL;
  44. p=indexTable=new IndexNode(numRead,0,ps);
  45. p->next=NULL;
  46. isFirst=false;
  47. //保存本次读取的号码以便读下一行时用到
  48. numLast=numRead;
  49. continue;
  50. }
  51. //如果地址未变
  52. if(strcmp(p->Address->value,addrRead)==0)
  53. {
  54. //保存本次读取的号码以便读下一行时用到
  55. numLast=numRead;
  56. continue;
  57. }
  58. //如果地址变了
  59. else
  60. {
  61. //完成前一条记录
  62. p->NumEnd=numLast;
  63. //开始新记录
  64. StringNode * s=FindString(stringTable,addrRead);
  65. if(s==NULL)
  66. {
  67. ps=ps->next=new StringNode(addrRead);
  68. s=ps;
  69. }
  70. p=p->next=new IndexNode(numRead,0,s);
  71. //保存本次读取的号码以便读下一行时用到
  72. numLast=numRead;
  73. }
  74. }
  75. p->NumEnd=numLast;
  76. //关闭源文件
  77. fclose(fpin);
  78. /***********************************************/
  79. //FILE * fps=fopen("StringTable.txt","w");
  80. int j=0;
  81. for(p=indexTable;p!=NULL;p=p->next)
  82. {
  83. //printf("%d %d  %s/n",p->NumStart,p->NumEnd,p->Address->value);
  84. j++;
  85. }
  86. int k=0;
  87. for(ps=stringTable;ps!=NULL;ps=ps->next)
  88. {
  89. //printf("%s/n",ps->value);
  90. //fprintf(fps,"%s/n",ps->value);
  91. k++;
  92. }
  93. /***********************************************/
  94. /***********************************************/
  95. //导入数据文件
  96. FILE * fpout=fopen(fnout,"wb");
  97. int header[2]={0,0};  //文件头
  98. fwrite(&header,sizeof(header),1,fpout);
  99. int pos=ftell(fpout);
  100. //写入字符串表
  101. for(ps=stringTable;ps!=NULL;ps=ps->next)
  102. {
  103. pos=ftell(fpout);
  104. ps->offset=pos;
  105. fwrite(ps->value,1,ps->length+1,fpout);
  106. }
  107. //写入索引记录表
  108. pos=ftell(fpout);
  109. header[0]=pos;
  110. IndexStruct is;
  111. for(p=indexTable;p!=NULL;p=p->next)
  112. {
  113. pos=ftell(fpout);
  114. is.NumStart=p->NumStart;
  115. is.NumEnd=p->NumEnd;
  116. is.Offset=p->Address->offset;
  117. fwrite(&is,sizeof(is)-1,1,fpout);
  118. }
  119. pos=ftell(fpout);
  120. header[1]=pos-(sizeof(is)-1);
  121. //重写文件头
  122. fseek(fpout,0,SEEK_SET);
  123. fwrite(&header,sizeof(header),1,fpout);
  124. //获取数据文件大小
  125. fseek(fpout,0,SEEK_END);
  126. pos=ftell(fpout);
  127. //关闭文件
  128. fclose(fpout);
  129. printf("导入成功!/n");
  130. printf("源文件记录数: %d/n",sfCount);
  131. printf("目标记录总数: %d/n",j);
  132. //fprintf(fps,"记录总数: %d/n",j);
  133. printf("字符串记录数: %d/n",k);
  134. //fprintf(fps,"字符串数: %d/n",k);
  135. //fclose(fps);
  136. printf("目标文件大小: %d字节/n",pos);
  137. /***********************************************/
  138. //printf("/n按任意键退出...");
  139. //getch();
  140. }
  141. //获取号码段记录在文件中的偏移量
  142. inline int getIndexOffset(FILE * fp, int fo, int lo, int num)
  143. {
  144. int mo;    //中间偏移量
  145. int mv;    //中间值
  146. int fv,lv; //边界值
  147. int llv;   //边界末末值
  148. fseek(fp,fo,SEEK_SET);
  149. fread(&fv,sizeof(fv),1,fp);
  150. fseek(fp,lo,SEEK_SET);
  151. fread(&lv,sizeof(lv),1,fp);
  152. fread(&llv,sizeof(llv),1,fp);
  153. //边界检测处理
  154. if(num<fv)
  155. return -1;
  156. else if(num>llv)
  157. return -1;
  158. //使用"二分法"确定记录偏移量
  159. do
  160. {
  161. mo=fo+(lo-fo)/(sizeof(IndexStruct)-1)/2*(sizeof(IndexStruct)-1);
  162. fseek(fp,mo,SEEK_SET);
  163. fread(&mv,sizeof(mv),1,fp);
  164. if(num>=mv)
  165. fo=mo;
  166. else
  167. lo=mo;
  168. if(lo-fo==sizeof(IndexStruct)-1)
  169. mo=lo=fo;
  170. } while(fo!=lo);
  171. return mo;
  172. }
  173. //查询号码,返回号码段和归属地信息
  174. MpLocation GetMpLocation(const char * fn, int num)
  175. {
  176. FILE * fp=fopen(fn,"rb");
  177. if(!fp)
  178. throw "打开数据文件失败!";
  179. int fo,lo;
  180. //读文件头,获取首末记录偏移量
  181. fread(&fo,sizeof(fo),1,fp);
  182. fread(&lo,sizeof(lo),1,fp);
  183. int rcOffset=getIndexOffset(fp,fo,lo,num);
  184. MpLocation mpl;
  185. if(rcOffset>=0)
  186. {
  187. fseek(fp,rcOffset,SEEK_SET);
  188. //读取号码段起始地址和结束地址
  189. fread(&mpl.NumStart,sizeof(mpl.NumStart),1,fp);
  190. fread(&mpl.NumEnd,sizeof(mpl.NumEnd),1,fp);
  191. //如果查询的号码处于中间空段
  192. if(num>mpl.NumEnd)
  193. {
  194. mpl.NumStart=0; mpl.NumEnd=0;
  195. mpl.Location="未知地址";
  196. }
  197. else
  198. {
  199. //读取字符串偏移量,3字节!
  200. int lstrOffset=0;
  201. fread(&lstrOffset,3,1,fp);
  202. lstrOffset&=0x00ffffff;
  203. fseek(fp,lstrOffset,SEEK_SET);
  204. //读取归属地字符串
  205. static char strBuf[48];
  206. fread(strBuf,sizeof(strBuf),1,fp);
  207. //检验字符串边界
  208. for(int i=0;strBuf[i]!='/0'&&i<sizeof(strBuf);i++);
  209. if(i==sizeof(strBuf)) strBuf[sizeof(strBuf)-1]='/0';
  210. mpl.Location=new char[strlen(strBuf)+1];
  211. strcpy(mpl.Location,strBuf);
  212. }
  213. }
  214. else
  215. {
  216. //没找到记录
  217. mpl.NumStart=0; mpl.NumEnd=0;
  218. mpl.Location="未知地址";
  219. }
  220. fclose(fp);
  221. return mpl;
  222. }
  223. //号码查询程序
  224. void MpLocating(const char * fn, char * sNum)
  225. {
  226. int num=0;
  227. if(!IsNumeric(sNum))
  228. {
  229. printf("请输入7位手机号!/n");
  230. }
  231. else
  232. {
  233. sscanf(sNum,"%7d",&num);
  234. try
  235. {
  236. MpLocation mpl=GetMpLocation(fn,num);
  237. printf("号码段: %07d - %07d/n",mpl.NumStart,mpl.NumEnd);
  238. printf("归属地: %s/n",mpl.Location);
  239. }
  240. catch(char * e)
  241. {
  242. printf("%s/n",e);
  243. }
  244. }
  245. }
  246. //显示帮助信息
  247. inline void printHelp()
  248. {
  249. const char * en="Mps";
  250. printf("手机归属地查询程序./n/n");
  251. printf("查询归属地: %s <号码前七位>/n",en);
  252. printf("导入数据库: %s -c <数据源文件名>/n",en);
  253. printf("/n示例:/n");
  254. printf("   > %s -c MpData.txt              导入MpData.txt到MpData.dat/n",en);
  255. printf("   > %s 1358348                    查询号段1358348的归属地/n",en);
  256. printf("/n提示: 查询归属地时请把数据库文件MpData.dat与本程序放在同一目录下./n");
  257. }
  258. //===================主程序入口===================
  259. void main(int argc, char * argv[])
  260. {
  261. /***********************************************************
  262. argc=2;
  263. argv[0]="Mps.exe";
  264. argv[1]="MpLocator.txt";
  265. ************************************************************/
  266. //数据文件名
  267. const char * fnData="MpData.dat";
  268. if(argc>1)
  269. {
  270. char opcode='s';  //操作码 's'为查询号码, 'c'为导入数据
  271. char * val="";    //参数值
  272. //获取操作码和参数值
  273. for(int i=1;i<argc;i++)
  274. {
  275. if(argv[i][0]=='-')
  276. opcode=argv[i][1];
  277. else
  278. val=argv[i];
  279. }
  280. //操作选择
  281. switch(opcode)
  282. {
  283. case 's':
  284. //查询号码
  285. MpLocating(fnData,val);
  286. break;
  287. case 'c':
  288. //导入数据
  289. MpDataConvert(val,ChangeFileExt(val,"dat"));
  290. break;
  291. case 'h':
  292. //帮助信息
  293. printHelp();
  294. break;
  295. default:
  296. //无操作
  297. break;
  298. }
  299. }
  300. else
  301. {
  302. //直接双击运行
  303. char inputBuf[32];
  304. while(true)
  305. {
  306. printf("手机号前7位: ");
  307. fgets(inputBuf,32,stdin);
  308. if(inputBuf[strlen(inputBuf)-1]=='/n')
  309. inputBuf[strlen(inputBuf)-1]='/0';
  310. //如果接收到空字符串则退出
  311. if(strlen(inputBuf)==0)
  312. break;
  313. MpLocating(fnData,inputBuf);
  314. printf("/n");
  315. }
  316. //保持屏幕5秒钟
  317. //Sleep(5000);
  318. }
  319. }

完整的源代码及数据文件请从这里下载: http://download.csdn.net/source/611741

  (原创文章,转载时请注明本文网址)

手机号归属地数据导入及查询工具源代码(C++)相关推荐

  1. 号码归属地及运营商查询工具

    号码归属地及运营商查询工具 import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phone ...

  2. 02_clickhouse安装,卸载,启动/关闭服务,交互式命令(数据库创建,数据导入,查询),批模式数据导入,MySQL接口操作ClickHouse,DBeaver可视化工具安装与使用(学习笔记)

    1 ClickHouse安装 安装文件清单 clickhouse-client-${version}.noarch.rpm clickhouse-common-static-dbg-${version ...

  3. Solr 7 - 中文分词、数据导入、查询 基本使用篇

    接着之前的 Solr 7 - CentOS 部署篇 继续 Go! 准备一下 /opt/solr-7.6.0 实际安装目录 /opt/solr 指向实际安装目录的链接 我们先链接一份 solr 命令到 ...

  4. Elasticsearch+Mongo亿级别数据导入及查询实践

    数据方案: 在Elasticsearch中通过code及time字段查询对应doc的mongo_id字段获得mongodb中的主键_id 通过获得id再进入mongodb进行查询   1,数据情况: ...

  5. excel 数据导入(附工具类)

    // 导入excel中的数据到数据库中@PostMapping(value = "importHDangerRecord")@Overridepublic RestMessage ...

  6. TDSQL“相似查询工具MSQL+”入选VLDB论文

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云数据库 TencentDB发表于云+社区专栏 作者介绍:王晓宇,腾讯数据库TDSQL团队成员,目前参与TDSQL数据库内核研发工 ...

  7. TDSQL“相似查询工具MSQL+”入选VLDB论文 1

    腾讯与高校合作的论文入选数据库顶会 腾讯TDSQL团队携手中国人民大学信息学院.武汉大学计算机学院合作的DEMO论文"MSQL+: a Plugin Toolkit for Similari ...

  8. 基于delphi的excel数据导入导出

    因为淘宝客户的一个小需求,写了一个"基于delphi 7的excel数据导入导出"小工具.为了抛砖引玉,将这个小工具分享出来.希望对初学者和用得到的朋友有点点小小的帮助.oracl ...

  9. 使用Python将Excel中的数据导入到MySQL

    使用Python将Excel中的数据导入到MySQL 工具 Python 2.7 xlrd MySQLdb 安装 Python 对于不同的系统安装方式不同,Windows平台有exe安装包,Ubunt ...

最新文章

  1. C#的6种常用集合类大比拼【月儿原创】
  2. 【C/C++】中的__FILE__、__LINE__、#line、__func__关键字(预定义宏)
  3. Powerup tinyos接口实现
  4. A Full Hardware Guide to Deep Learning
  5. Jackson用法详解
  6. ddos常见攻击报文
  7. ppt 2 html工具,PPTools PPT2HTML
  8. 如何使用 volatile, synchronized, final 进行线程间通信
  9. 终止正在运行的VBS脚本
  10. 当你使用R安装包出现rdb is corrupt问题的时候
  11. 从AssetBundle中获取图片,给Image 组件替换Sprite
  12. spring用的是哪种工厂模式_业务复杂就用 ifelse?刚来的技术大佬用这招彻底干掉了!...
  13. cs231n-svm作业
  14. A8. 无人机编队飞行定位分析与讨论-大结局
  15. arduino下载库出错_关于程序下载到最后卡住了以及自带库不能用的问题!!
  16. PLC数据采集之协议转换桥接器
  17. qq for android 1.0,QQ for Pad 1.0正式发布 Android专版
  18. 公众号开发:实现一键复制功能
  19. STM32F401 / STM32F411 WeAct Studio 资料以及翻版说明
  20. Excel做曲线拟合

热门文章

  1. 免费获取华夏邓白氏编码(021-26107504)
  2. 为什么CNN可以自动提取图像特征???(2)
  3. 计算机开路人阿兰·图灵
  4. CF1604B XOR Specia-LIS-t
  5. Linux_第1章 Linux入门
  6. (SQL入门详解)每天十分钟。10天搞定SQL
  7. Python我的世界小游戏源代码
  8. 不一样的VR全景购物,赋能商超和店铺购物升级
  9. shell脚本编程学习笔记1(xdl)——shell基础与Bash基本功能()
  10. 《中国制造2025》提出构建绿色制造体系,成为我国制造业新趋势