-2

そこで、単純なHashクラスを作成しました。ビジュアルスタジオ環境を使用すると、デバッグアサーションエラー「式:文字列の添え字が範囲外です」が表示されます。ただし、コマンドプロンプトでc ++リンカーを使用してプログラムをコンパイルし、実行すると、正常に実行されます。エラーはh.add( "a"、 "la");で発生します。

これがコードです

#include <iostream>
#include <string>
using namespace std;
bool die(const string &msg);

class Hash{
    public:
        Hash( unsigned tablesize, unsigned maxUsed );
        ~Hash();
        bool in( const string & code ) const;
        bool getDescription( string & description, const string & code ) const;
        void add( const string & code, const string & description );
        void changeDescription( const string & code, const string & newDescription );
        void showone(const string &code) const;
        void show() const;
    private:
        struct Data{
            string code;
            string descrip;
        };
        unsigned hash(unsigned val) const;
        unsigned rehash(unsigned val) const;
        static unsigned Hash::partialHash( const string & code );
        static bool prime( unsigned n );
        unsigned findindex(const string &code) const;
        Data *ptr;
        unsigned maxUsed;
        unsigned elements;
        unsigned tablesize;
        unsigned p;
        unsigned p2;
};

Hash::Hash(unsigned size, unsigned maxused){
    if(UINT_MAX-3<size || size<=4 || size<=maxused )
        die("Invalid Constructor");
    for(tablesize=size; !prime(tablesize); tablesize++){}
    ptr=new Data[tablesize];
    elements=0;
    maxUsed=maxused;
    for(p=tablesize; !prime(--p);){}
    for(p2=p; !prime(--p2);){}
    for(unsigned i=0; i<tablesize; i++){
        ptr[i].code="\0";
        ptr[i].descrip="\0";
    }
}

Hash::~Hash(){
    delete[] ptr;
}

bool Hash::in(const string &code)const{
    if(code==ptr[findindex(code)].code)
        return true;
    return false;
}

void Hash::showone(const string &code) const{
 unsigned i=findindex(code);
 cout<<'['<<i<<"]: "<<ptr[i].code<<' '<<ptr[i].descrip<<'\n';
}
void Hash::show() const{
 for(unsigned i=0; i<tablesize; i++)
  cout<<'['<<i<<"]: "<<ptr[i].code<<' '<<ptr[i].descrip<<'\n';
}

bool Hash::getDescription( string & description, const string & code ) const{
    if(in(code)){
        description=ptr[findindex(code)].descrip;
        return true;
    }
    return false;
}

void Hash::changeDescription(const string & code, const string & newdescription ){
    if(in(code)){
        ptr[findindex(code)].descrip=newdescription;
    }else{
        die("code not in table");
    }
}

unsigned Hash::hash(unsigned partialHashValue)const{
    return partialHashValue%p;
}

unsigned Hash::rehash(unsigned partialHashValue)const{
    return partialHashValue%p2+1;
}

unsigned Hash::partialHash( const string & code ){
    return (code[0]*26+code[1])*26+code[2];
}

void Hash::add( const string & code, const string & description ){
    if(in(code)) die("can't add");
    if(elements==maxUsed) die("Overflow");
    unsigned i=findindex(code);
    ptr[i].code=code;
    ptr[i].descrip=description;
    elements++;
}

bool Hash::prime( unsigned n ){
        if( n < 4 )  return n > 1;
        if( n%2 == 0 || n%3 == 0 )  return false;
        for(  unsigned fac = 5, inc = 4;  ;  fac += inc = 6-inc  ){
            if( fac > n/fac )  return true;
            if( n%fac == 0 )  return false;
        }   
    }

unsigned Hash::findindex( const string &code) const{
    unsigned partial=partialHash(code);
    unsigned hashnum = hash(partial);
    if(ptr[hashnum].code=="\0" || ptr[hashnum].code == code) return hashnum;
    unsigned rehashnum = rehash(partial);
    do{
        hashnum = (hashnum + rehashnum) % tablesize;
    }while(  ptr[hashnum].code != "\0" && ptr[hashnum].code != code );
    return hashnum;
}

int main(){
    Hash h(12, 8);
    h.add("LAX", "Space Shuttle Endeavour arrived here 9/21/2012");
    h.add("DEN", "jajaja");
    h.add("gold", "lalalala");
    h.add("Pp", "la");
    h.add("a", "la");
    h.add("b", "la");
    h.add("c", "la");
    h.add("d", "la");
    cout<<"p\n";
    h.showone("LAX");
    cout<<"\n\n";
    h.show();
}

bool die(string const &msg){
 cerr<<"fatal error: "<<msg;
 exit(EXIT_FAILURE);
}

これが出力です

[0]: gold lalalala
[1]: DEN jajaja
[2]: LAX Space Shuttle Endeavour arrived here 9/21/2012
[3]:
[4]:
[5]: a la
[6]: b la
[7]: Pp la
[8]:
[9]: d la
[10]: c la
[11]:
[12]:
4

1 に答える 1

1

部分ハッシュ関数では、コードに「a」のみが含まれている場合、code[2]は境界外アクセスです。

unsigned Hash::partialHash( const string & code ){
    return (code[0]*26+code[1])*26+code[2];
}

at()関数を使用して、スローされた例外をキャッチできます

   unsigned Hash::partialHash( const string & code )
    {
        try {
          return (code.at(0)*26+code.at(1))*26+code.at(2);
        } 
        catch(std::exception& e){
          std::cout << e.what() << std::endl;
        }
        return 0;
    }
于 2012-12-10T00:08:40.747 に答える