how to call the function for an array of classes c++ - c++

I created a class in C++ called Commands (file name commands.cpp).
I've taken that and put it into a command array (file name test.cpp).
What I would like to know is how to call the functions that are within the Commands class.
for example I have a function within the Commands class
called
void command::init(char data[])
{
//detail
}
and what i have tried to do to call the function is
EDIT
Class test{
int CmdCount; // number of commands in the array
int MaxCmds; // max amount of commands allowed
command* cmds;
Public:
int get_command_count() const{
return CmdCount;
}
int readfile(const char fname[]){
char line[161];
FILE* fp;
fp = fopen(fname, "r");
if(fp){
for(int i = 0; 1 == fscanf(fp, "%160[^\n]\n", line; i++){
cmds[get_command_count()].init(line);
CmdCount += 1;
}
}
fclose(fp);
}
};
I just want to know how to be able to call void command::init(char data[]).
Any suggestions?
thanks.

Sounds like your array contains instances of your class. In that case you want to call the method on a single entry in the array:
my_array[i].someMethod();
where my_array[i] is an instance of your class.

Related

Why can't I set a value inside of this class?

I have a class:
class SendData
{
public:
SendData(int SendAMsg(int foo, unsigned char *bar, int length), int number)
{
m_nDefinePos = 0;
m_nOtherStuffDefinedAs =0;
}
void somestuffhere();
void ClearDefinition();
private:
int aLotOfVariableshere;
int m_nDefinePos;
};
This is the class itself. Then some stuff is called:
SendData* m_pData;
m_pData->ClearDefinition();
Which now calls this one:
void SendData::ClearDefinition()
{
printf("Welcome to Clear Definition Script\n");
m_nDefinePos = 0;
// Some more stuff here
}
Here the code breaks somehow. I get the "Welcome to Clear Definition Script" message in my console, but that's all.
It breaks on m_nDefinePos = 0;. (I did put in another printf command after it, never showed in the console.)
I just don't know why it breaks there and i cant find any error.
SendData* m_pData;
m_pData->ClearDefinition();
This declares a pointer, but doesn't create an object or initialise the pointer to point to anything, so calling a member function via the pointer will go wrong. Perhaps you wanted to create an object:
SendData data(arguments);
data.ClearDefinition();
or perhaps you wanted to initialise the pointer to point an object that already exists:
SendData* m_pData = whatever;

C++ Wrapper to GNU Readline

I am trying to write a c++ wrapper for GNU Readline to be able to easily use custom completion but came across a small problem and can't think of a solution(I am still new to c++).
class ReadLine {
public:
ReadLine();
~ReadLine();
std::string exec ();
void enableHistory ();
private:
std::vector<std::string> keywordList;
bool history;
private:
static char** my_completion (const char*, int, int);
void* xmalloc (int);
char* generator (const char*, int);
char* dupstr (std::string);
};
cpp file:
std::string ReadLine::exec(){
rl_attempted_completion_function = my_completion;
std::string buf = "";
buf = readline("Command>>");
//enable auto-complete
rl_bind_key('\t',rl_complete);
if (buf[0]!=0)
add_history(buf.c_str());
return buf;
}
char** ReadLine::my_completion (const char* text, int start, int end) {
char** matches;
matches = NULL;
if (start == 0)
matches = rl_completion_matches(text, my_generator);
return matches;
}
My problem is the line
matches = rl_completion_matches(text, my_generator)
It obviously throws an error: call to non-static member function without an object argument but I don't want to make the generator static and I can't find what arguments it should take, because I won't be able to access class members inside of it (I need keywordlist to generate keywords).
What would you suggest?
It's not easy to solve this one in a good way, since the normal solution is to solve it by having a static wrapper function where you pass the pointer to the class in as an argument.
Someone else may be able to come up with something better, but I think the solution is to have a global variable that is a pointer to the current ReadLine class instance - this could be a stack, so you can push a new one onto it, and then pop it to get back to the old one when that's done.
In the simple case, you'd have something like this:
ReadLine *currenReadLine = 0;
....
std::string ReadLine::exec(){
...
currentReadLine = this;
}
// declared as static in the class.
char ** ReadLine::my_completion(...)
{
return currentReadLine->actual_completion(...);
}
And a similar solution for the my_generator.

C++ Passing pointer to function

OK i have a function
int main
{
....
char *wordl=word();//wordl pointer is an array of characters
...
gamewindow(wordl,length);
}
void gamewindow(char &wordl,int length);
My question is how to pass pointer such that passed pointer points to the same array list..
and i can access it by wordl[i] in gamewindow function.
From the comment below, implementation of word():
char* word()
{ int j=1988497762; cout<<j<<endl ;
static char original[25];
int x;
ifstream fin("out.txt");
for (j=0;!fin.eof();j++)
fin.getline(original,25);
fin.close();
srand ( (unsigned) time(NULL) );
x = rand()%j; cout<<x<<"\n";
cout<<rand()<<endl;
char c;
ifstream finn("out.txt");
for (j=0; !finn.eof(); j++)
{ finn>>c; finn.getline(original,25); if (x==j) break; }
finn.close();
return original; }
If you really want to use it like this only (and not use std::vector or std::string) you need change gamewindow to void gamewindow(char *wordl,int length); Then you can access char using word1[i].
Better use std::string, std::vector and other standard containers. If on C++2011, use perhaps std::array
So declare instead
void gamewindow(std::string&str);

How can I access a class's member function via an array of pointers?

I have a pretty standard class with some public member functions and private variables.
My problem originally stems from not being able to dynamically name object instances of my class so I created an array of pointers of the class type:
static CShape* shapeDB[dbSize];
I have some prompts to get info for the fields to be passed to the constructor (this seems to work):
shapeDB[CShape::openSlot] = new CShape(iParam1,sParam1,sParam2);
openSlot increments properly so if I were to create another CShape object, it would have the next pointer pointing to it. This next bit of code doesn't work and crashes consistently:
cout << shapeDB[2]->getName() << " has a surface area of: " << shapeDB[2]->getSA() << shapeDB[2]->getUnits() << endl;
The array of pointers is declared globally outside of main and the get() functions are public within the class returning strings or integers. I'm not sure what I'm doing wrong but something relating to the pointer set up I'm sure. I'm writing this code to try and learn more about classes/pointers and have gotten seriously stumped as I can't find anyone else trying to do this.
I'm also curious as to what the CShape new instances get named..? if there is any other way to dynamically create object instances and track the names so as to be able to access them for member functions, I'm all ears.
I've tried all sorts of permutations of pointer referencing/de-referencing but most are unable to compile. I can post larger chunks or all of the code if anyone thinks that will help.
class CShape {
int dim[maxFaces];
int faces;
string units;
string type;
string name;
bool initialized;
int slot;
public:
static int openSlot;
CShape();
CShape(int, string, string); // faces, units, name
~CShape();
void initialize(void);
// external assist functions
int getA(void) {
return 0;
}
int getSA(void) {
int tempSA = 0;
// initialize if not
if(initialized == false) {
initialize();
}
// if initialized, calculate SA
if(initialized == true) {
for(int i = 0; i < faces; i++)
{
tempSA += dim[i];
}
return(tempSA);
}
return 0;
}
string getUnits(void) {
return(units);
}
string getName(void) {
return(name);
}
// friend functions
friend int printDetails(string);
};
// constructor with values
CShape::CShape(int f, string u, string n) {
initialized = false;
faces = f;
units = u;
name = n;
slot = openSlot;
openSlot++;
}
My guess is you use the CShape constructor to increment CShape::openSlot?
You're probably changing the value before it's read, thus the pointer is stored in a different location.
Try replacing openSlot with a fixed value to rule out this CShape::option.
-- code was added --
I'm pretty sure this is the problem, the constructor is executed before the asignment, which means the lhs. will be evaluated after CShape::openSlot is incremented.

C++ Implementing Functions that don't utilize global declarations

My code is already working, seen here: http://pastebin.com/mekKRQkG
Right now, my functions work but utilizing information that I've declared globally, I guess, and I want to convert them so that they are in the format as seen on lines 11-15, but I'm unsure of how to convert them to do so. Simply put, I'm trying to convert my function of
"void add_county_election_file"
to be in the format of
"void add_county_election_file(const string, const vector &, const vector &, const vector &, const vector &)"
and I have no idea where to begin or how to even start.
Could someone please help me out and show me how I'd do this for the first function, so I can implement it across the board?
Thanks guys!
Your function declaration should look something like this:
void add_county_election_file(const string, vector<int>&, vector<string>..);
Make sure that your argument list for the vector template is correct(that's the type you put between <>)
Then match the implementation of you function to the declaration:
void add_county_election_file(const string, vector<int>&, vector<string>..){...}
Now call your function with apppropriate arguemtns in main:
string s;
vector<int> arg;
vector<string> sv;
void someFunction (s, arg, sv ...);
I think you are doing correct as the function you have declared
void add_county_election_file(const string, vector<int>&, vector<int>&,..);
so you just have to call the above function with the required arguments, as right now you are not passing the argument and your current definition doesn't accepts any arguments.
And as a good practice, in your int main() function you can use switch rather than going for if else.
Store your variables and functions in a class, overload operators and create functions to access these variables.
Declare all variables in int main() and set parameters to be passed into each function e.g.
void print_results() is modified to become
void print_results(std::vector<int> vec, int nCount, etc..)
Similar to the first one, create a struct to hold all data members, then pass the struct(by ref) into each function.
struct CountryTracker
{
std::vector<int> ID;
std::string name;
//etc...
}
`void print_results(CountryTracker& Obj) //pass single struct into functions`
The OOP way to do this is to create a class called perhaps ElectionInfo, where:
These would be its member fields:
vector <string> countyNameVector;
vector <int> countyNCount;
vector <int> countyFCount;
vector <int> countyOCount;
int NCount;
int FCount;
int OCount;
int NTotal;
int FTotal;
int OTotal;
and these would be its member functions:
void add_county_election_file(const string);
void search_county(const string);
void print_results();
This way you don't have to pass the references to the vectors around at all, instead you can just do:
ElectionInfo an_elect_info;
char selection = get_menu_choice();
// some if-statements to decide which of the following to call:
an_elect_info.add_county_election_file(county_name);
an_elect_info.search_county(county_name);
an_elect_info.print_results();
But if you'd prefer to stay with the current functional approach:
Declare and initialize the following inside your main method:
vector <string> countyNameVector;
vector <int> countyNCount;
vector <int> countyFCount;
vector <int> countyOCount;
int NCount;
int FCount;
int OCount;
int NTotal;
int FTotal;
int OTotal;
The syntax for the commented out function declarations should be tweaked to look like this:
void add_county_election_file(const string, vector<string>&, vector<int>&, vector<int&, vector<int>&);
(Of course, the definition should follow suit)
You would invoke it like this:
add_county_election_file(countyname, countyNameVector, countyNCount, countyFCount, countyOCount);
Objects are automatically passed-by-reference.
The basic process of refactoring should at the first step involve only code grouping and placement and should only minimally involve writing new logic. Using this as a principle you can go about modifying the code in the following way at first.
string ReadInputString(const char* title)
{
string s
cout << title;
cin >> s;
}
void add_county_election_file(const std::string& filename
, std::vector<string>& countyNameVector
, std::vector<int>& countyNCount
, std::vector<int>& countyFCount
, std::vector<int>& countyOCount
)
{
int NCount = 0;
int FCount = 0;
int OCount = 0;
int NTotal = 0;
int FTotal = 0;
int OTotal = 0;
char vote;
std::ifstream input((filename).c_str());
string countyName;
if(input.is_open())
{
input >> countyName;
countyNameVector.push_back(countyName);
while(input >> vote)
{
if(vote == 'N' || vote == 'n')
{
NCount = NCount + 1;
}
else if(vote == 'F' || vote == 'f')
{
FCount = FCount + 1;
}
else
{
OCount = OCount + 1;
}
}
countyNCount.push_back(NCount);
countyFCount.push_back(FCount);
countyOCount.push_back(OCount);
}
cout << countyName << endl;
}
void add_county_election_file()
{
string fn = ReadInputString("Enter the county file to process: ");
add_county_election_file(fn,g_countyNameVector,g_countyNCount,g_countyFCount,g_countyOCount);
}
As you can see I have just extracted your code and moved them to individual functions and changed names to make some significance. Like in the function ReadInputString - the line "cin >> s" was originally "cin >> filename". The abstract name "s" is to signify that the ReadInputString has no knowledge or doesn't care what the semantic meaning of the string it is reading from console.
In order to not change your main function - I have added a overloaded add_county_election_file that calls one function followed by another. The idea is that you should keep something unchanged and change others (for good) and then alternate if need be.
And I have changed names of your global variable to differentiate them from the local variable using "g_" - the point is that "g_" should only be found at very few places in your code.