Segmentation fault when reading into hash table

So I am to take this code for a hash table from a book and I am to read in the contents of a dictionary and store them in this hash table. I can't figure out how to read in all the words without getting a segmentation fault. Any ideas? Any guidance is much appreciated. Here is my code below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* Hash.cpp
 *
 *  Hash table implementation from:
 *  Kernighan & Ritchie, The C Programming Language,
 *     Second Edition, Prentice-Hall, 1988.
 */

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <fstream>

using namespace std;

#include "hash.h"

const int HASH_TABLE_SIZE = 101;
static NListPtr hashTable[HASH_TABLE_SIZE];

// int HASH_TABLE_SIZE = 101;
//NListPtr hashTable[HASH_TABLE_SIZE];

    //  Prototypes
// static char *Strdup( const char * );  //  in cstring, but...

static char *Strdup( const char * );  //  in cstring, but....


/*  Hash
 *  Generate hash value for string s
 */

unsigned Hash( char *s )
{
    unsigned hashVal;

    for( hashVal = 0 ; *s != '\0' ; s++ )
        hashVal = *s + 31 * hashVal;

    return  hashVal % HASH_TABLE_SIZE;
}
/*  Lookup
 *  Look for s in hashTable
 */

NListPtr Lookup( char *s )
{
    NListPtr np;

    for( np = hashTable[Hash(s)] ; np != NULL ; np = np->next )
    {
        if( strcmp(s, np->name) == 0 )
            return np;    //  found
    }

    return NULL;          //  not found
}

/*  Insert
 *  Put (name, defn) in hash table
*/

NListPtr Insert( char *name, char *defn )
{
    unsigned hashVal;
    NListPtr np;

    ifstream infile;

    if( (np = Lookup(name)) == NULL )  // not found
    {
        np = (NListPtr) malloc(sizeof(*np));
        if( np == NULL || (np->name = Strdup(name)) == NULL )
        return NULL;

        //////////////////////////

        infile.open("dict4.txt");
        while(!infile.eof())
        {
              infile >> name;
 }
        if(hashTable[hashVal] == NULL)
        {
         hashTable[hashVal] = np;
         np->next = NULL;
         }

        //////////////////////////

        hashVal = Hash(name);
        np->next = hashTable[hashVal];
        hashTable[hashVal] = np;

    }
    else
    {      //  remove previous definition
        free( (void *)np->defn );
    }

    if( (np->defn = Strdup(defn)) == NULL )
        return NULL;

    return np;
}


/*  PrintHashTable
 *  Print the hash table contents
 */

void PrintHashTable()
{
    NListPtr np;

    cout << "Hash table contents:" << endl;
    cout << "--------------------\n" << endl;

    for( int i = 0 ; i < HASH_TABLE_SIZE ; i++ )
    {
        np = hashTable[i];
        while( np != NULL )
        {
             cout << setw(3) << i << ":    ";
             cout << np->name << ", " << np->defn;
             cout << endl;
             np = np->next;
        }
    }
}


/*  Strdup
 *  Make a duplicate copy of s
 */

static char *Strdup( const char *s )
{
    char *p;

    p = (char *) malloc(strlen(s)+1);  /*  +1 for '\0'  */
    if( p != NULL )
        strcpy(p,s);

    return p;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

/*  hash.h
 */

#include<iostream>

using namespace std;
error: ‘hashTable’ was not declared in this scope
TestHash.cpp: I
#ifndef HASH_H
#define HASH_H

struct nList     /*  table entry:  */
{
   char *name;          /*  defined name         */
   char *defn;          /*  replacement text     */
   struct nList *next;  /*  next entry in chain  */
};

typedef struct nList *NListPtr;

unsigned Hash( char *s );
NListPtr Lookup( char *s );
NListPtr Insert( char *name, char *defn );

void PrintHashTable();

#endif  /*  HASH_H  */


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/* TestHash.cpp
 *   Test the Hash table code.
 */

#include <iostream>
#include <cstdlib>

using namespace std;

#include "hash.h"
#include "hash.cpp"

int main()
{
      //  Put a few values in the table...
   (void)Insert( "One",  "1" );
   (void)Insert( "One",  "11" );
   (void)Insert( "Two",  "2" );
   (void)Insert( "Four", "4" );
   (void)Insert( "Five", "5" );
   (void)Insert( "Six",  "6" );
   (void)Insert( "Nine", "9" );

   (void)Insert( "Yes", "1" );
   (void)Insert( "YES", "1" );
   (void)Insert( "No",  "0" );
   (void)Insert( "NO",  "0" );

   PrintHashTable();

   return EXIT_SUCCESS;
}
ISO C++ forbids converting a string constant to ‘char*’
(void)Insert( "One",  "1" );


Also, ¿what does your (void) casting do?
Could you explain a little bit more on that? I got it running without everything between lines 77-90 in the hash.cpp, it just doesn't quite do what I want it to.

And I believe the (void) casting just tells the function not to use the return value.
Last edited on
"This looks like a bunch of old-timey C code dressed up with C++ headers"
is what I was going to say, until I saw the comment at the top. Okay, I nust have reflexively blocked that out at the point of visual impact.

I imagine these are just copy-paste errors, but here goes:

static char *Strdup( const char * ); // in cstring, but.... no, it's not. C and C++ are case sensitive. Strdup is not the same as strdup.

1
2
3
4
while(!infile.eof())
        {
              infile >> name;
}
Do you really want just the last word in the file?

1
2
3
4
5
6
NListPtr Insert( char *name, char *defn )
...
(void)Insert( "One",  "1" );
// "One" and "1" are of type const char *
// Insert expects 2 arguments of type char *
// You cannot mix the 2 this way 


1
2
3
4
5
6
7
8
9
10
???
/*  hash.h
 */

#include<iostream>

using namespace std; //??? in a header
error: ‘hashTable’ was not declared in this scope
TestHash.cpp: I
#ifndef HASH_H 
I think this is definitely a copy and paste error

#include "hash.cpp" ?? don't defeat the point of separate compilation

hashVal is used uninitialised in Insert()

Could you post your newer, working code? Also do you really want to do this in C or in C++?
Last edited on
A string literal like "One" is a const char*
You are passing a const char* to a function that expects a char* (`Insert()')
There you just aimed the gun at your foot.

In that function you do infile >> name;
So you are trying to modify a string literal, a const char*
There you've pulled the trigger.
Topic archived. No new replies allowed.