How to access a function of an object that was returned as a pointer by another function. - c++

It's the guy who was making the boggle simulator again! This time I have the issue of having a function that was forced to return a pointer to an object for syntax reasons. I want to access a function of the object that said pointer points to. How should I go about this? My code for the functions involved is below.
boggleNode * nextNode(int adj){
return adjacency[adj]; //For switching between nodes.
}
bool getUsed(){
return isUsed;
}
private:
boggleNode * adjacency[8];
char letter;
bool isUsed;
};
And finally, here is the function that contains the functions above:
int sift(boggleNode bog, string word, string matcher){
int endofnodes;
string matchee;
if (bog.getData() == 'q')
matchee = matcher + bog.getData() + 'u';
else
matchee = matcher + bog.getData();
if (compare(word, matcher) == 0){
cout << word << endl;
return 5; //If it finds the word, escape the loop.
}
if (word.find(matcher) == 0){
bog.makeUsed();
for (int j = 0; j < 8; j++){
if (bog.nextNode(j) != NULL){
if ((bog.nextNode(j)).getUsed() == 0){
endofnodes = sift(bog.nextNode(j), word, matchee);
if (endofnodes == 5)
return endofnodes;
}
}
bog.reset();
return 0;
//If it doesn't find anything, move onto next adjacency.
/*any words share a common starting letter sequence with matcher*/
//Sift using an adjacent node, and add the old string to the new one.
}
}
}
In which I am specifically asking about this line:
if ((bog.nextNode(j)).getUsed() == 0)
When I attempt to compile this code, I get " error: request for member
getUsed' in(&bog)->boggleNode::nextNode(j)', which is of non-class
type `boggleNode*' "
Any help is greatly appreciated. Thanks in advance!

You should use -> instead of .:
if ((bog.nextNode(j))->getUsed() == 0)
which is shorthand, in this case, for:
if ((*(bog.nextNode(j))).getUsed() == 0)

Related

C++: Char pointer to char pointer array to char array

I'll do my best to be brief:
So I have an assignment where I am creating a 'Wordlist' class. In which I will store a list of words.
These are the member variables
class WordList
{ //...
unsigned int m_count; // Number of words currently in list
unsigned int m_max; // The total size of the list.
char** m_list; // The list storing the words
};
This is my constructor
WordList::WordList(const int max_words) {
if(max_words < 1){
m_list = nullptr;
m_max = 0;
m_count = 0;
}
else
m_list = new char*[max_words];
m_count = 0;
m_max = max_words;
for (int i = 0; i < max_words; i++) {
m_list[i] = new char[20];
}
}
And this is where I start to find problems.
The following add function is supposed to add a word in the form of a c-style string that is pointed to from the array of character pointers that is pointed to from **char m_list .
int WordList::add(const char word[]) {
if (m_count == 0 && m_list != nullptr ) {
strcpy (m_list[m_count], word);
m_count++;
return 0;
}
if (m_count < m_max) {
m_count++;
strcpy (m_list[m_count], word);
return 0;
}
if (m_count == m_max) {
m_count++;
m_max ++;
strcpy (m_list[m_count], word);
return 1;
}
if (strlen(word)==0) {
return -2;
}
if (m_list == nullptr ){
return -2;
}
else
return -2;
}
So the issue I am having is that I clearly not syntactically correct with my * because I am not getting an array of 5 pointers that point to full words rather I am getting the first letter saved to the final destination char but its not copying over everything like I want.
I'm sure I didn't translate my problem to English as well as I should have but hopefully thats a start. Thank you!
An example of how I will be calling my add function:
WordList *wordlist = new WordList(5);
wordlist->add("harry");
wordlist->add("ron");
wordlist->add("hermione");
And it should add to the bottom of the pointer array a pointer to each word
so
cout << wordlist->m_list[0][2] << endl; // Expect 'r'
cout << wordlist->m_list[1] << endl; // Expect "ron"
instead I get
r
printed out only
I don't see anything wrong with your use of double-pointers.
There are other issues, though:
in your WordList::add you should check for empty word or empty list first, and fail fast. Besides, in your code if the word was empty - you would already added it and returned form that function.
in if (m_count < m_max) block, you pre-increment m_count, leaving one element empty and risking to go out-of-bounds on the last entry.
in if (m_count == m_max) { you are CERTAINLY going out-of-bounds
Suggestion: instead of pre-allocating 20-character arrays, leave them nullptr; when you need to a word - use strdup(word); that would allocated a required space for you.
As for your I am getting the first letter saved - I am guessing you are not checking it right...
The problem is that you add the first word:
if (m_count == 0 && m_list != nullptr ) {
strcpy (m_list[m_count], word);
m_count++;
return 0;
}
Which increments m_count so now m_count is 1.
Then you add the second word:
if (m_count < m_max) {
m_count++;
strcpy (m_list[m_count], word);
return 0;
}
Which increments m_count BEFORE adding the word so the second word is at index 2 and index 1 is skipped altogether.
You need to always increment the count after copying the word because m_count is 1 based and the array is 0 based.

C++ There is a bool return type function returning (24) here

First of all sorry for too much code
Here there is a vector (teamNum) with type class, the class contain a vector (player) with type struct, it is a little complicated, but here in this function I need to check if there is a player in teamNum which contain tName equal to _tname (function parameter) contain (the player) pID equal to _pID (function parameter)
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
if (teamNum[i].tName == _tname)
{
for (int j = 0; j < teamNum[i].player.size(); j++)
{
if (teamNum[i].player[j].pID == _pID)
return true;
}
}
else if (i == (teamNum.size() - 1))
{
return false;
}
}
}
And in the main
int main()
{
cout << "\n" << thereIsSimilarID("Leverpool", 1) << endl;
}
The output is 24 !!!!!
(good note that this happen just when the team (Leverpool) is the last team in the vector teamNum)
Again sorry for too much code but I need to know the bug not only fix the problem I need to learn from you
You encountered undefined behaviour.
If you take the if (teamNum[i].tName == _tname)-branch on the last element, but find no player with the correct pID, you don't return anything. Which means, that the return value is whatever random value is currently in the memory location that should hold the return value. In your case it happens to 24. But theoretically, everything could happen.
The same problem occurs when teamNum is empty.
The solution is to make sure to always return a value from a function (except if it has return type void of course):
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
// In this loop return true if you find a matching element
}
// If no matching element was found we reach this point and make sure to return a value
return false;
}
You should take a look at your compiler settings and enable all the warnings. And often it's good to let it treat certain warnings as errors.

Searching a vector of object pointers

I have a Player class where each object of the type Class has a name, wins, losses, and draws. Each object of the Player class is created by calling the_player = new Player(the_name). When the user inputs a new name to add a Player object to the program a pointer is pushed into a vector AllPlayers. The program should check before pushing the new pointer that the desired player does not already exist in said vector. I have to do this check several times throughout my program so I thought I'd write a function for it. Here is my function:
int findPlayer(vector<Player*> &vals, string name_in)
{
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
else
return -1;
}
};
When the option is requested to add a new Player the following code is used:
do {
cout << "Name: ";
cin >> the_name;
if (findPlayer(AllPlayers, the_name) != -1){
cerr << "Player already exists\n";
}
} while (findPlayer(AllPlayers, the_name) != -1);
the_player = new Player(the_name);
AllPlayers.push_back(the_player);
For some reason, though, every time I try to add a new player it throws "Player already exists" and never leaves the do-while loop. This is even true when the AllPlayers vector is empty. I added a cout << findPlayer(AllPlayers, the_name) for debugging and it printed 4192252 which I assume is the largest element possible in a vector.
So the question is: Why does it return 4192252 rather than -1?
If vals is empty then the for loop is never entered and the function exits without hitting a return statement. Meaning that you get a random value returned instead, in this case 4192252 happens to be in the return register. Your compiler warnings will have told you this if you read them.
What you think, what will be returned from findPlayer if vals is empty?
Is it defined?
If the vector is empty, you don't enter the loop at all, so don't reach a return statement and don't return a valid value. You should enable compiler warnings to catch this error.
Otherwise, you only check the first item, and return immediately whether or not it matched. You want to return if you find a match, but keep looking otherwise, and only return -1 if there is no match:
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
}
return -1;
The find player function should be something like:
int findPlayer(vector<Player*> &vals, string name_in)
{
if(vals.size() == 0)
return -1;
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
}
return -1;
};
Rewrite the function the following way
bool findPlayer( const std::vector<Player*> &vals, const std::string &name_in )
{
std::vector<Player*>::size_tyoe i = 0;
while ( i < vals.size() && vals[i]->getName() != name_in ) ++i;
return i != vals.size();
}
Take into account that member function getName has to be defined with qualifier const.
As for your function then it returns nothing in case when the vector is empty or returns -1 in case when the first element of the vector does not coincide with the string.
Take into account that there is standard algorithm std::find_if declared in header <algorithm> that can be used instead of your function.

Count word in trie implementation

I'm implementing a trie to implmenta spelling dictionary. The basic element of a trie is a trienode, which consists of a letter part (char), a flag(whether this char is the last char of a word), and an array of 26 pointers.
Private part of the TrieNode class include:
ItemType item;//char
bool isEnd;//flag
typedef TrieNode* TrieNodePtr;
TrieNodePtr myNode;
TrieNodePtr array[26];//array of pointers
This is part of the test call:
Trie t4 = Trie();
t4.insert("for");
t4.insert("fork");
t4.insert("top");
t4.insert("tops");
t4.insert("topsy");
t4.insert("toss");
t4.print();
cout << t4.wordCount() << endl;
Right now I'm trying to traverse the trie to count how many words there are (how many flags are set to true).
size_t TrieNode::wordCount() const{
for (size_t i = 0; i < 26; i++){
if (array[i] == nullptr){
return 0;
}
if (array[i]->isEnd && array[i] != nullptr){
cout << "I'm here" << endl;
return 1 + array[i]->wordCount();
}
else if(!array[i]->isEnd && array[i]!=nullptr){
cout << "I'm there" << endl;
return 0 + array[i]->wordCount();
}
else{
// do nothing
}
}
}
Every time the function returns 0. I know it's because when the first element in the array is null, then the function exits, so the count is always 0. But I don't know how to avoid this, since every time I have start from the first pointer. I also get a warning:not all control paths return a value. I'm not sure where this comes from. How do I make the function continue to the next pointer in the array if the current pointer is null? Is there a more efficient way to count words? Thank you!
Here is a simple and clear way to do it(using depth-first search):
size_t TrieNode::wordCount() const {
size_t result = isEnd ? 1 : 0;
for (size_t i = 0; i < 26; i++){
if (array[i] != null)
result += array[i]->wordCount();
return result;
}

Nested for loop being ignored after if-else chain

I am programming a MARIE assembler for one of my classes and I've ran into a logical error involving my control structure for one of my functions.
What I'm trying to accomplish is taking in all the data that was inserted into my vectors and then that data is being used to create integer opcode data for display. Yet for whatever reason my nested for loop is being ignored after my if-else chain.
The code within the nested for-loop seems to be working properly aside from this one logic error.
Please note that instructions, hexNums, secondPassData, valueZ, and symBols are my vectors.
For some clarification:
The If-Else chain is just used to read instruction words and to set basedInt to the proper decimal number for later hexadecimal conversion.
There are a few special conditions in the code below which are marked.
If there is no special condition then the code checks the valueZ vector at instructions.at(i) to see if the valueZ element is in symBols.
If it is a symBol element through character checks, it takes its hexNums position and adds it to the basedInt.
If it is not, it instead has its corresponding valueZ element converted from string to int and then added to the basedInt.
Those elements are added to the secondPassData vector.
int basedInt;
int newInt;
int pushInt;
string temp;
for(unsigned int i = 0; i < instructions.size(); ++i) //if i is less then instructions.size(), follow through with the statement
{
if(instructions.at(i) == "JNS") //sets basedInt to a decimal version of its hexidecimal opcode
{
basedInt = 0;
}
else if(instructions.at(i) == "HALT") //a special condition where the number is plugged into the secondPassData vector automatically
{
secondPassData.push_back(28672);
continue;
}
else if(instructions.at(i) == "CLEAR") //same as above
{
secondPassData.push_back(-24576);
continue;
}
else if(instructions.at(i) == "ADDL")
else if(instructions.at(i) == "ORG")
{
secondPassData.push_back(0000);
continue;
}
else if(instructions.at(i) == "HEX") //checks for the HEX psuedo-OP.
{
temp = valueZ.at(i); //converts it at position i to a string
basedInt = atoi(temp.c_str()); //converts that string to an int.
secondPassData.push_back(basedInt);//pushes into vector.
continue;
}
else if(instructions.at(i) == "DEC")
{
temp = valueZ.at(i);
basedInt = atoi(temp.c_str()); //similar function as above.
secondPassData.push_back(basedInt);
continue;
}
else
{
cout << "Beep Boop, program borked!" << endl;
return;
}
//for some reason the code below is getting ignored.
cout << i << endl;
for(unsigned int a = 0; a < instructions.size(); ++a) //works
{
cout << i << " " << a << endl;
string valFind = valueZ.at(i);
string symFind = symBols.at(a); //works
temp = valueZ.at(i);
if(symFind[0] == valFind[0])
{
newInt = hexNums.at(a);
pushInt = basedInt + newInt;
secondPassData.push_back(pushInt);
break;
}
else if(symFind[0] != valFind[0]) //works
{
temp = valueZ.at(i);
newInt = atoi(temp.c_str()); //works
pushInt= basedInt + newInt;
secondPassData.push_back(pushInt); //works
break;
}
break;
}
}
If you hit a continue in your else-if chain your main for loop will jump to its next iteration and will skip the rest of your code (in this case your nested for loop)
continue