手机号归属地数据导入及查询工具源代码(C++)
手机归属地数据文件格式是自己定义的,格式描述如下:
手机号段数据导入程序 C++ 源代码:
1. 自定义工具库头文件Global.h
- #ifndef _MPGLOBAL_INCLUDED_
- #define _MPGLOBAL_INCLUDED_
- #pragma pack (1)
- //链表节点类
- class StringNode
- {
- public:
- char * value;
- int length;
- int offset;
- StringNode * next;
- StringNode(const char * val);
- StringNode();
- ~StringNode();
- };
- //索引表节点类
- class IndexNode
- {
- public:
- int NumStart;
- int NumEnd;
- StringNode * Address;
- IndexNode * next;
- IndexNode();
- IndexNode(int ns, int ne, StringNode * ad=NULL);
- };
- //索引记录结构体
- typedef struct _IndexStruct
- {
- int NumStart;
- int NumEnd;
- int Offset;
- } IndexStruct;
- //手机归属地结构体类型
- typedef struct _MpLocation
- {
- int NumStart;
- int NumEnd;
- char * Location;
- } MpLocation;
- //更改文件扩展名
- char * ChangeFileExt(const char * fn, const char * fext);
- //判断字符串是否为数字
- bool IsNumeric(const char * val);
- #endif
2. 自定义工具库程序文件Global.cpp
- #include <stdio.h>
- #include <string.h>
- #include "Global.h"
- StringNode::StringNode(const char * val)
- {
- this->length=strlen(val);
- this->value=new char[this->length+1];
- strcpy(this->value,val);
- this->next=NULL;
- }
- StringNode::StringNode()
- {
- value=NULL;
- length=0;
- next=NULL;
- }
- StringNode::~StringNode()
- {
- if(value) delete[] value;
- }
- IndexNode::IndexNode()
- {
- NumStart=NumEnd=0;
- Address=NULL;
- next=NULL;
- }
- IndexNode::IndexNode(int ns, int ne, StringNode * ad)
- {
- NumStart=ns; NumEnd=ne; Address=ad;
- next=NULL;
- }
- char * ChangeFileExt(const char * fn, const char * fext)
- {
- int l=strlen(fn);
- int le=strlen(fext);
- for(int i=l-1; fn[i]!='.' && fn[i]!='//' && fn[i]!='/' && fn[i]!=':' && i>=0; i--);
- char * fnext;
- //如果没扩展名
- if(i<=0||fn[i]=='/-:special:2:-||fn[i]=='/'||fn[i]==':')
- {
- fnext=new char[l+le+2];
- strcpy(fnext,fn);
- fnext[l]='.';
- l++;
- strcpy(fnext+l,fext);
- }
- else
- {
- l=i+1;
- fnext=new char[l+le+1];
- strcpy(fnext,fn);
- strcpy(fnext+l,fext);
- }
- //申请新文件名的存储空间
- return fnext;
- }
- bool IsNumeric(const char * val)
- {
- for(int i=0;val[i]!='/0';i++)
- {
- if(val[i]<'0'||val[i]>'9')
- return false;
- }
- return true;
- }
3. 主程序源文件 Mps.cpp
- #include <stdio.h>
- #include <string.h>
- #include <conio.h>
- #include <windows.h>
- #include "Global.h"
- #define LINE_BUFFER_SIZE 256
- //在字符串链表中搜索字符串,返回节点指针
- inline StringNode * FindString(StringNode * st, const char * str)
- {
- for(StringNode * ps=st; ps!=NULL; ps=ps->next)
- {
- if(strcmp(ps->value,str)==0)
- return ps;
- }
- return NULL;
- }
- //文本数据 -> 二进制数据文件
- void MpDataConvert(const char * fnin, const char * fnout)
- {
- FILE * fpin=fopen(fnin,"rb"); //输入文件
- if(!fpin)
- {
- printf("打开文件失败!/n");
- return;
- }
- printf("正在导入文件 [%s] 到 [%s] ... ",fnin,fnout);
- StringNode * stringTable;
- IndexNode * indexTable;
- StringNode * ps;
- IndexNode * p;
- int numLast; //上一行的号码
- int numRead; //当前读取的号码
- char * addrRead=new char[LINE_BUFFER_SIZE];
- int sfCount=0; //源文件记录计数
- bool isFirst=true;
- while(!feof(fpin))
- {
- fscanf(fpin,"%d,%s",&numRead,addrRead); sfCount++;
- //首记录处理
- if(isFirst)
- {
- ps=stringTable=new StringNode(addrRead);
- ps->next=NULL;
- p=indexTable=new IndexNode(numRead,0,ps);
- p->next=NULL;
- isFirst=false;
- //保存本次读取的号码以便读下一行时用到
- numLast=numRead;
- continue;
- }
- //如果地址未变
- if(strcmp(p->Address->value,addrRead)==0)
- {
- //保存本次读取的号码以便读下一行时用到
- numLast=numRead;
- continue;
- }
- //如果地址变了
- else
- {
- //完成前一条记录
- p->NumEnd=numLast;
- //开始新记录
- StringNode * s=FindString(stringTable,addrRead);
- if(s==NULL)
- {
- ps=ps->next=new StringNode(addrRead);
- s=ps;
- }
- p=p->next=new IndexNode(numRead,0,s);
- //保存本次读取的号码以便读下一行时用到
- numLast=numRead;
- }
- }
- p->NumEnd=numLast;
- //关闭源文件
- fclose(fpin);
- /***********************************************/
- //FILE * fps=fopen("StringTable.txt","w");
- int j=0;
- for(p=indexTable;p!=NULL;p=p->next)
- {
- //printf("%d %d %s/n",p->NumStart,p->NumEnd,p->Address->value);
- j++;
- }
- int k=0;
- for(ps=stringTable;ps!=NULL;ps=ps->next)
- {
- //printf("%s/n",ps->value);
- //fprintf(fps,"%s/n",ps->value);
- k++;
- }
- /***********************************************/
- /***********************************************/
- //导入数据文件
- FILE * fpout=fopen(fnout,"wb");
- int header[2]={0,0}; //文件头
- fwrite(&header,sizeof(header),1,fpout);
- int pos=ftell(fpout);
- //写入字符串表
- for(ps=stringTable;ps!=NULL;ps=ps->next)
- {
- pos=ftell(fpout);
- ps->offset=pos;
- fwrite(ps->value,1,ps->length+1,fpout);
- }
- //写入索引记录表
- pos=ftell(fpout);
- header[0]=pos;
- IndexStruct is;
- for(p=indexTable;p!=NULL;p=p->next)
- {
- pos=ftell(fpout);
- is.NumStart=p->NumStart;
- is.NumEnd=p->NumEnd;
- is.Offset=p->Address->offset;
- fwrite(&is,sizeof(is)-1,1,fpout);
- }
- pos=ftell(fpout);
- header[1]=pos-(sizeof(is)-1);
- //重写文件头
- fseek(fpout,0,SEEK_SET);
- fwrite(&header,sizeof(header),1,fpout);
- //获取数据文件大小
- fseek(fpout,0,SEEK_END);
- pos=ftell(fpout);
- //关闭文件
- fclose(fpout);
- printf("导入成功!/n");
- printf("源文件记录数: %d/n",sfCount);
- printf("目标记录总数: %d/n",j);
- //fprintf(fps,"记录总数: %d/n",j);
- printf("字符串记录数: %d/n",k);
- //fprintf(fps,"字符串数: %d/n",k);
- //fclose(fps);
- printf("目标文件大小: %d字节/n",pos);
- /***********************************************/
- //printf("/n按任意键退出...");
- //getch();
- }
- //获取号码段记录在文件中的偏移量
- inline int getIndexOffset(FILE * fp, int fo, int lo, int num)
- {
- int mo; //中间偏移量
- int mv; //中间值
- int fv,lv; //边界值
- int llv; //边界末末值
- fseek(fp,fo,SEEK_SET);
- fread(&fv,sizeof(fv),1,fp);
- fseek(fp,lo,SEEK_SET);
- fread(&lv,sizeof(lv),1,fp);
- fread(&llv,sizeof(llv),1,fp);
- //边界检测处理
- if(num<fv)
- return -1;
- else if(num>llv)
- return -1;
- //使用"二分法"确定记录偏移量
- do
- {
- mo=fo+(lo-fo)/(sizeof(IndexStruct)-1)/2*(sizeof(IndexStruct)-1);
- fseek(fp,mo,SEEK_SET);
- fread(&mv,sizeof(mv),1,fp);
- if(num>=mv)
- fo=mo;
- else
- lo=mo;
- if(lo-fo==sizeof(IndexStruct)-1)
- mo=lo=fo;
- } while(fo!=lo);
- return mo;
- }
- //查询号码,返回号码段和归属地信息
- MpLocation GetMpLocation(const char * fn, int num)
- {
- FILE * fp=fopen(fn,"rb");
- if(!fp)
- throw "打开数据文件失败!";
- int fo,lo;
- //读文件头,获取首末记录偏移量
- fread(&fo,sizeof(fo),1,fp);
- fread(&lo,sizeof(lo),1,fp);
- int rcOffset=getIndexOffset(fp,fo,lo,num);
- MpLocation mpl;
- if(rcOffset>=0)
- {
- fseek(fp,rcOffset,SEEK_SET);
- //读取号码段起始地址和结束地址
- fread(&mpl.NumStart,sizeof(mpl.NumStart),1,fp);
- fread(&mpl.NumEnd,sizeof(mpl.NumEnd),1,fp);
- //如果查询的号码处于中间空段
- if(num>mpl.NumEnd)
- {
- mpl.NumStart=0; mpl.NumEnd=0;
- mpl.Location="未知地址";
- }
- else
- {
- //读取字符串偏移量,3字节!
- int lstrOffset=0;
- fread(&lstrOffset,3,1,fp);
- lstrOffset&=0x00ffffff;
- fseek(fp,lstrOffset,SEEK_SET);
- //读取归属地字符串
- static char strBuf[48];
- fread(strBuf,sizeof(strBuf),1,fp);
- //检验字符串边界
- for(int i=0;strBuf[i]!='/0'&&i<sizeof(strBuf);i++);
- if(i==sizeof(strBuf)) strBuf[sizeof(strBuf)-1]='/0';
- mpl.Location=new char[strlen(strBuf)+1];
- strcpy(mpl.Location,strBuf);
- }
- }
- else
- {
- //没找到记录
- mpl.NumStart=0; mpl.NumEnd=0;
- mpl.Location="未知地址";
- }
- fclose(fp);
- return mpl;
- }
- //号码查询程序
- void MpLocating(const char * fn, char * sNum)
- {
- int num=0;
- if(!IsNumeric(sNum))
- {
- printf("请输入7位手机号!/n");
- }
- else
- {
- sscanf(sNum,"%7d",&num);
- try
- {
- MpLocation mpl=GetMpLocation(fn,num);
- printf("号码段: %07d - %07d/n",mpl.NumStart,mpl.NumEnd);
- printf("归属地: %s/n",mpl.Location);
- }
- catch(char * e)
- {
- printf("%s/n",e);
- }
- }
- }
- //显示帮助信息
- inline void printHelp()
- {
- const char * en="Mps";
- printf("手机归属地查询程序./n/n");
- printf("查询归属地: %s <号码前七位>/n",en);
- printf("导入数据库: %s -c <数据源文件名>/n",en);
- printf("/n示例:/n");
- printf(" > %s -c MpData.txt 导入MpData.txt到MpData.dat/n",en);
- printf(" > %s 1358348 查询号段1358348的归属地/n",en);
- printf("/n提示: 查询归属地时请把数据库文件MpData.dat与本程序放在同一目录下./n");
- }
- //===================主程序入口===================
- void main(int argc, char * argv[])
- {
- /***********************************************************
- argc=2;
- argv[0]="Mps.exe";
- argv[1]="MpLocator.txt";
- ************************************************************/
- //数据文件名
- const char * fnData="MpData.dat";
- if(argc>1)
- {
- char opcode='s'; //操作码 's'为查询号码, 'c'为导入数据
- char * val=""; //参数值
- //获取操作码和参数值
- for(int i=1;i<argc;i++)
- {
- if(argv[i][0]=='-')
- opcode=argv[i][1];
- else
- val=argv[i];
- }
- //操作选择
- switch(opcode)
- {
- case 's':
- //查询号码
- MpLocating(fnData,val);
- break;
- case 'c':
- //导入数据
- MpDataConvert(val,ChangeFileExt(val,"dat"));
- break;
- case 'h':
- //帮助信息
- printHelp();
- break;
- default:
- //无操作
- break;
- }
- }
- else
- {
- //直接双击运行
- char inputBuf[32];
- while(true)
- {
- printf("手机号前7位: ");
- fgets(inputBuf,32,stdin);
- if(inputBuf[strlen(inputBuf)-1]=='/n')
- inputBuf[strlen(inputBuf)-1]='/0';
- //如果接收到空字符串则退出
- if(strlen(inputBuf)==0)
- break;
- MpLocating(fnData,inputBuf);
- printf("/n");
- }
- //保持屏幕5秒钟
- //Sleep(5000);
- }
- }
完整的源代码及数据文件请从这里下载: http://download.csdn.net/source/611741
(原创文章,转载时请注明本文网址)
手机号归属地数据导入及查询工具源代码(C++)相关推荐
- 号码归属地及运营商查询工具
号码归属地及运营商查询工具 import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phone ...
- 02_clickhouse安装,卸载,启动/关闭服务,交互式命令(数据库创建,数据导入,查询),批模式数据导入,MySQL接口操作ClickHouse,DBeaver可视化工具安装与使用(学习笔记)
1 ClickHouse安装 安装文件清单 clickhouse-client-${version}.noarch.rpm clickhouse-common-static-dbg-${version ...
- Solr 7 - 中文分词、数据导入、查询 基本使用篇
接着之前的 Solr 7 - CentOS 部署篇 继续 Go! 准备一下 /opt/solr-7.6.0 实际安装目录 /opt/solr 指向实际安装目录的链接 我们先链接一份 solr 命令到 ...
- Elasticsearch+Mongo亿级别数据导入及查询实践
数据方案: 在Elasticsearch中通过code及time字段查询对应doc的mongo_id字段获得mongodb中的主键_id 通过获得id再进入mongodb进行查询 1,数据情况: ...
- excel 数据导入(附工具类)
// 导入excel中的数据到数据库中@PostMapping(value = "importHDangerRecord")@Overridepublic RestMessage ...
- TDSQL“相似查询工具MSQL+”入选VLDB论文
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云数据库 TencentDB发表于云+社区专栏 作者介绍:王晓宇,腾讯数据库TDSQL团队成员,目前参与TDSQL数据库内核研发工 ...
- TDSQL“相似查询工具MSQL+”入选VLDB论文 1
腾讯与高校合作的论文入选数据库顶会 腾讯TDSQL团队携手中国人民大学信息学院.武汉大学计算机学院合作的DEMO论文"MSQL+: a Plugin Toolkit for Similari ...
- 基于delphi的excel数据导入导出
因为淘宝客户的一个小需求,写了一个"基于delphi 7的excel数据导入导出"小工具.为了抛砖引玉,将这个小工具分享出来.希望对初学者和用得到的朋友有点点小小的帮助.oracl ...
- 使用Python将Excel中的数据导入到MySQL
使用Python将Excel中的数据导入到MySQL 工具 Python 2.7 xlrd MySQLdb 安装 Python 对于不同的系统安装方式不同,Windows平台有exe安装包,Ubunt ...
最新文章
- C#的6种常用集合类大比拼【月儿原创】
- 【C/C++】中的__FILE__、__LINE__、#line、__func__关键字(预定义宏)
- Powerup tinyos接口实现
- A Full Hardware Guide to Deep Learning
- Jackson用法详解
- ddos常见攻击报文
- ppt 2 html工具,PPTools PPT2HTML
- 如何使用 volatile, synchronized, final 进行线程间通信
- 终止正在运行的VBS脚本
- 当你使用R安装包出现rdb is corrupt问题的时候
- 从AssetBundle中获取图片,给Image 组件替换Sprite
- spring用的是哪种工厂模式_业务复杂就用 ifelse?刚来的技术大佬用这招彻底干掉了!...
- cs231n-svm作业
- A8. 无人机编队飞行定位分析与讨论-大结局
- arduino下载库出错_关于程序下载到最后卡住了以及自带库不能用的问题!!
- PLC数据采集之协议转换桥接器
- qq for android 1.0,QQ for Pad 1.0正式发布 Android专版
- 公众号开发:实现一键复制功能
- STM32F401 / STM32F411 WeAct Studio 资料以及翻版说明
- Excel做曲线拟合