各位大神帮忙修改一下程序,感激不尽。急!

cs小亮 2013-06-06 09:00:55
程序实现功能:
1、连接数据库dnsdata,从表domain_name中查询待检测域名(字符串)
2、查询出的域名去和表million_doamin_name表中的域名比较,计算相似度,然后对得到的相似度排序,得到与源字符串最相似的,输出这个对应关系
3、计算相似度用的算法是编辑距离,排序是堆排序,我用一个结构体保存目标域名和相似度的对应关系
4、自己写了一个函数parse_name用来分割域名,只提取二级域名,如www.baidu.com中的baidu
问题:
1、程序运行到parse_name时会出现段错误,而这个函数单独拿出来测试可以通过
2、感觉这个程序问题不少,但是别人急着要使用这个程序做后续的工作,求大神们帮我提以下修改方案,我几乎把分都用了,希望能解决问题(个人编程能力较弱)
#include <stdlib.h>
#include <stdio.h>
#include <mysql/mysql.h>
#include <syslog.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
MYSQL mysql;

struct domain
{
char *name;
float data;
};

void sift(float a[], int i, int n)
{
int child;
float tmp;
for (tmp = a[i]; n >= 2 * i; i = child)
{
child = 2 * i;
if (child != n && a[child + 1] < a[child])
{
child++;
}
if (tmp > a[child])
{
a[i] = a[child];
}
else break;
}
a[i] = tmp;
}

void heapsort(float a[], int n)
{
int i;
float tmp;
for (i = n / 2; i >= 1; i--)
{
sift(a, i, n);
}
for (i = n; i >= 2; i--)
{
tmp = a[1];
a[1] = a[i];
a[i] = tmp;

sift(a, 1, i-1);
}
}

int min(int a,int b,int c)
{
if(a<b&&a<c)
return a;
else if(b<a&&b<c)
return b;
else
return c;
}
int max(int x,int y)
{
int z;
if(x>y)
{
z=x;
}
else
{
z=y;
}
return z;
}

int distance(char *strA,char *strB)
{
int m=strlen(strA);
int n=strlen(strB);
int d[m+1][n+1];
int i,j,x,y,z;
for(i=0; i<=m; i++)
d[i][0] = i;
for(j=1; j<=n; j++)
d[0][j] = j;
for(i=1; i<=m; i++)
for(j=1; j<=n; j++)
{
x = d[i-1][j]+1;
y = d[i][j-1]+1;
if(strA[i] == strB[j])
z = d[i-1][j-1];
else
z = d[i-1][j-1]+1;
d[i][j] = min(x,y,z);
}
return d[m][n];
}

void parse_name(char* sour,char *dest)
{
char seps[] = ".";
char* token;
int j = 0;
char* arr[10];

token = strtok(sour, seps);
while(token != NULL)
{
arr[j] = (char*)malloc(512);
strcpy(arr[j], token);
j++;
token = strtok(NULL, seps);
}
dest= arr[j - 2];
}

void doquerysimilar(char str[])
{
int i,k,row;
MYSQL_ROW m_row;
MYSQL_RES *m_res;
char sql[1024];
char dname[128]="";
char pattern[128]="";

parse_name(str,dname);
sprintf(sql,"select Idomain from million_domain_name order by id limit 0,100");
if(mysql_query(&mysql,sql) != 0)
{
fprintf(stderr, "mysql_query err: %s",mysql_error(&mysql));
}
m_res = mysql_store_result(&mysql);
row = mysql_num_rows(m_res)+1;
float sim[row];
struct domain dom[row];
if(m_res==NULL)
{
fprintf(stderr, "get result err: %s",mysql_error(&mysql));
}

for(i=0; i<row; i++)
{
m_row = mysql_fetch_row(m_res);
if(m_row!=NULL)
{
dom[i].name=m_row[0];
parse_name(m_row[0],pattern);
k=distance(dname,pattern);
sim[i]=1-(float)k/max(strlen(dname),strlen(pattern));
dom[i].data=sim[i];

}
}
heapsort(sim,row);
for(i=0; i<row; i++)
{
if(dom[i].data==sim[0]&&sim[0]>0.7&&sim[0]<1.0)
{
printf("%s is similar to %s\n",str,dom[i].name);
}
}

mysql_free_result(m_res);

}

void doQuery()
{
int i,row;
MYSQL_ROW m_row;
MYSQL_RES *m_res;
char sql[1024];

sprintf(sql,"select domain from domain_name order by id limit 0,30000");
if(mysql_query(&mysql,sql) != 0)
{
fprintf(stderr, "mysql_query err: %s",mysql_error(&mysql));
}
m_res = mysql_store_result(&mysql);
row = mysql_num_rows(m_res)+1;


if(m_res==NULL)
{
fprintf(stderr, "get result err: %s",mysql_error(&mysql));
}


for(i=0; i<row; i++)
{
m_row = mysql_fetch_row(m_res);
if(m_row!=NULL)
doquerysimilar(m_row[0]);
}
mysql_free_result(m_res);

}

int main()
{
char host[32] = "localhost";
char user[32] = "root";
char passwd[32] = "123";
char db[32] = "dnsdata";
if( mysql_init(&mysql) == NULL )
{
fprintf(stderr,"Init mysql err!");
return 0;
}
if (mysql_real_connect(&mysql,host,user,passwd,db,0,NULL,0) == NULL)
{
fprintf(stderr,"Connect to mysql Error:%s!",mysql_error(&mysql));
return 0;
}
else
{
puts("Connect to mysql success!");
}

doQuery();
mysql_close(&mysql);
return 0;
}
...全文
127 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
Ericz 2013-06-06
  • 打赏
  • 举报
回复
这么做肯定提高不少速度,不过这个方法有几个问题需要注意: 1.从数据库得到数据之后存储在内存中使用,如果数据库中的数据更新了,那么内存相应的数据也应该更新。 2.缓存数据的策略。
引用 3 楼 u010418986 的回复:
[quote=引用 1 楼 zhou19891113 的回复:] 下面是你写的parse_name函数的解析: 该函数的参数没有参数检查就直接使用并且该函数不是static的,那我认为该函数是外部接口,也有风险存在 while(token != NULL) { arr[j] = (char*)malloc(512); 在这里分配了内存空间,程序效率很低 strcpy(arr[j], token); 在这里又copy,效率又降低。 j++; token = strtok(NULL, seps); } dest= arr[j - 2]; 没有释放上面分配的空间,出现严重的内存泄露。
谢谢你的解析,我还有个问题,每次目标表中的串比较的时候,都要再从数据库中取一遍数据,这样效率是不是很低,是不是应该一开始定义一个全局集合存这些目标串,然后比较的时候就直接操作集合,这样会好一点吗?[/quote]
cs小亮 2013-06-06
  • 打赏
  • 举报
回复
引用 1 楼 zhou19891113 的回复:
下面是你写的parse_name函数的解析: 该函数的参数没有参数检查就直接使用并且该函数不是static的,那我认为该函数是外部接口,也有风险存在 while(token != NULL) { arr[j] = (char*)malloc(512); 在这里分配了内存空间,程序效率很低 strcpy(arr[j], token); 在这里又copy,效率又降低。 j++; token = strtok(NULL, seps); } dest= arr[j - 2]; 没有释放上面分配的空间,出现严重的内存泄露。
谢谢你的解析,我还有个问题,每次目标表中的串比较的时候,都要再从数据库中取一遍数据,这样效率是不是很低,是不是应该一开始定义一个全局集合存这些目标串,然后比较的时候就直接操作集合,这样会好一点吗?
Ericz 2013-06-06
  • 打赏
  • 举报
回复
在不改变你代码逻辑的情况下,我认为这样实现更好一些:

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

#define SLD_SHIFT 2
#define SLD_MAX 512
#define SLD_SEPARATOR '.'
int parse_name(const char *sour,char *dest)
{
	int len = 0; 
	int i = 0;
	const char *pch = NULL; 
	assert(sour); 
	assert(dest); 

	len = strlen(sour); 
	pch = &sour[len]; 
	for(i = 0; i++ < SLD_SHIFT; ) {
		while((SLD_SEPARATOR != *pch) && (sour != pch)) {
			pch--;
		}
		if(sour == pch) {
			break; 
		}
		if(SLD_SHIFT > i) {
			while(SLD_SEPARATOR == *--pch) {
				/* no thing */
			}
		}
	}
	if(SLD_SHIFT > i) {
		return 1;   /* 没找到分隔符 */
	}

	if(sour != pch) {
		pch += 1; 
	}

	while(SLD_SEPARATOR != (*dest++ = *pch++)) {
		
	}
	dest--; 
	*dest = '\0'; 

	return 0; 
}

Ericz 2013-06-06
  • 打赏
  • 举报
回复
下面是你写的parse_name函数的解析: 该函数的参数没有参数检查就直接使用并且该函数不是static的,那我认为该函数是外部接口,也有风险存在 while(token != NULL) { arr[j] = (char*)malloc(512); 在这里分配了内存空间,程序效率很低 strcpy(arr[j], token); 在这里又copy,效率又降低。 j++; token = strtok(NULL, seps); } dest= arr[j - 2]; 没有释放上面分配的空间,出现严重的内存泄露。

69,336

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧