У меня есть файлы Record.h и Record.cpp. Когда я просто включаю файл Record.h, я получаю несколько неопределенных ошибок ссылок на функции, определенные в этих файлах. Когда я также включаю Record.cpp, ошибки исчезают. Это почему? Record.h имеет предварительные объявления для функций, которые, по его словам, являются неопределенной ссылкой.
Record.h
#ifndef RECORD_
#define RECORD_
#include <string>
#include <limits>
using namespace std;
#define PKEYSIZE 10
#define STREETNUMSIZE 8
#define STREETNAMESIZE 24
#define RNAMESIZE 30
#define ASTYLESIZE 20
#define YEARSIZE 12
#define MAXBUCKETSIZE 4
#define MAXDIRECTORYSIZE 100
typedef struct
{
char streetNum[STREETNUMSIZE];
char streetName[STREETNAMESIZE];
char rName[RNAMESIZE];
char aStyle[ASTYLESIZE];
char year[YEARSIZE];
char pkey[PKEYSIZE];
} RECORD;
typedef struct
{
int size;
int depth;
RECORD record[MAXBUCKETSIZE];
} BUCKET;
#define HEADERSIZE 2L
#define NODESIZE sizeof(BUCKET)
void addKey(RECORD *rec_ptr, string key);
void addStreetNum(RECORD *rec_ptr, string s);
void addStreetName(RECORD *rec_ptr, string s);
void addRName(RECORD *rec_ptr, string s);
void addAStyle(RECORD *rec_ptr, string s);
void addYear(RECORD *rec_ptr, string s);
void printRecord(RECORD *rec_ptr);
ostream & operator<<(ostream & out, RECORD *r);
string cvt_binary(unsigned int input);
void addRecord(RECORD *r);
void showbucket(int n);
#endif
Record.cpp
int dirDepth = 0;
int numberOfBuckets = 0;
int directory[MAXDIRECTORYSIZE];
BUCKET bucket[MAXDIRECTORYSIZE/MAXBUCKETSIZE];
void addKey(RECORD *rec_ptr, string key)
{
strncpy(rec_ptr->pkey, key.c_str(), PKEYSIZE);
}
void addStreetNum(RECORD *rec_ptr, string s)
{
strncpy(rec_ptr->streetNum, s.c_str(), STREETNUMSIZE);
}
void addStreetName(RECORD *rec_ptr, string s)
{
strncpy(rec_ptr->streetName, s.c_str(), STREETNAMESIZE);
}
void addRName(RECORD *rec_ptr, string s)
{
strncpy(rec_ptr->rName, s.c_str(), RNAMESIZE);
}
void addAStyle(RECORD *rec_ptr, string s)
{
strncpy(rec_ptr->aStyle, s.c_str(), ASTYLESIZE);
}
void addYear(RECORD *rec_ptr, string s)
{
strncpy(rec_ptr->year, s.c_str(), YEARSIZE);
}
void printRecord(RECORD *rec_ptr)
{
cout<< "|"
<< rec_ptr->pkey << "|"
<< rec_ptr->streetNum << "|"
<< rec_ptr->streetName << "|"
<< rec_ptr->rName << "|"
<< rec_ptr->aStyle << "|"
<< rec_ptr->year << endl;
}
ostream & operator<<(ostream & out, RECORD *r)
{
out << r->pkey << r->streetNum << r->streetName << r->rName
<< r->aStyle << r->year << endl;
return out;
}
int bucketread(short rrn, BUCKET *page_ptr)
{
// long lseek(), addr;
long addr;
addr = (long)rrn * (long)NODESIZE + HEADERSIZE;
lseek(btfd, addr, 0);
return ( read(btfd, page_ptr, NODESIZE) );
}
int bucketwrite(short rrn, BUCKET *page_ptr)
{
// long lseek(), addr;
long addr;
addr = (long) rrn * (long) NODESIZE + HEADERSIZE;
lseek(btfd, addr, 0);
return (write(btfd, page_ptr, NODESIZE));
}
void showbucket(int n)
{
cout << "loading bucket " << n << endl;
BUCKET b;
bucketread(n, &b);
cout << "there are " << b.size << " records in the bucket" << endl;
}
string cvt_binary(unsigned int input) {
if(input == 0) return "0"; // trivial case
string result;
for(int i = numeric_limits<unsigned int>::digits - 1; i >= 0; --i) {
if(input & (1 << i))
{
result += "1";
}
else
{
if(!result.empty()) result += "0";
}
}
return result;
}
string hash (char* key)
{
int sum = 0;
int len = strlen(key);
if (len % 2 == 1) len++; // make len even
//for an odd length string, use the trailing 0 as part of key
for (int j = 0; j < len; j +=2)
sum = (sum + 100 * key[j] + key[j+1]) % 19937;
return cvt_binary(sum);
}
void copyrecord(RECORD *dest, RECORD *src)
{
cout << "copying record" << endl;
addKey(dest, src->pkey);
addStreetNum(dest, src->streetNum);
addStreetName(dest, src->streetName);
addRName(dest, src->rName);
addAStyle(dest, src->aStyle);
addYear(dest, src->year);
}
void addToBucket(int n, RECORD *r)
{
cout << "Adding record " << r->pkey << " to bucket " << n << endl;
if (bucket[n].size == MAXBUCKETSIZE)
{
cout << "Bucket " << n << " is full." << endl;
// examine bucket depth and directory depth to determine next action
cout << "Bucket depth: " << bucket[n].depth << endl;
cout << "Directory depth: " << directory[0] << endl;
}
else
{
copyrecord(&bucket[n].record[bucket[n].size],r);
bucket[n].size++;
bucketwrite(1,&bucket[1]);
}
}
string getreverse(string key, int num)
{
if(num==0)
return "";
string newstring;
newstring = key.at(key.length());
newstring+= getreverse(key.substr(0,key.length()-1),num-1);
return newstring;
}
void addRecord(RECORD *r)
{
cout << r->pkey << endl;
string hashvalue = hash(r->pkey);
cout << "hash value is " << hashvalue << endl;
int directoryDepth = directory[0];
if(directoryDepth == 0)
{
directory[1] = 1;
addToBucket(1, r);
}
else
{
// use hashing to figure out which bucket to add to
cout << "The relevant string is" << getreverse(hashvalue, directoryDepth) << endl;
}
}