I am writing a small "quiz program". It looks similar to this:
#include <cstdlib>
#include <iostream>
#include <time.h>
using namespace std;
using std::cout;
class cQuestion
{
private:
static short goodAnswers[20][2];
public:
static void checkAnswer(int questNumber)
{
/* checking input, checking if answer is bad or good */
/* putting the answer to cQuiz::answArr */
};
static void question1(void) { cout << "this is question 1"; };
static void question2(void) { cout << "this is question 2"; };
static void question3(void) { cout << "this is question 3"; };
static void question4(void) { cout << "this is question 4"; };
static void question5(void) { cout << "this is question 5"; };
/*and so on to question 20*/
};
short cQuestion::goodAnswers[20][2] = {0,0};
class cQuiz
{
private:
static short questArr[5];
static short answArr[5];
public:
void drawRandom(void)
{
srand ( time(NULL) );
for (int i = 0; i < 5; i++ )
questArr[i] = rand() % 20 + 1;
};
void askQuestions(void)
{
for (int i = 0; i < 5; i++ )
{
/* call questions by question number from questArr */
/* HOW SHOULD I CALL CERTAIN cQuestion CLASS MEMBER ?? */
cQuestion::checkAnswer(questArr[i]);
}
};
};
short cQuiz::questArr[5] = {0};
short cQuiz::answArr[5] = {0};
int main(int argc, char *argv[])
{
cQuiz quiz;
quiz.drawRandom();
quiz.askQuestions();
system("PAUSE");
return EXIT_SUCCESS;
}
I am wondering, how can (or should) I call class cQuestion member methods ? I was thinking about using an array of pointers to these members (cQuestion::question1, cQuestion::question2, and so on) or overloading subscript operator[].
I am not sure if either way is good or bad. Should i consider different solution or somehow use both together? Or am I completely missing the point?
This is not good design. Having to add a new method for each question means that you have to recompile each time you add aquestion to the quiz. And as you have found out, it is hard to call those functions randomly. A re-design is in order here.
Further to the OOP post above, how about:
class Question { // Make this a C++ interface
public:
Question(string q, string a)
: QuestionText(q), Answer(a)
{}
string QuestionText;
string Answer;
}
Then instantiate these using a factory or just in your initialisation function:
q1 = Question("What is the secret of life", "DNA");
q2 = Question("What is the answer to the great question", "42");
You should probably put these in a vector, rather than in local or global variables.
Apart from all the OOP dilemmas, maintain an array of function pointers to your member functions and randomly select one of them.
Why is each question in its own method? Why not make an array of strings to store the questions?
How about something like this?
string[] questions = {"Q1","Q2","Q3"};
void question(int i)
{
cout << questions[i];
}
Related
I'm attempting to do something like this.
class testClass {
public:
void testFunction(char charArray[])
{
char output[].append(charArray.at(1));
char output[].append(charArray.at(7));
char output[].append(charArray.at(3));
cout << output;
}
int main() {
testClass testObject;
testObject.testFunction("Flowers");
return 0;
}
}
What it's meant to do is:
get the Letters 'F', 'S' and 'O' from the char array from an index number
append that char to the output chararray
It's been frustrating since I've went from strings, to *chars, and char arrays.
Not really sure what the simpliest easiest solution is.
Yes, I want to retain 1 char at a time from that string.
It was just meant to be a fun project but it's way more complicated than I thought it'd be
expected output:
FSO
Do you mean like this:
#include <string>
#include <iostream>
class testClass {
public:
void testFunction(const std::string& charArray)
{
std::string output;
output.push_back(charArray.at(0));
output.push_back(charArray.at(6));
output.push_back(charArray.at(2));
std::cout << output;
}
};
int main() {
testClass testObject;
testObject.testFunction("Flowers");
return 0;
}
Of course C++ like any sane language uses zero-based indexes.
There is a ""rumor"" that I've heard in the competitive programming community that an approach to implementing a data structure, for example, using classes would render a much slower time than an implementation basing itself on a purely functional paradigm. I've tested this out (on my recursive segment tree implementation using classes then only functions that were practically the same) with a completely random generator (the queries and the updates had an equal probability in appearing in the testcase), and the results concured with the hypothesis; the purely functional program averaged (~7 seconds) twice better than the object-oriented implementation (~12.8 seconds) in high (5 mil - 10 mil queries+updates) inputs.
So, my question is, why would this difference is so accentuated, and why does it even happen in the first place?
Thank you for reading this!
Here's the code(maybe I messed up something and that's why all of this happened):
The class implementation:
#include <iostream>
using namespace std; //poor practice :P
class AINT {
int tree[1048700];
public:
void update(int val, int poz, int node=1, int cl=1, int cr=500000) {
if(cl==cr) {
tree[node]=val;
return;
}
int mid=(cl+cr)/2;
if(poz<=mid)
update(val,poz,2*node,cl,mid);
else
update(val,poz,2*node+1,mid+1,cr);
tree[node]=max(tree[2*node],tree[2*node+1]);
}
int query(int l, int r, int node=1, int cl=1, int cr=500000) {
if(l<=cl && cr<=r) {
return tree[node];
}
int mid=(cl+cr)/2,a=0,b=0;
if(l<=mid)
a=query(l,r,2*node,cl,mid);
if(mid<r)
b=query(l,r,2*node+1,mid+1,cr);
return max(a,b);
}
}aint;
int main() {
int n;
cin >> n;
for(int i=0,t,x,y; i<n; i++) {
cin>> t >> x>> y;
if(t==1)
aint.update(y,x);
else
cout << aint.query(x,y) <<'\n'; // i added the output (which I then redirected to a file) because it seems relevant to also print the values (otherwise the compiler might just ignore the unused result)
}
return 0;
}
the purely functional implementation:
#include <iostream>
using namespace std;
int tree[1048700];
void update(int val, int poz, int node=1, int cl=1, int cr=500000) {
if(cl==cr) {
tree[node]=val;
return;
}
int mid=(cl+cr)/2;
if(poz<=mid)
update(val,poz,2*node,cl,mid);
else
update(val,poz,2*node+1,mid+1,cr);
tree[node]=max(tree[2*node],tree[2*node+1]);
}
int query(int l, int r, int node=1, int cl=1, int cr=500000) {
if(l<=cl && cr<=r) {
return tree[node];
}
int mid=(cl+cr)/2,a=0,b=0;
if(l<=mid)
a=query(l,r,2*node,cl,mid);
if(mid<r)
b=query(l,r,2*node+1,mid+1,cr);
return max(a,b);
}
int main() {
int n;
cin >> n;
for(int i=0,t,x,y; i<n; i++) {
cin>> t >> x>> y;
if(t==1)
update(y,x);
else
x=query(x,y); // i added the output (which I then redirected to a file) because it seems relevant to also print the values (otherwise the compiler might just ignore the unused result)
x=y+x*x;
}
return 0;
}
the generator:
#include <iostream>
using namespace std;
static int rand(int a, int b) {
return rand()%(b-a+1)+a;
}
int main(int argc, char * argv[]) {
srand(atoi(argv[1]));
int n;
n=10000000;
cout << n << '\n';
for(int i=0; i<n; i++) {
int t=rand(0,1),x=rand(1,500000),y=rand(1,500000);
if(t==0 && x>y)
swap(x,y);
cout << t << ' ' <<x << ' ' <<y <<'\n';
}
}
It depends if your class defines constructors or destructors or inherits from another class and especially if it uses inherited virtual functions like:
class Animal{
virtual void makeSound(){}
virtual std::string getName(){}
};
class Dog : Animal{
void makeSound(){}
std::string getName(){}
};
than there is overhead for using the virtual function table. I know for a fact that virtual destructors can really kill performance. However just moving a bunch of functions into a class will not hurt your performance at all.
It's also arguable that your example of 'pure functional' is not even close to the tag definition.
If you meant using a bunch of functions in the global namespace vs functions wrapped in class, there is no performance differences if you compile with -O3 optimizations or Release Mode on MSVC.
Although if your not going to use the features of classes and you just want a way to organize and find functions use a namespace like:
namespace animal {
namespace dog {
void bark() {}
}
}
animal::dog::bark();
Also please be careful how your measuring performance, if you're timing std::cout or std::cin you're going to get terrible numbers IO is always very slow and totally inconsistent.
You would never measure IO operations if you can help it. I suggest you watch this: https://www.youtube.com/watch?v=YG4jexlSAjc
by The Cherno a.k.a. Yan Chernokov , his tutorials are fantastic.
I have the following code:
#include<iostream>
using namespace std;
void saludo();
void despedida();
int main(){
void (*Ptr_Funciones[2])() = {saludo, despedida};
(Ptr_Funciones[0])();
(Ptr_Funciones[1])();
return 0;
}
void saludo(){
cout<<"\nHola mundo";
}
void despedida(){
cout<<"\nAdios mundo"<<endl<<endl;
}
Based on this, a few questions were generated which I investigated before asking but did not fully understand.
The questions are:
How do I make an array of functions, if they are of a different type?
I know that in C ++ this notation is used for undetermined parameters: (type var ...) The
thing is, I don't know how to interact with them inside the function.
If questions 1 and 2 are possible, can these points be combined when creating function
arrays?
I really have investigated. But I can't find much information, and the little I did find I didn't understand very well. I hope you can collaborate with me.
Thank you very much.
How do I make an array of functions, if they are of a different type?
You can, but you don't want to. It doesn't make semantic sense. An array is a collection of the same kind of thing. If you find that you need to make a collection of different kinds of things, there are several data structures at your disposal.
I know that in C++ this notation is used for undetermined parameters: (type var ...) The thing is, I don't know how to interact with them inside the function.
Here's how you can use the syntax you mention. They're called variadic functions.
If questions 1 and 2 are possible, can these points be combined when creating function arrays?
Erm, I can't imagine why/when a combination of these two would be needed, but out of intellectual curiosity, awayyy we go...
A modified version of the code from the reference link above that kinda does what you want (i've used a map instead of an array, cuz why not):
#include <iostream>
#include <cstdarg>
#include <unordered_map>
template<typename T>
using fooptr = void (*) (T *t...);
struct A {
const char *fmt;
A(const char *s) :fmt{s} {}
};
struct B : public A {
B(const char *s) : A{s} {}
};
void simple_printf(A *a...)
{
va_list args;
auto fmt = a->fmt;
va_start(args, a);
while (*fmt != '\0') {
if (*fmt == 'd') {
int i = va_arg(args, int);
std::cout << i << '\n';
} else if (*fmt == 'c') {
// note automatic conversion to integral type
int c = va_arg(args, int);
std::cout << static_cast<char>(c) << '\n';
} else if (*fmt == 'f') {
double d = va_arg(args, double);
std::cout << d << '\n';
}
++fmt;
}
va_end(args);
}
int main()
{
A a{"dcff"};
B b{"dcfff"};
std::unordered_map<size_t, fooptr<struct A>> index;
index[1] = simple_printf;
index[5] = simple_printf;
index[1](&a, 3, 'a', 1.999, 42.5);
index[5](&b, 4, 'b', 2.999, 52.5, 100.5);
}
This still really doesn't do what you wanted (i.e., give us the ability to choose from different functions during runtime). Bonus points if you understand why that's the case and/or how to fix it to do what you want.
Use a type alias to make things readable:
Live On Coliru
using Signature = void();
Signature* Ptr_Funciones[] = { saludo, despedida };
Prints
Hola mundo
Adios mundo
More flexible:
You can also use a vector:
Live On Coliru
#include <iostream>
#include <vector>
using namespace std;
void saludo() { cout << "\nHola mundo"; }
void despedida() { cout << "\nAdios mundo" << endl << endl; }
int main() {
vector Ptr_Funciones = { saludo, despedida };
Ptr_Funciones.front()();
Ptr_Funciones.back()();
}
Prints the same.
More Flexibility: Calleables of Different Types
To bind different types of functions, type-erasure should be used. std::function helps:
Live On Coliru
#include <iostream>
#include <functional>
#include <vector>
using namespace std;
void saludo(int value) { cout << "\nHola mundo (" << value << ")"; }
std::string despedida() { cout << "\nAdios mundo" << endl << endl; return "done"; }
int main() {
vector<function<void()>>
Ptr_Funciones {
bind(saludo, 42),
despedida
};
Ptr_Funciones.front()();
Ptr_Funciones.back()();
}
Prints
Hola mundo (42)
Adios mundo
Here is one solution that is possible, whether it fits your needs I'm not sure.
#include <Windows.h>
#include <iostream>
void saludo()
{
std::cout << "\nHola mundo" << std::endl;;
}
void despedida()
{
std::cout << "\nAdios mundo" << std::endl;
}
void* fnPtrs[2];
typedef void* (VoidFunc)();
int main()
{
fnPtrs[0] = saludo;
fnPtrs[1] = despedida;
((VoidFunc*)fnPtrs[0])();
((VoidFunc*)fnPtrs[1])();
std::getchar();
return 0;
}
I want to create a static function pointer array, so I can jump to a certain function regarding a received index. Like an index jumper.
So imagine a class like this:
Class A
{
private:
static void 1stFunction();
static void 2ndFunction();
static void(*functionPointer[20])(void);
};
Then I would like that functionPointer to get the value of the 1stFunction and 2ndFunction, and maybe even more.
So, how do I initialize it?
As far as I know, when a static member is declared, you can use it even before an instance is created. So I though, lets initialize that function pointer, so later I can call it like this
functionPointer[receivedIndex]();
So i tried to initilize it like this, in the same .h file
void (*A::functionPointer[])(void) =
{
A::1stFunction,
A::2ndFunction,
};
But the compiler gives me redifinition, it says it's already created.
So, pretty sure I'm missing something. I don't know though, if it is syntax or simply it is not possible to do it this way.
I know that function pointers to class's member functions are different than normal function pointers... But this is a static function, so I believe it doesn't belong to an instance and therefore it should work with normal function pointers.
Any help would be appreciated.
Thanks
The following would be a working example that probably achieves what you need.
You need C++11 for the initializer list.
It is a good practice to initialize the static member in the cpp file, as you don't want to have a definition of the static member everytime the header is included (this can lead to linking issues).
You can call callf with the desired index and have the corresponding function called, based on the initialization of the function pointer array.
The output of the program would be:
I am 2ndFunction
Header file
class A
{
private:
static void Function1();
static void Function2();
static void(*functionPointer[20])();
public:
static void callf(int index);
};
Implementation
#include <iostream>
#include "ex.h"
void(*A::functionPointer[20])() {
A::Function1,
A::Function2
};
void A::Function1() {
std::cout << "I am 1stFunction" << std::endl;
}
void A::Function2() {
std::cout << "I am 2ndFunction" << std::endl;
}
void A::callf(int index) {
A::functionPointer[index]();
}
int main(int argc, char const *argv[]) {
A::callf(1);
return 0;
}
Here you have a more modern C++ approach (C++14 needed)
I would advise you to explore lambda functions if you are not restricted to C++03.
#include <iostream>
#include <functional>
#include <vector>
class A {
public:
using f_type = std::function<void(void)>;
f_type f1 = []() { std::cout << "f0" << std::endl;};
f_type f2 = []() { std::cout << "f1" << std::endl;};
static void f3() { std::cout << "f3" << std::endl; }
std::vector<f_type> functions{f1, f2, f3};
};
int main() {
A a;
a.functions[0]();
a.functions[1]();
//adding custom lambda
a.functions.emplace_back([](){ std::cout << "custom f" << std::endl;});
a.functions[2]();
return 0;
}
you can add both functions and lambdas to your container.
I'm having trouble declaring and initializing a char array. It always displays random characters. I created a smaller bit of code to show what I'm trying in my larger program:
class test
{
private:
char name[40];
int x;
public:
test();
void display()
{
std::cout<<name<<std::endl;
std::cin>>x;
}
};
test::test()
{
char name [] = "Standard";
}
int main()
{ test *test1 = new test;
test1->display();
}
And sorry if my formatting is bad, I can barely figure out this website let alone how to fix my code :(
If there are no particular reasons to not use std::string, do use std::string.
But if you really need to initialize that character array member, then:
#include <assert.h>
#include <iostream>
#include <string.h>
using namespace std;
class test
{
private:
char name[40];
int x;
public:
test();
void display() const
{
std::cout<<name<<std::endl;
}
};
test::test()
{
static char const nameData[] = "Standard";
assert( strlen( nameData ) < sizeof( name ) );
strcpy( name, nameData );
}
int main()
{
test().display();
}
Your constructor is not setting the member variable name, it's declaring a local variable. Once the local variable goes out of scope at the end of the constructor, it disappears. Meanwhile the member variable still isn't initialized and is filled with random garbage.
If you're going to use old-fashioned character arrays you'll also need to use an old-fashioned function like strcpy to copy into the member variable. If all you want to do is set it to an empty string you can initialize it with name[0] = 0.
Since you are using C++, I suggest using strings instead of char arrays. Otherwise you'd need to employ strcpy (or friends).
Also, you forgot to delete the test1 instance.
#include <iostream>
#include <string>
class test
{
private:
std::string name;
int x;
public:
test();
void display()
{
std::cout<<name<<std::endl;
}
};
test::test()
{
name = "Standard";
}
int main()
{
test test1;
test1.display();
std::cin>>x;
}
Considering you tagged the question as C++, you should use std::string:
#include <string>
class test
{
private:
std::string name;
int x;
public:
test();
void display()
{
std::cout<<name<<std::endl;
std::cin>>x;
}
};
test::test() : name("Standard")
{
}
c++11 actually provides two ways of doing this. You can default the member on it's declaration line or you can use the constructor initialization list.
Example of declaration line initialization:
class test1 {
char name[40] = "Standard";
public:
void display() { cout << name << endl; }
};
Example of constructor initialization:
class test2 {
char name[40];
public:
test2() : name("Standard") {};
void display() { cout << name << endl; }
};
You can see a live example of both of these here: http://ideone.com/zC8We9
My personal preference is to use the declaration line initialization because:
Where no other variables must be constructed this allows the generated default constructor to be used
Where multiple constructors are required this allows the variable to be initialized in only one place rather than in all the constructor initialization lists
Having said all this, using a char[] may be considered damaging as the generated default assignment operator, and copy/move constructors won't work. This can be solved by:
Making the member const
Using a char* (this won't work if the member will hold anything but a literal string)
In the general case std::string should be preferred