Converting String to int using stoi inside a function - c++

I've tried multiple methods to make the stoi (or other functions) work for my needs (converting a given string to an integer for the purpose of making a key for a hash table). Specifically, I would like to ask why stoi does not like this conversion. I get the error "std::invalid_argument at memory location 0x0034F41C." I have looked around and couldn't find what I am doing wrong.
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
enum EntryType { Legitimate, Empty, Deleted }; //creat new data type that holds node status
struct HashNode //create new struct with (hash node)
{
string element; // item inside node
enum EntryType info; //status
};
struct HashTable //Creates a new struct (hash table)
{
int size; //defines size of table
HashNode *table; //creates pointer to table
};
int HashFun1(std::string skey, int size) //first hash function
{
std::string key2 = skey;
int key = stoi(key2);
return key % size; // will return the inputed value
}
//int HashFunc2(string key, int size) //second hash function
//{
// return(key * size - 1) % size; //needs to convert between string and int
//}
int main()
{
cout<<HashFun1("t", 2);
}

Related

Expected type got Element c++

Im trying to make a object / type that consists of an element of the periodic table. But when i try to use a vector of that object as a parameter, i get this error message expected a type, got ‘Element’
here is my code so far:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
Element(int AtomicNumm, string Symboll, string Namee, double Weightt,
int Neutronss, int Protonss, string ElectronConfigg) {
string Name = Namee;
int AtomicNum = AtomicNumm;
string Symbol = Symboll;
double Weight = Weightt;
int Neutrons = Neutronss;
int Protons = Protonss;
string ElectronConfig = ElectronConfigg;
}
string returnElement(vector<Element> vec, string input) { // error here
if (input.size() == 2) {
for (int i = 0; i < vec.length(); i++) {
}
}
return "";
}
int main(int argc, char*argv[]) {
vector<Element> PT;
string userinput (argv[1]);
return -1;
}
Also, im new to c++. If objects work completely differently here please let me know. (Coming from java)
That's because you haven't declared 'Element' in your program. Syntactically, it is close to definition of a constructor.
To make your program work, i guess you can do following modification to existing element:
class Element {
// your definition of element Here:
// also include default constructor without any implementation
Element() {}
};

Creating a hashtable using vectors of vectors?

I'm currently trying to write a program that creates a hash table, using vectors of vectors for my collision resolution method.
The problem I am facing is that during runtime, a vector of vectors is created, but all of the Entry vectors inside remain of size 0. I know my put functions are faulty but I don't know where/why.
This is my first time creating a hash table and I'd appreciate any assistance in what the problem might be. My goal is to create a vector of Entry vectors, and each Entry has its associated key and value. After finding the hash value for a new Entry key, it should check the Entry vectors' key values to see if the key already exists. If it does, it updates that key's value.
This is a segment of table.cpp:
Table::Table(unsigned int maximumEntries) : maxEntries(100){
this->maxEntries = maximumEntries;
this->Tsize = 2*maxEntries;
}
Table::Table(unsigned int entries, std::istream& input){ //do not input more than the specified number of entries.
this->maxEntries = entries;
this->Tsize = 2*maxEntries;
std::string line = "";
int numEntries = 0;
getline(input, line);
while(numEntries<maxEntries || input.eof()){ // reads to entries or end of file
int key;
std::string strData = "";
convertToValues(key, strData, line);
put(key, strData); // adds each of the values to the tab;e
numEntries++;
getline(input,line);
}
}
void Table::put(unsigned int key, std::string data){
Entry newEntryObj(key,data); //create a new Entry obj
put(newEntryObj);
}
void Table::put(Entry e){ // creating the hash table
assert(currNumEntries < maxEntries);
int hash = (e.get_key() % Tsize);
Entry newEntry = Entry(e.get_key(), e.get_data());
for(int i = 0; i < hashtable[hash].size(); i++){
if (e.get_key() == hashtable[hash][i].get_key()){
hashtable[hash][i].set_data(e.get_data());
}
else{
hashtable[hash].push_back(newEntry); // IF KEY DOESNT EXIST, ADD TO THE VECTOR
}
}
}
This is Table.h
#ifndef table_h
#define table_h
#include "entry.h"
#include <string>
#include <istream>
#include <fstream>
#include <iostream>
#include <vector>
class Table{
public:
Table(unsigned int max_entries = 100); //Builds empty table with maxEntry value
Table(unsigned int entries, std::istream& input); //Builds table designed to hold number of entires
void put(unsigned int key, std::string data); //creates a new Entry to put in
void put(Entry e); //puts COPY of entry into the table
std::string get(unsigned int key) const; //returns string associated w/ param, "" if no entry exists
bool remove(unsigned int key); //removes Entry containing the given key
friend std::ostream& operator<< (std::ostream& out, const Table& t); //overloads << operator to PRINT the table.
int getSize();
std::vector<std::vector<Entry>> getHashtable();
private:
std::vector<std::vector<Entry>> hashtable; //vector of vectors
int Tsize; //size of table equal to twice the max number of entries
int maxEntries;
int currNumEntries;
#endif /* table_h */
};
and Entry.h:
#include <string>
#include <iosfwd>
class Entry {
public:
// constructor
Entry(unsigned int key = 0, std::string data = "");
// access and mutator functions
unsigned int get_key() const;
std::string get_data() const;
static unsigned int access_count();
void set_key(unsigned int k);
void set_data(std::string d);
// operator conversion function simplifies comparisons
operator unsigned int () const;
// input and output friends
friend std::istream& operator>>
(std::istream& inp, Entry &e);
friend std::ostream& operator<<
(std::ostream& out, Entry &e);
private:
unsigned int key;
std::string data;
static unsigned int accesses;
};
There are various problems with your code, but the answer for your question would be this:
In
void Table::put(Entry e){ // creating the hash table
Have a look at the loop.
for(int i = 0; i < hashtable[hash].size(); i++){
Now, hashtable[hash] is a vector. But initially it doesn't have any elements. So hashtable[hash].size() is 0. So you don't enter the loop.
On top of this, trying to access hashtable[hash] in the first place results in undefined behaviour due to hashtable not being properly resized to Tsize. Try this in your constructor(s):
this->maxEntries = maximumEntries;
this->Tsize = 2*maxEntries;
this->hashtable.resize(this->Tsize);
EDIT:
It would be easier for you to understand if you use std::vector::at function instead of std::vector::operator[]. For example:
void Table::put(Entry e){ // creating the hash table
assert(currNumEntries < maxEntries);
int hash = (e.get_key() % Tsize);
Entry newEntry = Entry(e.get_key(), e.get_data());
for(int i = 0; i < hashtabl.at(hash).size(); i++){
if (e.get_key() == hashtable.at(hash).at(i).get_key()){
hashtable.at(hash).at(i).set_data(e.get_data());
}
else{
hashtable.at(hash).push_back(newEntry); // IF KEY DOESNT EXIST, ADD TO THE VECTOR
}
}
}
Without resizing hashtable, this code would throw an out_of_range exception when you try to do hashtable.at(hash) the first time.
P.S. None of this is tested.

Solving leaky memory and syntax issues in a simple hash table

I'm implementing a basic hashtable. My logic for the table makes sense (at least to me), but I'm a bit rusty with my C++. My program returns a free memory error when I run it, but I can't seem to figure out where my problem is. I think is has to do with how I call the pointers in the various class functions.
#include <iostream>
#include <unordered_map>
#include <string>
#include <cmath>
#include <exception>
using namespace std;
int hashU(string in/*, int M*/){ //hThe hash function that utilizes a smal pseusorandom number
char *v = new char[in.size() + 1]; //generator to return an number between 0 and 50. (I arbitrarily chose 50 as the upper limit)
copy(in.begin(), in.end(), v); //First the input string is turned into a char* for use in the the function.
v[in.size()] = '\0';
int h, a = 31415, b = 27183;
for(h=0;*v!=0;v++,a=a*b%(49-1))
h = (a*h + *v)%50;
delete[] v; //Delete the char* to prevent leaky memory.
return (h<0) ? (h+50) : h; //Return number
}
struct hashNode{ //The node that will store the key and the values
string key;
float val;
struct hashNode *next;
};
struct hashLink{ //The linked list that will store additional keys and values should there be a collision.
public:
struct hashNode *start; //Start pointer
struct hashNode *tail; //Tail pointer
hashLink(){ //hashLink constructor
start=NULL;
tail=NULL;
}
void push(string key, float val); //Function to push values to stack. Used if there is a collision.
};
void hashLink::push(string key, float val){
struct hashNode *ptr;
ptr = new hashNode;
ptr->key = key;
ptr->val = val;
ptr->next = NULL;
if(start != NULL){
ptr->next = tail;
}
tail = ptr;
return;
}
struct hashTable{ //The "hash table." Creates an array of Linked Lists that are indexed by the values returned by the hash function.
public:
hashLink hash[50];
hashTable(){ //Constructor
}
void emplace(string in, float val); //Function to insert a new key and value into the table.
float fetch(string in); //Function to retrieve a stored key.
};
void hashTable::emplace(string in, float val){
int i = hashU(in); //Retrieve index of key from hash function.
hashNode *trav; //Create node traveler
trav = hash[i].start; //Set the traveler to the start of the desired linked list
while(trav!=hash[i].tail){ //Traverse the list searching to see if the input key already exists
if(trav->key.compare(in)==0){ //If the input key already exists, its associated value is updated, and the function returns.
trav->val = val;
return;
}
else //Travler moves to next node if the input key in not found.
trav = trav->next;
}
hash[i].push(in,val); //If the traveler does not see the input key, the request key must not exist and must be created by pushing the input key and associated value to the stack.
return;
}
float hashTable::fetch(string in){
int i = hashU(in); //Retrieve index of key
hashNode *trav; //Create node traveler and set it to the start of the appropriate list.
trav = hash[i].start;
while(trav!=hash[i].tail){ //Traverse the linked list searching for the requested key.
if(trav->key.compare(in)==0){ //If the the requested key is found, return the associated value.
return trav->val;
}
else
trav = trav->next; //If not found in the current node, move to the next.
}
return false; //If the requested key is not found, return false.
}
int main(){
hashTable vars; //initialize the hash table
float num = 5.23; //create test variable
vars.emplace("KILO",num);
cout<<vars.fetch("KILO")<<endl;
return 0;
}
The problem is that when you call delete[] v, you have advanced v such that it is pointing to the 0 at the end of the string, which is the wrong address to delete.
Also, you're wasting a lot of code unnecessarily copying the string out of where it is already available as a c-string.
unsigned int hashU(string in/*, int M*/) {
const char* v = in.c_str();
unsigned int h, a = 31415, b = 27183;
for(h=0;*v!=0;v++,a=a*b%(49-1))
h = (a*h + *v);
return h % 50;
}
for(h=0;*v!=0;v++,a=a*b%(49-1))
h = (a*h + *v)%50;
delete[] v; //Delete the char* to prevent leaky
You are incrementing v, then deleting an invalid memory location.

Seg fault at the specified line: Hash table insert/search functions

I am getting a EXC_BAD_ACCESS error. I'm trying to insert words into a hash table and am using separate chaining. Here is my class Hash.h that has, within it, class wordData to store the word and pageNumbers the word appears on:
class Hash
{
private:
class wordData
{
public:
string word;
vector < int >pageNum;
wordData *nextWord;
// Initializing the next pointer to null in the constructor
wordData()
{
nextWord = nullptr;
}
// Constructor that accepts a word and pointer to next word
wordData(string word, wordData * nextWord)
{
this->word = word;
this->nextWord = nextWord;
}
// Getting and setting the next linked word
wordData *getNext()
{
return nextWord; //-------------------> BAD_ACCESS ERROR
}
void setNext(wordData * newInfo)
{
nextWord = newInfo;
}
// Setting info for the word node.
void setInfo(string & w, int pNum)
{
this->word = w;
this->pageNum.push_back(pNum);
}
// ******************* Gives a thread-bad access error************************
string getWord()
{
return word;
}
void addPageNums(int x)
{
this->pageNum.push_back(x);
}
};
private:
// Head to point to the head node of the linked list for a particular word
wordData ** head;
int size;
int *bucketSize;
int totalElements;
public:
// Class hash function functions
Hash();
// Function to calculate bucket number based on string passed
int hashFunction(string key);
// search if word is present
bool Search(string);
// Insert word
void Insert(string, int);
int bucketNumberOfElements(int index);
};
#endif /* Hash_h */
After running the debugger I found the value of nextWord to be 0x00000000000 which I understand is not the same as nullptr but is due to a NULL assignment although I can't seem to figure out where and why. I haven't included the Hash.cpp file because I think there is an obvious pointer manipulation that I'm doing wrong in the .h file.
Any help will be appreciated. Thanks.

Hash table(linear probing)

I am making a hash table using linear probing and i have to resize the array when ever the load factor i.e (no. of elements entered in hashtable)/(size of hashtable), becomes greater than 0.5, i have to resize the array.I am doing the resizing by initializing a pointer in a class which contains functions related to hashtable.I am putting the pointer equal to an array of a struct (struct only contains a string) of size 100.every time load factor becomes greater than 0.5, i resize the array by making a new array of double the previous size and point the pointer to the new array.I also have an int which stores current size of array and which is updated with every instance in which resize function is used.The number of elements inserted are incremented with every call to insert function.Am I doing this correctly?Below is my code
#include <cstring>
#include <vector>
#include <math.h>
#include <iomanip>
using namespace std;
int power(int a,int b)
{
for (int i=0;i<b;i++)
{
a*=a;
}
return a;
};
struct Bucket
{
string word;
};
const int size=100;
class LProbing
{
private:
int a; //a constant which is used in hashing
int cursize; //current size of hash table
Bucket *Table; //pointer to array of struct
int loadfactor; //ratio of number of elements entered over size of hashtable
int n; //number of elements entered
Bucket table[size]; //array of structs
public:
LProbing(int A); //constant is decided by user
void resize();
void insert(string word);
void Lookup(string word);
};
LProbing::LProbing(int A)
{
cursize=size;
a=A;
Table=table;
loadfactor=0; //initially loadfactor is 0 as number of elements entered are 0
n=0;
}
void LProbing::resize()
{
cout<<"resize"<<endl;
loadfactor=n/cursize; //ensuring if resize needs to be done
if (loadfactor<=0.5)
{
return;
}
const int s=2*cursize;
Bucket PTable[s];
for (int i=0;i<cursize;i++)
{
if (Table[i].word.empty())
continue;
//rehashing the word onto the new array
string w=Table[i].word;
int key=0;
for (int j=0;j<w.size();j++)
{
unsigned char b=(unsigned char)w[j];
key+=(int)power(a,i)*b;
}
key=key%(2*cursize);
PTable[key].word=w; //entering the word in the new array
}
Table=PTable; //putting pointer equal to new array
cursize=2*cursize; //doubling the current size of array
}
void LProbing::insert(string word)
{
cout<<"1"<<endl;
n++; //incrementing the number of elements entered with every call to insert
//if loadfactor is greater than 0.5, resize array
loadfactor=n/cursize;
if (loadfactor>0.5)
{
resize();
}
//hashing the word
int k=0;
for (int i=0;i<word.size();i++)
{
unsigned char b=(unsigned char)word[i];
int c=(int)((power(a,i))*b);
k+=c;
cout<<c<<endl;
}
int key=0;
key=k%cursize;
cout<<key<<endl;
//if the respective key index is empty enter the word in that slot
if (Table[key].word.empty()==1)
{
cout<<"initial empty slot"<<endl;
Table[key].word=word;
}
else //otherwise enter in the next slot
{
//searching array for empty slot
while (Table[key].word.empty()==0)
{
k++;
key=k%cursize;
}
//when empty slot found,entering the word in that bucket
Table[key].word=word;
cout<<"word entered"<<endl;
}
}
#include "Linear Probing.cpp"
#include <fstream>
using namespace std;
int main()
{
LProbing H(35);
ifstream fin;
fin.open("dict.txt");
vector<string> D;
string d;
while (getline(fin,d))
{
if (!d.empty())
{
D.push_back(d);
}
}
fin.close();
for (int i=0;i<D.size();i++)
{
H.insert(D[i]);
}
system("PAUSE");
return 0;
}
You may find it helpful somewhere:
http://www.cs.rmit.edu.au/online/blackboard/chapter/05/documents/contribute/chapter/05/linear-probing.html
You are dealing with big numbers and variable "key" is overflowing in:
key += (int)power(a,i)*b
It looks like loadfactor is calculated as int/int so it will stay 0 until it reaches 1. Try casting the inputs to the division into floats.