用C++将哈希表写入文件并从文件中恢复

Writing a Hash Table to File and Restoring From File in C++

本文关键字:文件 恢复 C++ 哈希表      更新时间:2023-10-16

我正在使用结构程序中的哈希表为学校做作业。任务的一部分是将一个由20个主存储桶和10个溢出存储桶组成的哈希表写入磁盘,每个存储桶有3个由密钥和数据字段组成的插槽,然后从中恢复

#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdio.h>
#include <string.h> // for strcpy()
using namespace std;
typedef char STR10[10+1];
typedef char STR20[20+1];
struct SLOT
{
STR10 key;
STR20 data;
};
struct BUCKET
{
SLOT entry[3];
int count;
BUCKET* overflow;
};
struct HASHTABLE
{
BUCKET pBkt[20];
BUCKET oBkt[10];
};
void WriteHTtoDisk (HASHTABLE ht, char *HashDisk);
void ReportHT (HASHTABLE ht, char * when);
int main()
{
int maxP = 20;
int maxO = 10;
int maxS = 3;
HASHTABLE ht;
STR10 mKey;
STR20 mData;
FILE * inFile;
inFile = fopen("DATAIN.dat","rb");
if (inFile == NULL)
{
cout << " DATAIN file access error ... n";
cout << " Terminating application ... n ";
cout << " Press any key ... n ";
return -100;
}
char crLF;
while (!feof(inFile))
{
fscanf(inFile,"%10c%20cn",mKey,mData);
mKey[10] = mData[20] = 0; // add string terminators
printf(" MyKey: %10sn MyData: %20sn",mKey,mData);
cin.ignore(80,'n'), cin.get();
//InsertIntoHT (ht, mKey, mData);
}
fclose(inFile);
WriteHTtoDisk(ht, "hashTable.dat");
ReportHT (ht,"BEFORE");
return 0;
}
void WriteHTtoDisk (HASHTABLE ht, char *HashDisk)
{
FILE * HASHDISK = fopen(HashDisk, "rb");
int maxBkt = 30;
int maxSlot = 3;
for (int i = 0; i < maxBkt; i++)
{
for (int j = 0; j < maxSlot; j++)
{
fwrite(ht.pBkt[i].entry[j].key,11,sizeof(maxSlot),HASHDISK);
fwrite(ht.pBkt[i].entry[j].data,21,sizeof(maxSlot),HASHDISK);
}
}
}
void ReportHT (HASHTABLE ht, char * when)
{
int maxB = 30;
int maxS = 3;
cout << "Hash Table n" << "Verification Report n" << when << " Restoration" << endl;
for (int b = 0; b < maxB; b++)
{
cout << "Bucket " << (b+1) << endl;
if (b < 20)
{
for (int i = 0; i < maxS; i++)
{
cout << setw(3) << "Slot " << (i+1) << ": " << ht.pBkt[b].entry[i].key << setw(3) << ht.pBkt[b].entry[i].data << endl;
}
}
else
{
for (int i = 0; i < maxS; i++)
{
cout << setw(3) << "Slot " << (i+1) << ": " << ht.oBkt[b].entry[i].key << setw(3) << ht.oBkt[b].entry[i].data << endl;
}
}
}
}

代码编译起来没有问题,但当我检查文件时,我发现它只是胡言乱语和奇怪的符号。我使用的数据以前是从另一个文件中提取的,我想将其保存为插入的格式。我确信问题出在fwrite的行上(我对C语法的经验不如C++(。

数据在DATAIN.dat文件中,如下所示:

大东公司KAMERMAN LCIRRUS BEAVERTON,或哥伦比亚方AST researchalton AV IRVINE CA

我希望新文件看起来像这样:

大同公司。EL PR.长滩CA

KAMERMAN L卷云

QUADRAM CO泥鳅AV NORCROSS GE

上次重新密封ALTON AV IRVINE CA

如有任何帮助,我们将不胜感激。非常感谢。

看起来您的代码没有初始化,甚至没有使用成员count。当散列桶为空时,count应该指示它。在C++中,它很容易实现:只需将= 0添加到它的定义中即可:

struct BUCKET
{
SLOT entry[3];
int count = 0;
BUCKET* overflow;
};

此外,在将bucket的数据写入文件时,请使用计数,不要假设bucket中的所有条目都已填充。

for (int j = 0; j < ht.pBkt[i].count; j++)
...

此外,只写入所需的字节数。fwrite接受两个参数:要写入的数据元素的大小及其数量。这里,大小是11或21,数字是1,因为每个fwrite调用只能向文件写入一个字符串。

fwrite(ht.pBkt[i].entry[j].key,11,1,HASHDISK);
fwrite(ht.pBkt[i].entry[j].data,21,1,HASHDISK);

顺便说一句,由于您有一个STR10类型,您可以避免幻数,并写sizeof(STR10)而不是11。这样,当您更改字符串的长度时,您的代码仍然可以工作。