I am trying to build a spell check validator using Hash Table. I have list of words in a text file. I want to imported them to program and entered them into Hash Table using seperate chaining. Now, I want to run the program and I have these two errors. Can anyone help me with this?
at line 30-- no matching function for call to
'std::__cxx11::basic_string::push_back(std::__cxx11::string&)'
at line 40-- no match for 'operator==' (operand types are
'__gnu_cxx::__alloc_traits, char>::value_type'
{aka 'char'} and 'std::__cxx11::string' {aka
'std::__cxx11::basic_string'})
I know it's simple mistake of converting str to char but I couldn't figure out how to do without changing the rest of the program.
I would like to have a simple solution which doesnot change the existing code.
If it is not possible please tell me how to proceed.
#include<iostream>
#include <string>
#include <cstring>
#include <fstream>
std::string hashTable[27];
int hashTableSize = 27;
#define MAX_LEN 27
using namespace std;
int hashFunc(std::string s)
{
// A simple hashing, no collision handled
int sum=0,index=0;
for(std::string::size_type i=0; i < s.length(); i++)
{
sum += s[i];
}
index = sum % MAX_LEN;
return index;
}
void insert(std::string s)
{
// Compute the index using Hash Function
int index = hashFunc(s);
// Insert the element in the linked list at the particular index
hashTable[index].push_back(s);
}
void search(string s)
{
//Compute the index by using the hash function
int index = hashFunc(s);
//Search the linked list at that specific index
for(int i = 0;i < hashTable[index].size();i++)
{
if(hashTable[index][i] == s)
{
cout << s << " is found!" << endl;
return;
}
}
cout << s << " is not found!" << endl;
}
int main(){
//opening text file
std::ifstream inFile;
inFile.open("un.txt");
// If text file doesnot exist or not included in root folder.
if(inFile.fail()) {
std::cerr << "Error opening file"<< std::endl ;
exit(1);
}
//if text file exists.
std::string wordsinfile;
std::string words[100];
int count=0,i=0;
std::string str;
// writing words from text file into Array.
while( !inFile.eof()) {
inFile >> wordsinfile;
words[i]=wordsinfile;
count++;
i++;
}
for (i=0;i<100;i++){
std::cout<< words[i]<<std::endl;
}
for(i=0;i<=23;i++) {
insert(words[i]);
}
int choice;
string z;
string y;
while(1) {
cout << "Enter choice. 1) Insert\n 2) Search\n 3) Exit\n";
cin >> choice;
switch (choice) {
case 1:
cin>>y;
insert(y);
break;
case 2:
cin>>z;
search(z);
break;
case 3:
exit(0);
}
}
return 0;
}
My txt file had 38 different words and size of hash table is 27
Here's the correct version of your program. Your hashtable is supposed to be a collection of strings and since you are using indexing in the search function, using an STL vector for hashtable should do the trick.
#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
#include <vector>
std::vector<std::string> hashTable[27];
int hashTableSize = 27;
#define MAX_LEN 27
using namespace std;
int hashFunc(std::string s)
{
// A simple hashing, no collision handled
int sum=0,index=0;
for(std::string::size_type i=0; i < s.length(); i++)
{
sum += s[i];
}
index = sum % MAX_LEN;
return index;
}
void insert(std::string s)
{
// Compute the index using Hash Function
int index = hashFunc(s);
// Insert the element in the linked list at the particular index
hashTable[index].push_back(s);
}
void search(string s)
{
//Compute the index by using the hash function
int index = hashFunc(s);
//Search the linked list at that specific index
for(int i = 0;i < hashTable[index].size();i++)
{
if(hashTable[index][i] == s)
{
cout << s << " is found!" << endl;
return;
}
}
cout << s << " is not found!" << endl;
}
int main(){
//opening text file
std::ifstream inFile;
inFile.open("un.txt");
// If text file doesnot exist or not included in root folder.
if(inFile.fail()) {
std::cerr << "Error opening file"<< std::endl ;
exit(1);
}
//if text file exists.
std::string wordsinfile;
std::vector<std::string> words;
std::string str;
// writing words from text file into Array.
while( inFile >> wordsinfile) {
words.push_back(std::move(wordsinfile));
}
std::cout << "Total words read: " << words.size() << std::endl;
for (int i = 0;i < words.size(); i++){
std::cout << words[i] << std::endl;
}
for(int i=0; i < words.size(); i++) {
insert(words[i]);
}
int choice;
string z;
string y;
while(1) {
cout << "Enter choice. 1) Insert\n 2) Search\n 3) Exit\n";
cin >> choice;
switch (choice) {
case 1:
cin>>y;
insert(y);
break;
case 2:
cin>>z;
search(z);
break;
case 3:
exit(0);
}
}
return 0;
}
Related
This is part of a homework assignment I recently finished. I am required to use an array of structs to store a library of books by title and author. The code is working and running perfectly fine when sorting and displaying author or title alphabetically according to user input.
The only issue I run into is when it shows all books sorted alphabetically. There are 14 books total in the text file used with the assignment, but only 13 books show up when the show all (S) option is entered.
An example of the error would be:
()
Audio for Games (Brandon)
Instead of:
Audio for Games (Brandon)
Beginning LINUX Programming (Stones and Matthew)
My Code:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
// structure
struct Book {
string title;
string author;
};
const int ARRAY_SIZE = 1000;
Book books[ARRAY_SIZE];
string pathName;
ifstream lib;
// global variables
int loadData();
void showAll(int count);
void sortByTitle(int count, string title);
int main()
{
// initialised variables
int count = 0;
char selector = 'q', yesNoAnswer = 'n';
string name;
string title;
// asks user for file pathname
cout << "Welcome to Tommy's Library Database." << endl;
cout << "Please enter the name of the file: ";
getline(cin, pathName);
loadData();
count = loadData();
cout << count << " Records loaded successfully." << endl;
// Switch case menu
do {
cout << endl << "Please enter a keyword that corresponds to the list of options: " << endl;
cout << " Search by: (A)uthor, (T)itle, (S)how All, (Q)uit Program: ";
cin >> selector;
selector = toupper(selector);
switch (selector)
{
case 'S':
sortByTitle(count, title);
if (count <= 0) {
cout << " No counts found! " << endl;
}
else {
showAll(count);
}
break;
}
}
while (selector != 'q' && selector != 'Q');
return 0;
}
int loadData()
{
int count = 0;
int i = 0;
lib.open(pathName);
ifstream lib(pathName);
if (!lib)
{
cout << " Unable to open file path! " << endl;
return -1;
}
while (!lib.eof())
{
getline(lib, books[count].title);
getline(lib, books[count].author);
count++;
}
return count;
}
// displays all book titles beside the author names
void showAll(int count)
{
for (int i = 0; i < count; i++)
{
cout << books[i].title << " " << "(" << books[i].author << ")" << endl;
}
}
// Sorts by book title.
void sortByTitle(int count, string title) {
Book temp;
for (int i = 0; i < count; i++) {
for (int j = 0; j < count - i; j++) {
if (books[j].title > books[j + 1].title) {
temp = books[j];
books[j] = books[j + 1];
books[j + 1] = temp;
}
}
}
}
The text file im using with the assignment (books.txt)
Objects First with Java
Barnes and Kolling
Game Development Essentials
Novak
The Game Maker's Apprentice
Overmars
C++ Programming: From Problem Analysis...
Malik
C++ Programming Lab Manual
Scholl
Beginning LINUX Programming
Stones and Matthew
C++ Programming: Program Design Including...
D. S. Malik
C++ How to Program
Deitel and Deitel
Programming and Problem Solving with C++
Dale, Weems, Headington
Game Character Development with Maya
Ward
Developing Games in Java
Brackeen
C# Programming
Harvey, Robinson, Templeman, Watson
Java Programming
Farrell
Audio for Games
Brandon
You were starting your loop from 0 inside your showAll() method when your books array starts from 1, just start the loop from 1 and go to count + 1
for (int i = 1; i < count + 1; i++)
Your sort function doesn't work correctly. It's off by one and moves an empty element to the first index. It would cause undefined behavior if your array were full. Your sort function sorts all elements from 0 to count but it should sort from 0 to count - 1. You should fix your sort function (std::sort usually is faster than bubble sort):
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
// structure
struct Book {
string title;
string author;
};
const int ARRAY_SIZE = 1000;
Book books[ARRAY_SIZE];
string pathName;
ifstream lib;
// global variables
int loadData();
void showAll(int count);
void sortByTitle(int count, string title);
int main()
{
// initialised variables
int count = 0;
char selector = 'q', yesNoAnswer = 'n';
string name;
string title;
// asks user for file pathname
cout << "Welcome to Tommy's Library Database." << endl;
cout << "Please enter the name of the file: ";
getline(cin, pathName);
loadData();
count = loadData();
cout << count << " Records loaded successfully." << endl;
// Switch case menu
do {
cout << endl << "Please enter a keyword that corresponds to the list of options: " << endl;
cout << " Search by: (A)uthor, (T)itle, (S)how All, (Q)uit Program: ";
cin >> selector;
selector = toupper(selector);
switch (selector)
{
case 'S':
sortByTitle(count, title);
if (count <= 0) {
cout << " No counts found! " << endl;
}
else {
showAll(count);
}
break;
}
}
while (selector != 'q' && selector != 'Q');
return 0;
}
int loadData()
{
int count = 0;
int i = 0;
lib.open(pathName);
ifstream lib(pathName);
if (!lib)
{
cout << " Unable to open file path! " << endl;
return -1;
}
while (!lib.eof())
{
getline(lib, books[count].title);
getline(lib, books[count].author);
count++;
}
return count;
}
// displays all book titles beside the author names
void showAll(int count)
{
for (int i = 0; i < count; i++)
{
cout << books[i].title << " " << "(" << books[i].author << ")" << endl;
}
}
// Sorts by book title.
void sortByTitle(int count, string title) {
std::sort(books, books + count, [](const auto &lhs, const auto &rhs) {
return lhs.title < rhs.title;
});
}
In addition:
You shouldn't read a stream with while (!lib.eof()): Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong?
You can remove the first loadData()
You can remove the second parameter of void sortByTitle(int count)
You are shadowing global variables with local variables, e.g. global ifstream lib and local ifstream lib in int loadData()
You can remove unused variables
You should remove using namespace std;: Why is “using namespace std;” considered bad practice?
You should avoid global variables
You should replace endl by '\n' if you don't need to flush in that moment. endl does more than a simple linebreak and usually it's not necessary.
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using std::cin;
using std::cout;
using std::ifstream;
using std::string;
// structure
struct Book {
string title;
string author;
};
const int ARRAY_SIZE = 1000;
// global variables
int loadData(string pathName, Book *books);
void showAll(Book *books, int count);
void sortByTitle(Book *books, int count);
int main()
{
// initialised variables
int count = 0;
char selector = 'q';
// asks user for file pathname
cout << "Welcome to Tommy's Library Database.\n";
cout << "Please enter the name of the file: ";
string pathName;
getline(cin, pathName);
Book books[ARRAY_SIZE];
count = loadData(pathName, books);
cout << count << " Records loaded successfully.\n";
// Switch case menu
do {
cout << "\nPlease enter a keyword that corresponds to the list of options: \n";
cout << " Search by: (A)uthor, (T)itle, (S)how All, (Q)uit Program: ";
cin >> selector;
selector = toupper(selector);
switch (selector)
{
case 'S':
sortByTitle(books, count);
if (count <= 0) {
cout << " No counts found! \n";
}
else {
showAll(books, count);
}
break;
}
}
while (selector != 'q' && selector != 'Q');
return 0;
}
int loadData(string pathName, Book *books)
{
int count = 0;
ifstream lib(pathName);
if (!lib)
{
cout << " Unable to open file path! \n";
return -1;
}
while (getline(lib, books[count].title))
{
getline(lib, books[count].author);
count++;
}
return count;
}
// displays all book titles beside the author names
void showAll(Book *books, int count)
{
for (int i = 0; i < count; i++)
{
cout << books[i].title << " " << "(" << books[i].author << ")\n";
}
}
// Sorts by book title.
void sortByTitle(Book *books, int count) {
std::sort(books, books + count, [](const auto &lhs, const auto &rhs) {
return lhs.title < rhs.title;
});
}
So I am doing a school project that requires me to execute my program with arguments and display the contents of a file based on a particular action.
This is done by simply requesting the action after the file name is specified.
It is:
./executable_name 'filename' 'action'
actions include list or find. List will list all the book contents of the specific file in that order and find will find a book by it's ISBN number specified.
Now my error lies with the find function, more specifically how i compare the Strings. I cannot compare the strings within the "find" function for the life of me. Ive tried "strcmp()" with the ".c_str()", I've tried "==", I've tried "string.copmare(string2)", and nothing. I have developed some interesting clues though.
If I try to print the string from my array of arguments concatenated with a few letters it properly does some expected printing, BUT if I perform the same action from the struct instance of any particular book array it seems to be overwritten like a return carriage type.
EX:
argv[4] = 0-201-60464-7 near here
books[0].isbn = near here-60464-7
Driver File
##include"book.h"
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
using namespace std;
int main(int argc, char** argv)
{
//The structure of the book will also incorporate an array to
//acommadate more books
Book books[35];
string filename = argv[1];
int filesRead = read (filename, books);
if(string(argv[2])== "list")
{
for(int index =0;index < filesRead; index++ )
{
cout << books[index].title << endl;
cout << books[index].authorCount<< endl;
for(int j =0; j < books[index].authorCount; j++)
{
cout << books[index].authors[j] << endl;
}
cout << books[index].publisher <<endl;
cout << books[index].yearPublish <<endl;
cout << books[index].hardcover << endl;
cout << books[index].price << endl;
cout << books[index].isbn << endl;
cout << books[index].copies << endl;
}
}
if(argc > 3)
{
if(string(argv[2]) == "find")
{
int book_index = find(argv[3], books, filesRead);
if(book_index < 0)
{
cout << "Not found" << endl;
}
cout << books[book_index].title << endl;
cout << books[book_index].authorCount<< endl;
for(int j =0; j < books[book_index].authorCount; j++)
{
cout << books[book_index].authors[j];
}
cout << books[book_index].publisher <<endl;
cout << books[book_index].yearPublish <<endl;
cout << books[book_index].hardcover << endl;
cout << books[book_index].price << endl;
cout << books[book_index].isbn << endl;
cout << books[book_index].copies << endl;
}
}
}
Function file
#include"book.h"
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
using namespace std;
int read (string filename, Book books[])
{
ifstream inputFile(filename);
//validation for the file itself
if(!inputFile)
{
cout << "File does not exist!" << endl;
}
//use a mix of get line and ifstream
//created a temporary string to consume lines
//from primitive data types
int counter =0;
string consume_line;
while(counter < 35 && getline(inputFile, books[counter].title))
{
inputFile >> books[counter].authorCount;
getline(inputFile, consume_line);
for(int j =0; j < books[counter].authorCount; j++)
{
getline(inputFile, books[counter].authors[j]);
}
getline(inputFile, books[counter].publisher);
inputFile >> books[counter].yearPublish;
inputFile >> books[counter].hardcover;
inputFile >> books[counter].price;
getline(inputFile, consume_line);
getline(inputFile, books[counter].isbn);
inputFile >> books[counter].copies;
getline(inputFile, consume_line);
if(inputFile.eof())
{
break;
}
counter++;
}
return counter;
}
int find(string id, Book books[], int length)
{
int found=0;
for(int index = 0; index < length; index++)
{
string test =books[index].isbn;
if(id.compare(test)==0)
{
found = index;
break;
}
if(id > test)
{
cout << "greater than" << endl;
found = -1;
break;
}
if(id < test)
{
cout << "less than" << endl;
found =-1;
break;
}
}
return found;
}
Header File
// #file book.h
#ifndef BOOK_H
#define BOOK_H
#include <string>
using namespace std;
const int MAX_AUTHORS = 20;
struct Book {
string title;
string authors[MAX_AUTHORS];
short authorCount;
string publisher;
short yearPublish;
bool hardcover;
float price;
string isbn;
long copies;
};
/**
* #param filename name of the input data file
* #param books[] an array of textbook records read from the file
*
* #return the number of textbook records read
*/
int read (string filename, Book books[]);
/**
* #param id the ISBN number to search for
* #param books[] the list of textbook records
* #param length the number of textbook records in the array
*
* #return the array index of the matching record, otherwise it returns -1
*/
int find (string id, Book books[], int length);
#endif /* BOOK_H */
condensed Code
e
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
using namespace std;
const int MAX_AUTHORS = 20;
struct Book {
string title;
string authors[MAX_AUTHORS];
short authorCount;
string publisher;
short yearPublish;
bool hardcover;
float price;
string isbn;
long copies;
};
int read (string filename, Book books[])
{
ifstream inputFile(filename);
//validation for the file itself
if(!inputFile)
{
cout << "File does not exist!" << endl;
}
//use a mix of get line and ifstream
//created a temporary string to consume lines
//from primitive data types
int counter =0;
string consume_line;
while(counter < 35 && getline(inputFile, books[counter].title))
{
inputFile >> books[counter].authorCount;
getline(inputFile, consume_line);
for(int j =0; j < books[counter].authorCount; j++)
{
getline(inputFile, books[counter].authors[j]);
}
getline(inputFile, books[counter].publisher);
inputFile >> books[counter].yearPublish;
inputFile >> books[counter].hardcover;
inputFile >> books[counter].price;
getline(inputFile, consume_line);
getline(inputFile, books[counter].isbn);
inputFile >> books[counter].copies;
getline(inputFile, consume_line);
if(inputFile.eof())
{
break;
}
counter++;
}
return counter;
}
int find(string id, Book books[], int length)
{
int found=0;
for(int index = 0; index < length; index++)
{
string test =books[index].isbn;
if(id.compare(test)==0)
{
found = index;
break;
}
if(id > test)
{
cout << "greater than" << endl;
found = -1;
break;
}
if(id < test)
{
cout << "less than" << endl;
found =-1;
break;
}
}
return found;
}
int main(int argc, char** argv)
{
//The structure of the book will also incorporate an array to
//acommadate more books
Book books[35];
string filename = "test3.txt";
string isbn = "0-201-60464-7";
int filesRead = read (filename, books);
int book_index = find(isbn, books, filesRead);
if(book_index < 0)
{
cout << "Not found" << endl;
}
cout << books[book_index].title << endl;
cout << books[book_index].authorCount<< endl;
for(int j =0; j < books[book_index].authorCount; j++)
{
cout << books[book_index].authors[j];
}
cout << books[book_index].publisher <<endl;
cout << books[book_index].yearPublish <<endl;
cout << books[book_index].hardcover << endl;
cout << books[book_index].price << endl;
cout << books[book_index].isbn << endl;
cout << books[book_index].copies << endl;
}
test file in txt or dat whichever extension preferred
#file.txt
C++ Network Programming – Volume 1
2
Douglas C. Schmidt
Stephen D. Huston
Addison-Wesley
2002
0
35.99
0-201-60464-7
236
refactored to one compilation unit and zero test files.
Fixed logic errors
added some (hopefully explanatory) comments
added handling of windows-style line endings for increased portability
Note: Avoid the use of using namespace at global scope. A reasonable exception to this rule is using namespace std::literals;
#include<iostream>
#include<string>
#include<fstream>
#include<cstring>
#include <sstream>
using namespace std;
const int MAX_AUTHORS = 20;
struct Book {
string title;
string authors[MAX_AUTHORS];
short authorCount;
string publisher;
short yearPublish;
bool hardcover;
float price;
string isbn;
long copies;
};
void strip(std::string& str)
{
if (str.size() && str.back() == '\r')
{
str.pop_back();
}
}
std::istream& get_line_and_strip(std::istream& is, std::string& result)
{
std::getline(is, result);
strip(result);
return is;
}
// be specific about the bounds of the output variable.
int read (std::istream& inputFile, Book books[35])
{
//validation for the file itself
if(!inputFile)
{
std::cout << "File does not exist!" << std::endl;
// avoid UB by returning a value as per the function signature
return 0;
}
//use a mix of get line and ifstream
//created a temporary string to consume lines
//from primitive data types
int counter =0;
std::string consume_line;
while(counter < 35)
{
get_line_and_strip(inputFile, books[counter].title);
inputFile >> books[counter].authorCount;
std::getline(inputFile, consume_line);
for(int j =0; j < books[counter].authorCount; j++)
{
get_line_and_strip(inputFile, books[counter].authors[j]);
}
get_line_and_strip(inputFile, books[counter].publisher);
inputFile >> books[counter].yearPublish;
std::getline(inputFile, consume_line);
inputFile >> books[counter].hardcover;
std::getline(inputFile, consume_line);
inputFile >> books[counter].price;
std::getline(inputFile, consume_line);
get_line_and_strip(inputFile, books[counter].isbn);
inputFile >> books[counter].copies;
std::getline(inputFile, consume_line);
if(!inputFile) // tests for EOF or error during input
{
break;
}
counter++;
}
return counter;
}
int find(string id, Book books[35], int length)
{
int found=0;
for(int index = 0; index < length; index++)
{
string test =books[index].isbn;
if(id.compare(test)==0)
{
found = index;
break;
}
if(id > test)
{
cout << "greater than" << endl;
found = -1;
break;
}
if(id < test)
{
cout << "less than" << endl;
found =-1;
break;
}
}
return found;
}
auto test_data = ""
"C++ Network Programming – Volume 1\r\n"
"2\r\n"
"Douglas C. Schmidt\r\n"
"Stephen D. Huston\r\n"
"Addison-Wesley\r\n"
"2002\r\n"
"0\r\n"
"35.99\r\n"
"0-201-60464-7\r\n"
"236\r\n"
""s;
int main(int argc, char** argv)
{
//The structure of the book will also incorporate an array to
//acommadate more books
Book books[35];
string filename = "test3.txt";
string isbn = "0-201-60464-7";
auto test_file = std::istringstream(test_data);
int filesRead = read (test_file, books);
int book_index = find(isbn, books, filesRead);
if(book_index < 0)
{
cout << "Not found" << endl;
// would be invalid to continue if book not found
return 0;
}
cout << books[book_index].title << endl;
cout << books[book_index].authorCount<< endl;
for(int j =0; j < books[book_index].authorCount; j++)
{
cout << books[book_index].authors[j] <<endl;
}
cout << books[book_index].publisher <<endl;
cout << books[book_index].yearPublish <<endl;
cout << books[book_index].hardcover << endl;
cout << books[book_index].price << endl;
cout << books[book_index].isbn << endl;
cout << books[book_index].copies << endl;
}
Expected output:
C++ Network Programming – Volume 1
2
Douglas C. Schmidt
Stephen D. Huston
Addison-Wesley
2002
0
35.99
0-201-60464-7
236
https://coliru.stacked-crooked.com/a/9b08598ffcd0edc2
I'm just a beginner for C++
I want to read the text file (maximum of 1024 words) into an array, and I need to ignore all single character words. Can you guys help me to discard words that are single characters to avoid symbols, special characters.
This is my code:
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
const int SIZE = 1024;
void showArray(string names[], int SIZE){
cout << "Unsorted words: " << endl;
for (int i = 0; i < SIZE; i++){
cout << names[i] << " ";
cout << endl;
}
cout << endl;
}
int main()
{
int count = 0;
string names[SIZE];
// Ask the user to input the file name
cout << "Please enter the file name: ";
string fileName;
getline(cin, fileName);
ifstream inputFile;
inputFile.open(fileName);
// If the file name cannot open
if (!inputFile){
cout << "ERROR opening file!" << endl;
exit(1);
}
// sort the text file into array
while (count < SIZE)
{
inputFile >> names[count];
if (names[count].length() == 1);
else
{
count++;
}
}
showArray(names, SIZE); // This function will show the array on screen
system("PAUSE");
return 0;
}
If you change names into a std::vector, then you can populate it using push_back. You could fill names like this.
for (count = 0; count < SIZE; count++)
{
std::string next;
inputFile >> next;
if (next.length() > 1);
{
names.push_back(next);
}
}
Alternatively you could fill all the words into names and then utilize the Erase–remove idiom.
std::copy(std::istream_iterator<std::string>(inputFile),
std::istream_iterator<std::string>(),
std::back_inserter<std::vector<std::string>>(names));
names.erase(std::remove(names.begin(), names.end(),
[](const std::string& x){return x.length() == 1;}), names.end());
Iam trying to create an open addressed hash table. The user has to be able to define the table's size. For my collision resolution I am using psuedo random probing -
http://algoviz.org/OpenDSA/Books/OpenDSA/html/HashCImproved.html#HashingPseudoRandomProbePRO
Anyway the hashing function(s) seem to work fine until I only have 1 more space to fill in the table. As soon as I input the final element of the table my program crashes and I get a segmentation fault. I've been pulling my hair out trying to find the problem for hours. Please help!
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
using namespace std;
class HashTable
{
string* hash;
bool* inTable;
vector<int> perm;
int table_size;
int permFunc(int, int);
void permutation();
int hashFunc(string);
public:
//constructor for a hashtable
HashTable(int);
//deconstructor for hashtable
~HashTable();
bool isFull();
//The prototype for the insert method
void insert(string);
//The prototype for the lookup method
bool lookup(string);
//The prototype for the remove method
void remove(string);
//The prototype for the size method
int size();
//The prototype for the print method
void print();
};
//constructor
HashTable::HashTable(int table_size)
{
this -> table_size = table_size;
hash = new string[table_size];
inTable = new bool[table_size];
for(int i=0; i<table_size; i++) perm.push_back(i);
permutation();
}
//deconstructor
HashTable::~HashTable()
{
delete [] hash;
delete [] inTable;
}
//creates a permutation of the perm vectors index elements
void HashTable::permutation()
{
random_shuffle ( perm.begin() + 1, perm.end() );
}
//Hash function method for strings
int HashTable::hashFunc(string str)
{
int key = 0;
for (int i=0; i < str.size(); i++)
{
key += static_cast<int>(str.at(i));
}
cout << "key is:" << key << endl;
return key%table_size;
}
int HashTable::permFunc(int index, int i)
{
int temp = index;
index += perm[i];
if(index > table_size){index = index - table_size;}
if(inTable[index] == false ){return index;}
index = temp;
i++;
permFunc(index, i);
}
bool HashTable::isFull()
{
int num=0;
for(int i=0;i<table_size; i++)
{
if(inTable[i] == true){num ++;}
if(num == table_size){
cout<<"FULL TABLE";
return true;}
}
return false;
}
//Method that inserts an integer into the hash table
void HashTable::insert(string str)
{
int i=1;
if(isFull()){return;}
int pos = hashFunc(str);
if(inTable[pos] == true)
{
int permPos = permFunc(pos, i);
hash[permPos] = str;
inTable[permPos] = true;
}
else
hash[pos] = str;
inTable[pos] = true;
}
//A function that prints out the menu
void menu()
{
cout << endl;
cout << "press i to insert an element into the hash table" << endl;
cout << "press d to inTableete an element from the hash table" << endl;
cout << "press l to look up an element" << endl;
cout << "press s to obtain the size of the table" << endl;
cout << "press p to print the current table" << endl;
return;
}
//The main method
//Implements all the input and output
int main(void)
{
int table_size;
cout << "Enter table size: ";
cin >> table_size;
HashTable h(table_size);
while(true)
{
char c;
string str;
menu();
getline(cin, str);
stringstream stream;
stream << str;
stream >> c;
switch(c)
{
case 'i':
getline(cin, str);
h.insert(str);
break;
case 'd':
getline(cin, str);
h.remove(str);
break;
case 'l':
getline(cin, str);
cout << h.lookup(str) << "\n";
break;
case 's':
cout << h.size() << "\n";
break;
case 'p':
h.print();
break;
default:
cout << "Don't understand '" << c << "'\n";
}
}
return 0;
}
I don't know if this is your problem but this line:
if(index > table_size){index = index - table_size;}
will leave index at table_size which is out of bounds for your array. Change the > to >=
If this isn't it, could you add an example crashing input to your post, for testing?
need to create a word matcher which counts how many times a specific word is mentioned in a text file. here is what i have done so far and am not sure what iv done wrong. 1 text file contains a long paragraph the other just contains a few words. I need to compare both text files e.g. the word "and" is in the short text file. need to compare this with the long paragraph and see how many time this words appears and then have a report at the end of the program which displays this.
E.g and - 6tmes, but - 0times, it - 23times.
^^ something like this. not sure how to start making this
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream infile("text1.txt");
if(!infile)
{
cout << "Error";
}
string words[250];
int counter = 0;
while (!infile.eof() )
{
infile >> words[counter];
counter++;
}
ifstream infile2("banned.txt");
if(!infile2)
{
cout << "Error";
}
string bannedwords[250];
counter = 0;
while (!infile2.eof() )
{
infile2 >> words[counter];
counter++;
}
int eatcount= 0;
int orcount = 0;
int hellocount = 0;
int number;
for(int i=0; i<200; i++)
{
for(int j = 0; j < 8; j++)
{
if ( words[i] == bannedwords[j])
{
cout << words[i] << " ";
if (words[i]=="eat")
{
eatcount++;
}
else if (words[i] == "or")
{
orcount++;
}
else if (words[i]== "hello")
{
hellocount++;
}
}
}
}
cout << endl;
cout<< "eat was found "<<eatcount<<" times";
cout << endl;
cout<< "or was found "<<orcount<<" times";
cout << endl;
cout<< "hello was found "<<hellocount<<" times";
system("pause");
}
Why not use a std::multiset?
ifstream infile("text1.txt");
if(!infile)
{
cout << "Error";
}
std::multiset<string> words;
string tmp;
while (!infile.eof() )
{
infile >> tmp;
words.insert(tmp);
}
Then also use a map for the banned words:
ifstream infile2("banned.txt");
if(!infile2)
{
cout << "Error";
}
std::map<string, int> banned;
string tmp;
while (!infile2.eof() )
{
infile2 >> tmp;
banned.insert(tmp);
}
Then you can use std::multiset::count(string) to find the words without all the extra looping. You would only need one loop to go through your banned words list. e.g:
std::map<string, int>::iterator bannedwordIter = bannedwords.begin();
for( ; bannedwordIter != bannedwords.end(); ++bannedwordIter )
{
bannedwordIter->second = words.count(bannedwordIter->first);
// you could print here as you process, or have another loop that prints it all after you finish
cout << bannedwordIter->first << " - " << bannedwordIter->second << " times." << endl;
}
A minimal way would be to use regular expressions, like so
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
using namespace std;
unsigned countMatches(std::istream &is, std::string const &word)
{
string text;
unsigned count(0);
std::regex const expression(word);
while (getline(is, text)) {
count += distance(sregex_iterator(
text.begin(), text.end(), expression), sregex_iterator());
}
return count;
}
so you just pass it the input stream (in your case an input file stream) and it counts the occurences of the word specified after creating a regular expression that matches that word
int main()
{
ifstream ifs;
ifs.open("example_text_file.txt");
cout << countMatches(ifs, "word_you_want_to_search_for") << endl;
return 0;
}