我正在编写一个用于类分配的程序,该程序测试具有3个不同的双哈希函数(例如1 / 1、1 / 2、1 / 3、2 / 1、2 / 2等)的3个哈希函数,并且最终目标是按照我的教授的说明,通过控制台命令“ exename> Results.txt”将每个配对的测试结果输出到一个文件中。我即将进行最终测试,但是我的程序将进入主程序,一次完成嵌套的for循环,输出第一个哈希函数对的测试结果,然后该程序无任何错误地结束。我已经将Visual Studio 12的调试器弄糟了几个小时,并且比我刚开始时更找不到解决方案。当我通过控制台运行该程序时,它会输出“无法打开数据文件。程序终止”,即使在单步执行该程序时也从未进入过for循环。有任何想法吗?谢谢!
P.S。我知道该程序中使用的某些方法可能是非常规的,或者不一定是实现此方法的最简单/最佳方法,但是我必须限制在教授的标准之内。
更新:我在getline的forline循环中添加了一条提示行,现在可以看到测试完成了一次,然后在它的下一次重复执行for循环41次,然后退出,而不是全部完成了50次。到达某个地方。
这是我的输出:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950950ERROR1 使用双哈希1测试哈希函数1。总冲突= 360。 ||||||| ------------------------------------- |||||| ||||||||| --------- ||||||||||||||| ------------ ||||||||||||||
1234567891011121314151617181920212223242526272829303132333435363738394041
#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#include <string.h>
#define TABLESIZE 100
#define KEYSIZE 4
#define EMPTYKEY "----"
#define DATAFILE "P4DATA.txt"
using namespace std;
struct HashStruct
{
char key[5];
int data;
};
void InitTable(HashStruct hashT[], int TableSize);
int Hash_1(char *key);
int Hash_2(char *key);
int Hash_3(char *key);
int ProbeDec_1(char *key);
int ProbeDec_2(char *key);
int ProbeDec_3(char *key);
int HashInsert(HashStruct T[], char *key, int data, int hNum, int dhNum);
int main(void){
int hashNum, dHashNum, count;
ifstream *inFile;
HashStruct T[100]; // Hash table srray of 100 data structures
char line[64];// Array to hold lines read from file
char key[5]; // Array to hold 4-character keys
int data; // Integer data
char filename[15];
strcpy(filename, DATAFILE);
for(hashNum = 0; hashNum < 3; hashNum++){
for(dHashNum = 0; dHashNum < 3; dHashNum++){
InitTable(T, TABLESIZE);
inFile = new ifstream();
inFile->open(filename, ifstream::in);
if(!inFile->is_open()){
cout << "Unable to open data file. Program terminating\n";
return 0;
}
count = 0;
for(int i = 0; i < 50; i++){
inFile->getline(line, 64, '\n');
sscanf(line, "%s %d", key, &data);
count += HashInsert(T, key, data, hashNum, dHashNum);
}
cout << "Testing hash function " << hashNum + 1 << " using double hash " << dHashNum + 1 << ".\n";
cout << "Total collisions = " << count << ".\n";
for(int i=0; i < 100; i++){
if(strcmp(T[i].key, EMPTYKEY))
cout << "|";
else
cout << "-";
}
cout << "\n\n";
inFile->close();
delete inFile;
}
}
return 1;
}
int HashInsert(HashStruct T[], char *key, int data, int hNum, int dhNum){
int testNum = (hNum * 3) + dhNum;
int colCount = 0;
int hashIndex, probeDec;
switch(testNum){
case 0 : // Hash function 1 -- Double hash 1 (linear probing)
hashIndex = Hash_1(key);
probeDec = ProbeDec_1(key); // Function just returns 1
break;
case 1 : // Hash function 1 -- Double hash 2
hashIndex = Hash_1(key);
probeDec = ProbeDec_2(key);
break;
case 2 : // Hash function 1 -- Double hash 3
hashIndex = Hash_1(key);
probeDec = ProbeDec_3(key);
break;
case 3 : // Hash function 2 -- Double hash 1 (linear probing)
hashIndex = Hash_2(key);
probeDec = ProbeDec_1(key); // Function just returns 1
break;
case 4 : // Hash function 2 -- Double hash 2
hashIndex = Hash_2(key);
probeDec = ProbeDec_2(key);
break;
case 5 : // Hash function 2 -- Double hash 3
hashIndex = Hash_2(key);
probeDec = ProbeDec_3(key);
break;
case 6 : // Hash function 3 -- Double hash 1 (linear probing)
hashIndex = Hash_3(key);
probeDec = ProbeDec_1(key); // Function just returns 1
break;
case 7 : // Hash function 3 -- Double hash 2
hashIndex = Hash_3(key);
probeDec = ProbeDec_2(key);
break;
case 8 : // Hash function 3 -- Double hash 3
hashIndex = Hash_3(key);
probeDec = ProbeDec_3(key);
break;
}
while(strcmp(T[hashIndex].key, EMPTYKEY) != 0){
colCount++;
hashIndex -= probeDec; // Decrementing was chosen you could also choose to
if(hashIndex < 0) // increment and wrap back to the beginning of the table.
hashIndex = hashIndex + TABLESIZE;
}
strcpy(T[hashIndex].key, key);
T[hashIndex].data = data;
return colCount;
}
void InitTable(HashStruct hashT[], int TableSize){
int i;
for(i=0; i<TableSize; i++){
strcpy(hashT[i].key, EMPTYKEY);
hashT[i].data = 0;
}
}
int Hash_1(char *key){
int hash = 0;
int prime = 29;
int index = 0;
for(int i = 0; i < 4; i++){
hash = (key[i]-'0')*prime;
for(int j = (3-i); j > 0; j--){
hash *= prime;
}
}
index = hash % TABLESIZE;
return index;
}
int Hash_2(char *key){ // Folding
int hash = 0;
int index = 0;
hash = (((key[0]-'0')+(key[1]-'0'))*37) +
(((key[1]-'0')+(key[2]-'0'))*47) +
(((key[2]-'0')+(key[3]-'0'))*67);
index = hash % TABLESIZE;
return index;
}
int Hash_3(char *key){ //Middle Squaring
int hash = 0;
int index = 0;
hash = ((key[1]-'0') + (key[2]-'0'));
hash *= hash;
index = hash % TABLESIZE;
return index;
}
int ProbeDec_1(char *key){
return 1;
}
int ProbeDec_2(char *key){
int dhash = 0;
int index = 0;
dhash = ((key[0]-'0')*97) + ((key[1]-'0')*83);
index = dhash % TABLESIZE;
return index;
}
int ProbeDec_3(char *key){
int dhash = 0;
int index = 0;
dhash = (((key[0]-'0')*29) + ((key[1]-'0')*59) +
((key[2]-'0')*79) + ((key[3]-'0')*89));
index = dhash % TABLESIZE;
return index;
}
答案 0 :(得分:0)
在这段代码中有很多错误的检查,我只是其中一部分。
for(int i = 0; i < 50; i++){
inFile->getline(line, 64, '\n');
sscanf(line, "%s %d", key, &data);
count += HashInsert(T, key, data, hashNum, dHashNum);
}
第1 + 2行:太多的幻数,如果将50、64和4混合使用,则会出错。
第3行:sscanf非常强大,但由于您不知道字符串的返回值有多长,因此有些不安全,一种方法是使字符串数组与读取的行一样长。
第2 + 3行的返回值未选中。
char key[MAXLineLength];
const int LinesToRead = 100; // your hash array is 100, but you read only 50
const int NUMFIELDS = 2;
const int ERROR = -1; // there is a system return somewhere that is more correct.
for(int i = 0; i < LinesToRead ; i++){
inFile->getline(line, MAXLineLength, '\n');
if (!inFile->good())
return ERROR;
if (NUMFIELDS != sscanf(line, "%s %d", key, &data))
return ERROR;
if (strlen(key)!=4)
return ERROR;
count += HashInsert(T, key, data, hashNum, dHashNum);
}