c++ - C++程序结束而不是重复for循环
问题描述
我正在编写一个用于类分配的程序,该程序使用 3 个不同的双哈希函数(如 1/1、1/2、1/3、2/1、2/2 等)测试 3 个哈希函数,以及最终目标是按照我的教授的指示,通过控制台命令“exename > Results.txt”将每个配对的测试结果输出到文件中。我即将进入最终测试,但我的程序将进入 main,完成一次嵌套 for 循环,输出第一个哈希函数配对的测试结果,然后程序结束,没有错误。我已经将 Visual Studio 12 的调试器搞砸了好几个小时,并且与我刚开始时相比,我离找到解决方案还差得远。当我通过控制台运行程序时,它会输出“无法打开数据文件。程序终止”,即使在单步执行程序时它从未进入该 for 循环。有任何想法吗?谢谢!
PS我知道这个程序中使用的一些方法可能是非常规的,或者不一定是实现这一点的最简单/最好的方法,但我需要限制在我教授的标准范围内。
更新:我在 getline for 循环中添加了一条 cout 行,现在可以看到测试完成了一次,然后下一次围绕它重复 for 循环 41 次并退出而不是完成所有 50 次。看起来我们到了某个地方。
这是我的输出:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950ERROR1 使用双重哈希测试哈希函数 1。总冲突 = 3.||||||---------------------------- ---------|||||||||||||||-----|||||||||||||||------ --|||||||||||||
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;
}
解决方案
这段代码有很多不好的检查,我只做一部分。
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);
}
推荐阅读
- javascript - document.querySelector().getAttribute() 没有获得新的内容元名称
- ios - (Swift)如何在切换开关打开时隐藏 tableView 中的某些部分?
- javascript - Javascript:在块内初始化“让”变量的位置是否重要?
- delphi - 在 IIS 中托管 RAD 服务器。未找到 EMS 许可证
- angular - 如何在使用 location.go() 方法时设置查询参数
- ios - 健康应用程序中的重复数据条目
- iot - 是否可以将 micro: bit 板连接到岩石上,并让它计算它被抛到空中的次数?
- git - Git pull vs Git Rebase 头部版本
- java - OnCreate 中的 PopupWindow 与 ShowAtLocation - 如何获取父视图?
- react-native - 简化样式更改 onPress React Native