大作业常见问题

大作业常见问题

基本注意事项

从命令行输入作为需要返回的检索结果数量NUM和作为检索的关键词串K1,K2,…,Km

  • 注意是从命令行读入,而不是标准输入
  • 命令行输入时,argv[0]是当前程序的路径,在本题中不需要考虑;argv[1]num,从argc[2]argv[argc-1]为关键词。

若找到的网页文档数(即Sim值大于0的文档数,即包含所给关键词的文档数)少于NUM,则按实际数目输出(屏幕输出也如此)。

  • 即只需要输出Sim值大于0的文档。

如果相关度Sim值相同,则按照网页序号由小到大的顺序输出!

  • 即判断排序的逻辑时,不仅要考虑Sim值的大小,还要比较文章的序号。

若某个关键词未在文档集合中出现,则不用计算其IDFk,其对所有文档的相关度都为0。

  • 若关键词的DNk为0,则跳过该关键词的相关度,否则计算时会有除0错误,或者计算出来的数为NaN。

网页文档间以换页符\f分隔。

  • 换页符只出现在网页文档间,即最后一篇文档后是没有换页符的。

输入串K1 K2 … Km中的停用词及非字典中单词将不进行相关度分析。

  • 若关键词中有停用词或者非字典词,不应该带入计算,简而言之,有没有这个关键词对结果不影响

    • 可以试试 search 100 yourselves edu news article这组命令行输入,因为yourselves是停用词,所以结果应与样例一致

    • 同时还要注意判断关键词是否是字典词()

  • 页数格式为’数字-数字’,可以用两个数字变量存储,或者直接按字符串读入

细节问题

读入

  • fgetc读入字符时,一定要用int型的变量存储
1
2
3
4
int c;
while(c = fgetc(in)) {
// do something
}
  • 读入字典词或关键词时,注意最后一个词有没有读入(用fscanf()读入时不需要考虑这个问题)
  • 检查最后一篇文章有没有读入和处理,因为最后一篇文章后没有换页符
  • 如果用fgets读标题行,一定要确定读的那一行是标题行,以下是错误示范
1
2
3
4
if(c == '\f') {
fgetc(in);// 读取换行符
fgets(...)// 读取标题行
}

以下仅供参考

1
2
3
4
5
6
if(c == '\f') {
// do something
while(!isdigit(c = fgetc(in)));
ungetc(c, in);
fgets(...);
}
  • fread读入时要保存长度,并保证结束处有结束符,在处理时要保证不超过文章长度,以下仅供参考
1
2
3
4
5
6
7
8
9
10
11
long long leng;
FILE *art = fopen("article.txt", "rb");
fseek(art, 0L, SEEK_END);
leng = ftell(art);
Art = (char *)malloc(sizeof(char) * (leng + 1));
fseek(art, 0L, SEEK_SET);
fread(Art, sizeof(char), leng + 1, art);
Art[leng] = 0;
for(i = 0; i < leng; i++) {
// do something
}

处理

  • 数组的大小要仔细考量,或者开到一定大小保证不会越界,或者在访问数组前判断下标是否越界
  • 注意数组存储下标的一致性,以下仅供参考
1
2
3
4
5
6
7
8
9
10
11
int cnt = 1;
{
if(c == '\f') {
// do something
cnt++;
}
}
{
// do something for the last article
}
qsort(arr + 1, cnt, sizeof(arr[1]), cmp);
  • 注意浮点数的计算和比较,以下也仅供参考
1
2
3
4
5
6
7
double eps = 1e-6;
int cmp(const void *v1, const void *v2) {
Nodeptr n1 = (Nodeptr)v1, n2 = (Nodeptr)v2;
if(n1->sim - n2->sim > eps) return -1;
else if(n2->sim - n1->sim > eps) return 1;
else return n1->id - n2->id;
}

数据规模

停用词文件

  • 单词个数:320
  • 最长单词长度:12

字典文件

  • 单词个数:不超过42w
  • 最长单词长度:小于50

  • 单词总个数:不超过42w
  • 不同单词数:小于1.5w
  • 最长单词长度:小于80
  • 网页数:1k
  • 测试点1命令:100 edu news article
  • 测试点2命令:100 apt and node or whale nnnnn

  • 单词总个数:不超过550w
  • 不同单词数:小于5w
  • 最长单词长度:小于80
  • 网页数:1.6w
  • 关键词个数:少于100(大胆点,应该是10个左右)

不同数据点考到的细节

这里的意思是,过了其中两个点,而剩下一个点输出错误时,没有考虑到的问题

小-1

这个点和样例是一样的

小-2

  • 输出了sim值为0的文章

  • 没有考虑关键词中出现的停用词

  • fgetc()读入时没有用int变量存储

  • fread()读入时没有设置长度和结束符(见读入部分对fread的处理)

  • fgets()读入时…建议还是不要用fgets(),用以上两种方法皆可

  • 输出时网页序号和标识号的问题

    • 标识号不一定是1-N的格式,如果是这样的话,那么读标识号将没有任何意义,小数据中符合这个规则只是因为网页数量较少
    • 序号与标识号右端数字不一定等价,例如1-1000后的文章可能从2-1开始标号

如果本地正确,但小数据点全错

  • 检查输入文件名article.txt, stopwords.txt, dictionary.txt

  • 检查输出文件名results.txt

  • 检查是否是命令行输入,以及参数位置是否正确