⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mps.cpp

📁 手机归属地数据文件格式是自己定义的
💻 CPP
字号:
/************************************************************
手机号归属地数据导入及查询工具源代码(C++)
  Author: rssn
  Email : rssn@163.com
  QQ    : 126027268
  Blog  : http://blog.csdn.net/rssn_net/
 ************************************************************/

#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
#include "Global.h"

#define LINE_BUFFER_SIZE 256

//在字符串链表中搜索字符串,返回节点指针,若无则返回NULL
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);
	}
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -