Hello everyone, I'm writing a hashtable for an exercise.
I am nearly finished but unfortunately I get a exc_bad_access error.
Now I am stuck for more than two days and since I am not able to find/understand the problem I hope to get a little bit help from you guys.
The idea is to have a bucket array of the class linked list.
In this bucket array each list signifies a linked list that stores the elements: name and mass.
For me it seems that something is wrong with my bucket declaration.
Thank you for any advise.
//
// header.h
// ex3
//
// Created by Georg Pollak on 19.11.12.
// Copyright (c) 2012 Georg Pollak. All rights reserved.
//
#ifndef __ex3__header__
#define __ex3__header__
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
usingnamespace std;
class test{
int y;
};
// elements we want to store in the queue------------------------------
class element{
public:
int set_element(string name_n, float mass_n);
float get_mass();
string get_name();
private:
string name;
float mass;
};
// minimal linked list (queue)-----------------------------------------
class node{
public:
// constructor
node(); // constructors have the same name as the class
// and no return value.
// another constructor, with one argument
// (using function overloading, also works inside classes)
//zeiger auf sich selbst
node(node *n);
// destructor
~node(); // destructor: beginning with ~, no arguments (ever)
// member functions
element *get_item();
node *get_next();
node *return_next();
int set_item(element x);
int set_next(node *n);
private:
element *item;
node *next;
};
class linked_list{
public:
linked_list();
~linked_list();
int push(element x);
int pop();
int hash(string s);
int make_table(int arg_num, char *arg_var[]);
node *get_anchor();
private:
linked_list **bucket;
node *anchor;
};
#endif /* defined(__ex3__header__) */
//
// header.cpp
// ex3
//
// Created by Georg Pollak on 19.11.12.
// Copyright (c) 2012 Georg Pollak. All rights reserved.
//
#include "header.h"
usingnamespace std;
// member functions implementation element-----------------------------
int element::set_element(string name, float mass){
this->name = name;
this->mass = mass;
return 0;
}
float element::get_mass(){
returnthis->mass;
}
string element::get_name(){
returnthis->name;
}
// member functions implementation node--------------------------------
//constructor
node::node(){
item = NULL;
next = NULL;
}
//Construction of a new List node n
node::node(node *n){
item = NULL;
next = n;
}
// destructor
//Is called when the scope of the Object is lost
node::~node(){
}
//returns a pointer to the elment item of node n [e.g. node.get_item();] => acess of variable of element of node n
element *node::get_item(){
return item;
}
//returns a pointer to a node [e.g. node.get_next();]
node *node::get_next(){
return next;
}
node *node::return_next(){
return next;
}
int node::set_item(element x){
item = &x;
return 0;
}
//set a new node from current node (if it is the last) [e.g. lastnode.set_next(newnode);] => pointer of lastnode points to next node
int node::set_next(node *n){
if (next != NULL){
// we already have a next one, not at the end
// cannot add here
return 1;
}
next = n;
return 0;
}
// member functions implementation linked_list--------------------------
linked_list::linked_list(){
anchor = NULL;
bucket = new linked_list *[5]; // I AM NOT SURE IF THIS WORS AS I HOPE
for (int i=0; i<5; i++){
bucket[i] = NULL;
}
}
//HERE COMES THE PLACE WHERE THE DEBBUGER SHOWS ME THE ERROR OF THE NODE ANCHOR
//IF I CALL PUSH WITH THE BUCKET IN MAKE_TABLE
int linked_list::push(element x){
node *n = new node;
n->set_item(x);
n->set_next(anchor); // Thread 1:EXC_BAD_ACCESS(code=1, address=0x8) error!!?
anchor = n;
return 0;
}
//Simple Hashfunction(works!)
int linked_list::hash(string s){
intconst FACTOR = 101;
intconst MAX =5;
int sum = 0;
for(unsignedint i=0; i < s.length(); ++i){
sum += s[i] * FACTOR;
sum %= MAX;
}
return sum;
}
node *linked_list::get_anchor(){
returnthis->anchor;
}
int linked_list::make_table(int arg_num, char *arg_var[]){
if(arg_num != 2){
cout << "usage: " << arg_var[0] << " filename" << endl;
return 1;
}
// the data
int i = 0;
string name;
float mass;
{
//fin(arg_var[1]); = fin.open(argv[1], ios::in);
ifstream fin(arg_var[1]);
if (!fin.is_open()){
cout << "error opening file: " << arg_var[1] << endl;
return 1;
} //.is_open(): The function returns true if a previous call to open succeeded
stringstream inp; // create the stream for the data without the comments
string s; // and a buffer to read in
//stringstream provides an interface to manipulate strings
// read in the whole file
while(true){
getline(fin, s); //getline(): extracts characters from fin and stores them into s
//eof(): end of line
s = s.substr(0, s.find('#')); // get rid of everything right to the #
if (s!="") //stringstream << : Insert data with format (zwischenspeicher)
inp << s << endl;
if(fin.eof()) break; //substr(pos, npos): returns a string object with its contents initialized to a substring of the current object
} //pos: position of a character in the current string object to be used as starting character for the substring.
//n: length of the substring. / find(): searches for the content and returns position / if something left, add to the stream
fin.close();
// now read in as normal / stringstream >> x: Extract formatted data into x
/*if (!(inp >> d1[i] >> d2[i])){
cout << "error while reading in data" << endl;
return 1;
}*/
//make hash_table
//We have alread checked in the beginning that no empty list is submitted!
node test;
while(!inp.eof()){
//reads in strings & floats
inp >> name >> mass;
element x;
x.set_element(name, mass);
//make_table
//SHOULD MAKE A HASHTABLE OUT OF 5 LINKED LISTS AND STORES THE ELEMENTS X IN THE //CORRECT BUCKET. HERE IS THE PLACE WHERE BUCKET CALLS PUSH AND THAN I GET THE ERROR
bucket[hash(name)]->push(x);
i+=1;
}
}
return 0;
// do whatever you wanted to do with the data...
}
linked_list::~linked_list(){
}
int node::set_item(element x){
item = &x;
return 0;
}
x only exists for the scope of the function, therefore the value held by item is only valid for the scope of the function. Once the function returns item points to memory that no longer holds an element.
The typical implementation of a linked list stores a copy of the element inserted, not a pointer to it.
Ok thanks, that makes sense.
So I changed item to an normal element but I still get the EXC_BAD_ACCESS error.
I also tried to make name and mass public to fill it directly.
So the error seems to come from somewhere else:(
//SHOULD MAKE A HASHTABLE OUT OF 5 LINKED LISTS AND STORES THE ELEMENTS X IN THE //CORRECT BUCKET. HERE IS THE PLACE WHERE BUCKET CALLS PUSH AND THAN I GET THE ERROR
bucket[hash(name)]->push(x);
Fist, make_table has no business in your linked_list implementation.
Second, linked_list has no business having a member named bucket.
The only manipulation to bucket prior to this is to allocate space for 5 pointers and set them to NULL. Here, you dereference those NULL pointers.