题目是这样的:
开心网的自助广告系统于2010年8月上线发布,通过该系统,中小企业或创业型团队可以面向开心网不同地区、年龄、性别的用户进行精准且低成本的广告投放,从而帮助其更好地提升品牌价值、开展市场营销活动。
在自助广告系统中,用户的地域、年龄、性别等属性都是重要因素,为了更加精准地区分不同地域的用户,除了用户的既有属性之外,还可以根据用户的IP地址进行地域转换。此转换由于是在用户访问时实时执行,所以对性能的要求非常高。
假设你是开心网的工程师,请实现此种转换。
输入:
两个文本文件,一个是IP库文件(ipbase.txt),所有IP地址均为IPV4 IP地址,文件为GBK编码, 格式是一行一个IP范围与地址的映射。分为三列,第一列是起始IP,第二列是结束IP,第三列是此范围内的IP(含起始IP和结束IP)对应的地址,列之间以制表符分隔。另一个文件是要查询的IP文件(ipcheck.txt) ,每行为一个IP地址。
输出:
每行输出一个查询结果,格式为:查询的IP 对应的地址(以制表符分隔)。
示例:
IP库文件:
61.50.219.42 | 61.50.221.33 | 北京 |
61.50.221.34 | 61.50.221.34 | 北京 |
61.50.221.35 | 61.50.221.42 | 北京 |
222.33.75.18 | 222.33.75.255 | 辽宁 |
222.33.76.0 | 222.33.77.255 | 辽宁 |
222.33.78.0 | 222.33.79.129 | 辽宁 |
222.33.79.130 | 222.33.79.130 | 辽宁 |
222.33.79.131 | 222.33.84.105 | 辽宁 |
222.33.84.106 | 222.33.84.106 | 辽宁 |
222.36.52.37 | 222.36.52.37 | 天津 |
222.36.52.38 | 222.36.52.224 | 天津 |
222.36.52.225 | 222.36.52.225 | 天津 |
222.36.52.226 | 222.36.64.219 | 天津 |
222.36.64.220 | 222.36.64.220 | 天津 |
要查询的IP文件:
61.50.221.34
222.33.76.2
222.33.75.18
222.33.75.19
得到如下结果:
61.50.221.34 北京
222.33.76.2 辽宁
222.33.75.18 辽宁
222.33.75.19 辽宁
我的机子比较差劲试运行了一下在给的测试文件情况下生成了50K的文本result.txt 结果耗时170ms
热诚期盼大虾高手指导
实现代码如下:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <vector>
#include <time.h>
using namespace std;
typedef unsigned int UINT;
typedef struct{
UINT start;
UINT close;
string LocId;//以后再改int,先测试
}IpNode;//IP 地址结构体
static UINT NUM_IPS = 10000;//文件行数
void resolveIp(UINT& temp, string IP){//IP 格式为4.0.0.0,转化后从temp返回
temp = 0; int pos = -1; int prepos = 0;
for(int i = 0; i < 4; i++){
int shift = 24 - 8*i;
prepos = pos + 1;
pos = IP.find_first_of(".",prepos);
temp += (atoi(IP.substr(prepos,pos).c_str()) << shift);
}
}
int main(int argc , char* argv[])
{
clock_t start, finish;//声明时间
start=clock();//开始时间
char* input = argv[1];
char* intha = argv[2];
//cout<< input<<endl<<intha;
//string* IpLoc = new string[NUM_IPS];//用来做地址存储以后map查找
//IpNode* nodes = new IpNode[NUM_IPS];
vector<IpNode> nodes(NUM_IPS);
ifstream inf(input);
if(! inf){
cerr<<"Could not open ipbase.txt" << endl;
exit(EXIT_FAILURE);
}
int i;//计数有多少行
for(i = 0; !inf.eof(); i++) {//暂时这样,不能标志到文件结尾
if(i >= NUM_IPS )
{ NUM_IPS += 1000;
nodes.resize(NUM_IPS);
}
string Ip;
inf >> Ip;//4.0.0.0
resolveIp(nodes[i].start, Ip);
inf >> Ip;
resolveIp(nodes[i].close, Ip);
inf >> Ip;
nodes[i].LocId = Ip;
}
NUM_IPS = i;//重新定长度
//从文件中读入IP输出地址
inf.close();
ifstream read(intha);
ofstream out("result.txt");
if(! read){
cerr<<"Could not open ipcheck.txt" << endl;
exit(EXIT_FAILURE);
}
string IP[2000];UINT k = 0;
for(UINT j = 0; !read.eof(); j++){
if(j < 2000){
read >> IP[k];
UINT temp = 1;
resolveIp(temp, IP[k]);
UINT l = 0; UINT u = NUM_IPS-1; UINT m;
if(temp ==0)break;
for(;;){
if(l > u){break;}
m = (l+u)/2;
if(nodes[m].close < temp)
l = m +1;
else if(nodes[m].start >temp)
u = m -1;
else if(nodes[m].start <= temp && nodes[m].close >=temp){
out<<IP[k]<<"/t"<<nodes[m].LocId<<endl;
break;
}
}
k++;
}
else{
k = 0;
}
}
flush(cout);
out.close();
finish=clock();//结束时间
cout<<endl<<(double)(finish-start)<<endl;
}