Calling a Hash Class Function [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am trying to create my own hash class. However after countless tries I cannot get my program to work correctly. I believe that there is an error in me calling the function, however I am not quite sure. Can anyone help me figure out what I am doing wrong and possibly show me how to fix it?
hash.h
#include <iostream>
class MyHash {
public:
MyHash();
int hashCode(char, char);
};
hash.cpp
#include <iostream>
#include "Hash.h"
MyHash::MyHash() {}
int MyHash::hashCode(char first_letter, char last_letter) {
int hash = 0;
int ascii = 1;
hash = ((ascii * first_letter) + (ascii * last_letter)) % 23;
return (hash);
}
driver.cpp
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include "Hash.h"
using namespace std;
int main() {
vector<string> words;
int first_letter;
int last_letter;
string word;
int n = 0;
int hash = 0;
for (int i = 0; i < 5; i++) {
cout << " Please enter a word: ";
cin >> word;
words.push_back(word);
}
vector<string>::iterator itr = words.begin();
for (; itr != words.end(); itr++) {
first_letter = *itr[n].begin();
last_letter = *itr[n].rbegin();
cout << endl << " " << first_letter << " " << last_letter << endl;
hash = hashCode(first_letter, last_letter) cout << hash << endl;
}
return 0;
}

Why are you wrapping your function inside a class? It's completely arbitrary to define a class, place no data whatsoever inside of it then try to call the function from it without declaring any objects.
int hashCode(char first_letter, char last_letter) {
int hash = 0;
int ascii = 1;
hash = ((ascii * first_letter) + (ascii * last_letter)) % 23;
return (hash);
}
If you wanted to use a class, you need to have a structure along the lines of:
class myHash{
public:
myHash();
insert();
remove();
private:
std::vector<std::string> words;
hash();
rehash();
};

So to get over the compilation problem and not change the overall structure of the program you'll need to change your call to hashDode(...) to be MyHash::hashCode(...) and also change your declaration of int hashCode(char, char); to be static int hashCode(char, char);.
Youcan't just call a function defined in some scope and expect the compiler to figure it out, you need to give some indication as to where the function is. Since it's a class method you need to specify a class object or the class itself.
The static keyword will allow you to call the function without an object, which is OK in this case since you don't have any data in your object.

Related

Having a set of regex and a set of functions, how to link each regex to a specific function and then call that function once you have a match? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 months ago.
Improve this question
// vector of pairs
vector<pair<regex, void (*)(string)>> patterns;
// store a regex pattern
patterns[0].first = pattern;
// store a function name
patterns[0].second = func1;
patterns[1].first = pattern2;
patterns[1].second = func2;
// take user's input
string input;
cin >> input;
for (int i = 0; i < patterns.size(); i++)
{
if (regex_match(input, patterns[i].first)) // if the input matches one of the patterns, call the function associated with that pattern
{
patterns[i].second(input);
}
}
The problem is that I'm getting an error message for patterns[i].second(input); saying that: the expression preceding parentheses of apparent call must have (pointer-to-) function type
Let us first look at your code: I will show you the problems and how to fix it. And then I will show, how it could be optimized further.
I will put comments in your code to show the problems:
// vector of pairs
// *** Here we have the base for a later problem
// *** After this line, you will have an empty vector, that has no elements.
vector<pair<regex, void (*)(string)>> patterns;
// *** The vector is empty.
// *** And if you try to access patterns[0] or patterns[1]
// *** then you try to acess elements that don't exist.
// *** This will cause UB (Undefined Behaviour)
// store a regex pattern patterns
patterns[0].first = pattern;
// store a function name
patterns[0].second = func1;
patterns[1].first = pattern2;
patterns[1].second = func2;
// *** all UB (Undefined Behaviour) from here on.
// take user's input
//*** Please use getline to read a complete line
string input;
cin >> input;
for (int i = 0; i < patterns.size(); i++)
{
if (regex_match(input, patterns[i].first)) // if the input matches one of the patterns, call the function associated with that pattern
{
patterns[i].second(input);
}
}
So, obviously, you want to have a std::vector with 2 elements, so that you can use the index operator to fill it.
With that the easiest way will be to use std::vectors constructor no. 4 to set aninitial size. This could be done like this:
std::vector <std::pair <std::regex, void (*)(std::string&)>> patterns(2);
Then your could use the index operator [] to assign values.
But most likely, you would use either the std::vectors push_back - function, or an initializer list.
So, an intermediate optimized solution could look like:
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <regex>
void function1(std::string& s) {
std::cout << "Function 1:\t " << s << '\n';
}
void function2(std::string& s) {
std::cout << "Function 2:\t " << s << '\n';
}
int main() {
// Pattern and related callback function
std::vector <std::pair <std::regex, void (*)(std::string&)>> patterns{};
// Initialize vector
patterns.push_back({ std::regex(".*abc.*"),function1 });
patterns.push_back({ std::regex(".*def.*"),function2 });
// Get input from user
std::string input{};
std::getline(std::cin, input);
// Find a pattern and call the corresponding function
for (size_t i{}; i < patterns.size(); ++i) {
if (std::regex_match(input, patterns[i].first))
patterns[i].second(input);
}
}
Modern C++ has more nice features, like structured bindings and range based for loops.
With that, the code can be made even more readable.
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <regex>
void function1(std::string& s) {
std::cout << "Function 1:\t " << s << '\n';
}
void function2(std::string& s) {
std::cout << "Function 2:\t " << s << '\n';
}
int main() {
// Pattern and related callback function
std::vector <std::pair <std::regex, void (*)(std::string&)>> patterns{
{ std::regex(".*abc.*"),function1 },
{ std::regex(".*def.*"),function2 }
};
// Get input from user
std::string input{};
std::getline(std::cin, input);
// Find a pattern and call the corresponding function
for (const auto& [regex, function] : patterns) {
if (std::regex_match(input, regex))
function(input);
}
}
I would do it this way, so that the code also becomes a bit more self explaining :
#include <iostream>
#include <vector>
#include <string>
#include <regex>
#include <functional>
// using namespace std; <== NO
using handler_function_t = std::function<void(const std::string&)>;
// do not use pair, so hard to reason back to WHAT you mean
// define a struct
struct pattern_handler_t
{
pattern_handler_t(std::string&& rx, handler_function_t&& fn) :
regular_expression{ rx },
call{ fn }
{
};
const std::regex regular_expression; // give clear readable names, so much better then 'first' of pair
const std::function<void(const std::string&)> call;
};
void callback1(const std::string& text)
{
std::cout << text << ", starts with an a\n";
}
void callback2(const std::string& text)
{
std::cout << text << ", starts with a b\n";
}
int main()
{
// you can use an initializer list.
std::vector<pattern_handler_t> pattern_handlers
{
{"a.*",callback1},
{"b.*",callback2}
};
std::string input{ "another example" };
//std::cin >> input;
// use range based for loop for vector
for (const auto& pattern_handler : pattern_handlers)
{
std::smatch match;
if (std::regex_match(input, match, pattern_handler.regular_expression))
{
pattern_handler.call(match[0]);
}
}
return 0;
}

issue in intialising character array from the structure through an array object [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
i am getting an issue while initialising the character array in the structure through the structure object
#include <iostream>
#include <string.h>
using namespace std;
struct emp
{
int age;
char name[10];
};
int main()
{
struct emp v[2];
List item
v[0].age = 9;
v[0].name[] = "name1"; <-this is where i am getting error
v[1].age = 10;
v[1].name[]= "name2"; <-this is where i am getting error
for (int i = 0; i < 2; i++)
{
cout << v[i].age << " " << v[i].name<<endl;
}
return 0;
}
For starters there is at least a typo
v[0].name[] = "name1"; <-this is where i am getting error
^^^^
v[1].name[]= "name2"; <-this is where i am getting error
^^^^
Arrays do not have the assignment operator. So these assignment statements
v[0].name[] = "name1";
v[1].name[]= "name2";
are incorrect syntactically and semantically.
You could initialize the elements of the array when it is declared.
For example
struct emp v[2] =
{
{ 9, "name1" },
{ 10, "name2" }
};
Otherwise you could use the standard string function strcpy. For example
#include <cstring>
//...
v[0].age = 9;
strcpy( v[0].name, "name1" );
v[1].age = 10;
strcpy( v[1].name, "name2" );
Another approach is to use class std::string instead of the character array. For example
#include <string>
// ...
struct emp
{
int age;
std::string name;
};
int main()
{
struct emp v[2];
v[0].age = 9;
v[0].name = "name1";
v[1].age = 10;
v[1].name= "name2";
for (int i = 0; i < 2; i++)
{
cout << v[i].age << " " << v[i].name<<endl;
}
return 0;
}
Pay attention to that instead of the ordinary for loop you could use the range-based for loop.
For example
for ( const auto &item : v )
{
cout << item.age << " " << item.name << endl;
}
In Modern C++:
#include <iostream>
#include <string>
#include <array>
struct emp {
int age;
std::string name;
};
int main() {
std::array<emp, 2> v{{{9, "name1"}, {10, "name2"}}};
for (const auto& item : v) {
std::cout << item.age << " " << item.name << std::endl;
}
return 0;
}

Reverse a string C++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm new to programming. I've learned how to reverse a string today. I've tried to use string instead of char but terminal gives an error.
string name = { "george" };
int nChar = sizeof(name) - 1;
string *pName = &name;
string *pNameLast = &name + nChar - 1;
while(pName < pNameLast) {
string save = *pName;
*pName = *pNameLast;
*pNameLast = save;
pName++;
pNameLast--;
}
cout << name << endl;
Here is an example of using std::reverse_interator. This is better a better way of doing it. Rather than doing it yourself.
#include <iostream>
#include <string>
#include <iterator>
int main()
{
std::string s = "George";
std::reverse_iterator<std::string::iterator> r = s.rbegin();
std::string rev(r, s.rend());
std::cout << rev << endl;
}
Problem:
When you attempt to do operations like string *pName = &name and
string *pNameLast = &name + nChar - 1;, you're treating std::string's as char*'s. You cannot do that and expect the code to work.
Solution:
Treat std::string's as std::string's. Instead of doing string *pName = &name declare pName as an int and use the operator [] of std::string to access to the values. Similarly with pNameLast. You also have to declare string save as a char or, as I prefer, use the std::swap function.
Additional info:
As far as I can see you're probably using using namespace std; as you're declaring std::string as string. If that is the case consider that using namespace std; is considered a bad practice (More info here).
Full code:
#include <iostream>
int main() {
std::string name = "george";
int length = name.size();
int pNameFirst = 0;
int pNameLast = length - 1;
while(pNameFirst < pNameLast)
{
std::swap(name[pNameFirst],name[pNameLast]);
pNameFirst++;
pNameLast--;
}
std::cout << name << std::endl;
}
If you want to reverse a string object, just do the following (note this is the one of many handmade ways:
#include <iostream>
#include <string>
int main() {
std::string my_string{"hello"};
// Similar to your way:
int index{static_cast<int>(my_string.length() - 1)};
for (; index >= 0; --index) {
std::cout << my_string.at(index) << std::endl;
}
}

How do I modify this loop to list numbers 100 to 1 [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
#include <iostream>
using namespace std;
int main()
{
// Local variable declaration:
int a = 10;
// while loop execution
while (a < 20)
{
cout << "value of a: " << a << endl;
a++;
}
return 0;
}
#include <iostream>
using namespace std;
int main()
{
// Local variable declaration:
int a = 100;
// while loop execution
while (a > 0)
{
cout << "value of a: " << a << endl;
a--;
}
return 0;
}
Strange indentation. (Now fixed)
But a while loop is based on a condition which means you should initialise the variable a to be 100.
After this use a loop to check while a is greater than 0. Then in the loops body you can output the variable a and decrement the number.
#include <iostream>
using namespace std;
int main()
{
int a = 100;
while (a > 0) {
cout << "value of a: " << a << endl;
a--; // Decrement A
}
}
Another method would be use a for loop
#include <iostream>
using namespace std;
int main()
{
for (int a = 100; a > 0; a--) {
cout << "value of a: " << a << endl;
}
}
These are very simple ways and I'd recommend looking into some books for beginners if you are new to C++ to understand the different syntax of loops.
You can modify your loop like this:
#include<iostream>
#include<ranges>
namespace sv = std::views;
int main()
{
for (int i : sv::iota(1, 101) | sv::reverse)
std::cout << i << "\n";
}
Here's a demo.
Note that this code is only valid from C++20.

c++ What's the output of this function? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
the output of this program should be this:
Can anybody explain why the output of this main is:
F1/2 F2/3 F5/4 F0/1 F0/1 F0/1 F0/1 F0/1
K0/1 K0/1
K?/? K2/3 K1/2
can you explain how we get the last 2 lines ?
thanks
the constructor is initialize like this in fraction.h
Fraction(int n=0, int d=1);
/* fraction.cpp */
#include "fraction.h"
#include <iostream>
using namespace std;
Fraction::Fraction(int n, int d)
: numerateur(n)
{
dedominateur = d;
cout << "F" << n << '/' << d << ' ';
simplifier();
}
Fraction::~Fraction(){
//cout<<"destructeur";
cout << "K"
<< numerateur << '/'
<< dedominateur << ' ';
numerateur = dedominateur = 0;
}
void Fraction::simplifier(){/*...*/}
/* prog1.cpp */
#include <iostream>
#include "fraction.h"
using namespace std;
void test(Fraction a, Fraction& b){
Fraction* c = new Fraction(a);
a = b;
b = *c;
c = NULL;
cout<< "F";
return;
}
int main(){
Fraction f1(1,2), f2(2,3), f3(5,4);
Fraction* tab = new Fraction[5];
std::cout << std::endl;
test(f1, tab[2]);
test(tab[3], tab[4]);
f3 = tab[5];
std::cout << std::endl;
return 0;
}
The output with a K obviously comes from the destructor. Two of them would be from the parameter a which is passed by value (copy) to test. The other three are the ones on the first line of main.
The objects created by new are never delete'd, so they are never destructed.