Subscript operator overloading to access a private array - c++

I am trying to overload the operator[], however, something funky is going on.
To avoid long codes here, I put the code on GitHub (I'll keep the code as is there forever).
The issue is that when I access the subscript, it doesn't return the GameEntry when accessing s[0], but Scores. In addition to that the << operator returns the whole array, while I was requesting only one of the entries.
Please, advise. Thanks
EDIT: The operator[] is declared on line 58.

This line declares pointer to Scores:
Scores *s = new Scores(5);
So instead of
cout << typeid(s[0]).name() << endl;
try
cout << typeid((*s)[0]).name() << endl;

Related

Using a class/struct member delared inside 'if' conditional outside

I am attempting to recreate some "R" scripts in C++, just for the fun of it. Have used C decades ago but not recently. Now what I have is a bit of code where I am reading data from a binary file and placing the data into a structure (or class) with an unknown number of array structures (for the file reading side). Not knowing exactly how many arrays are needed, I define the number after reading another binary file which contains that data. So, I have two options; one to enter new data (which saves that plus the number of arrays to two files); another to read saved data back in (which provides the number of needed array structures). Having done either option via 'IF' conditionals, I need the new or recovered data to perform math on outside those conditionals. This is where things go wrong. The data is not available. The simple example recreates the problem and I have not stumbled upon the solution yet. I am not familiar enough with C++ to find what is most likely something simple to fix. The 'closed' function's first line outside the 'if' conditionals does work as expected, but that's not the data I need, and I don't want that line in the program.
#include <iostream>
using namespace std;
void closed(void);
class traverse {
public:
int sta;
};
int main()
{
closed();
return 0;
}
void closed(void)
{
traverse stations[1]; // removes 'stations was not declared' error on line 35.
cout << "Enter 1 or 2\nSelect: ";
int selType;
cin >> selType;
if (selType == 2) {
cout << selType << " selected\n";
traverse stations[1];
stations[0].sta = 2; //need this member value available outside conditional.
cout << "Value is " << stations[0].sta << " inside." << endl;
} else {
cout << selType << " selected\n";
traverse stations[1];
stations[0].sta = 1; //need this member value available outside conditional.
cout << "Value is " << stations[0].sta << " inside." << endl;
}
cout << "Value is " << stations[0].sta << " outside." << endl;
}
I originally used a 'struct' but decided to try a 'class' to discover the differences. But, the same problem persists with both, so I don't think it is anything with the definitions, but perhaps with different declarations. Any ideas would be greatly appreciated. Thanks.
If you need it to live longer than the scope of the if, then declare it in the outer scope where you need it to continue living.
After you added this line to deal with the warning:
traverse stations[1]; // removes 'stations was not declared' error on line 35.
You left the declaration of stations inside the if. That hides the outer name, and will receive the data, then go out of scope when the brace-enclosed block exits. To put data into the outer stations don't hide it.
If you need this data to live longer than the function call itself, you'll need to pass in an object to be written into, or allocate and return one to the caller. Perhaps a vector? I don't like (or recommend) to pass raw arrays because they decay to pointers and lose the bounds encoding from their type. That makes it too easy to go out of bounds without being very careful. There are smart pointer wrappers you could use, or a span class, etc., to help do it more sensibly.

Getting a segmentation error when printing my array of strings

Hello all c++ noob here,
For my homework in c++ I must create a program that inputs 5 cities and prints them in order and reverse order by the users choice using arrays and seperate functions. The homework requires that you use all these functions to operate. The program runs fine until I enter o or r for reverse order. I get a segmentation error. I think I am printing or passing the strings incorrectly.
Here is my declaration of my array function
void displayInOrder (string o[5]);
Now here is my function with the executable code.
void displayInOrder (string o[5])
{
cout << "Here are the cities in order: " << endl;
cout << o[0] << " " << o[1] << " " << o[2] << " " << o[3] << " " << o[4]
<< endl; //the error seems to lie somewhere in here and the same
//in the reverse function
}
Now in the main I am calling the function like this.
displayInOrder (&cities[5]);
I think I am either calling the function incorrectly, declaring it wrong, or printing it wrong. It's been a while since I programmed in C++ and I am a bit of a noob. I appreciate any help anyone has to offer.
The displayInOrder() function is expecting a pointer to an the whole array. Instead, you passed a pointer to cities[5]. This has two problems:
It's a pointer to a specific element, not the whole array.
The last element of the array is cities[4], so you're accessing outside the array bounds.
You should call the function this way:
displayInOrder(cities);
There's no need to use &, an array variable automatically decays to a pointer when used as a function argument.

C++ cannot read from 2D string array

this cold be really obvious but I havent done C++ in about 15 years so thanks in advance.
I have a 2D array of strings and when I read from it I get this:
0x22fc90
Here is my code, any ideas?
std::string results[3][3] = {
{"Draw", "Win", "Lose"} , /* initializers for row indexed by 0 */
{"Lose", "Draw", "Win"} , /* initializers for row indexed by 1 */
{"Win", "Lose", "Draw"} /* initializers for row indexed by 2 */
};
cout << "It's a " << results[choice,compChoice];
choice and compChoice are integers
There is a difference between for example the C++ syntax and the C# syntax for multidimensional arrays. What you wrote in this statement relative to accessing an element of the array
cout << "It's a " << results[choice,compChoice];
is valid in C# and does what you mean.
In C++ this statement
cout << "It's a " << results[choice,compChoice];
is also valid but its meaning is different. There is used the so-called comma operator in the subscript operator results[choice,compChoice] that in fact is equivalent to results[compChoice] except that the first subexpression will not be evaluated. So results[compChoice] gives a row of the two-dimensional array and operator<< outputs its address.
What you want is the following
cout << "It's a " << results[choice][compChoice];
Access the array using results[choice][compChoice].
That's because two dimensional arrays are actually arrays of arrays.
First you need to go into results[choice] and then you select [compChoice] from that.
choice,compChoice just evaluates to compChoice, so you are just outputting the pointer to the start of the choiceth array in results. Use results[choice][compChoice] instead.
results is an array of arrays. Try accessing via
results[choice][compChoice]
So results[choice] "returns" an array that you can access with another [] operator. As far as I know, multiple indices aren't supported in one pair of brackets.
Thanks everyone.Am glad it was a syntax issue am not me missing the point completely!

returning pointer from function giving me random numbers

I am working on a small console game on my free time and have come across a bug I can't seem to fix no matter what I try. I have tried a lot of different things with the pointers so this is just the latest version of my code. I have been searching around and a few questions other's have asked indicated I may be experiencing a memory leak, or that I am reading values from beyond my arrays (don't understand how). However, those questions have been solved without leaving me any hints as to what is wrong with my code.
Basically, I have a function called int * spendAttribute(int point);
Since anything created in that function is out of scope in my main() I want to take 6 int out of that function, and bring them into my main().
I thought "hey why not use a pointer!" The function is supposed to return a pointer to an array created during the function, and paste it to another pointer created in main(), this has worked once before in my main(), but now it's not working and I have no clue why.
int * spendAttribute(int point)
{
string choice;
int hp,hpT,endur,endurT,dmg,dmgT,armor,armorT,agility,agilityT,evade,evadeT;
while(condition)
{
//do a bunch of junk ....
}
int stats[6] = {hp,endur,dmg,armor,agility,evade};
//some cout testing to see if values are correct (they are)
int* p_stats = new int [6]; //create a block of 6
p_stats = &stats[0]; //point to the first value of stats array
return p_stats; //return pointer
delete [] p_stats; //delete blocks
}
Note: I have tried without deleting the blocks and it still does not work. I tried this since I read that it might be a memory leak.I have tried it without using new at all.
main()
{
//.... some junk
while(main game loop)
{
int * pointer;
cout << "*************** Enter 'begin' to commence ****************** " << endl ;
cout << "*************** Enter 'spend' to use new attribute points ** " << endl ;
cin >> beginChoice; //declared before while loop
if(beginChoice == "spend")
{
cout << "total attributes: " << Bryan.returnAttribute() << endl ;
pointer = spendAttribute(Bryan.returnAttribute()); //copy pointer
cout << "TEST: " << endl ;
cout << pointer[0] << endl ; //out put is a bunch of random numbers..
cout << pointer[1] << endl ;
cout << pointer[2] << endl ;
cout << pointer[3] << endl ;
cout << pointer[4] << endl ;
cout << pointer[5] << endl ; //SOME DAMN BUG HERE
Bryan.addMaxHp(pointer[0]);
Bryan.addEndurance(pointer[0]);
Bryan.addDmg(pointer[0]);
Bryan.addArmor(pointer[0]);
Bryan.addAgility(pointer[0]);
Bryan.addEvasion(pointer[0]);
//after this character ends up having some ridiculous stats like -564553535%
//evasion or 9879967856 armor...
}
}
}
This method of transferring the array over to main worked for me before in this exact file, so I don't know exactly how I am getting these errors or what's causing them. I have even tried deleting the previous pointer used to see if thats what was causing it but it wasn't.
Please Halp.
Because you return a pointer to a local variable, and when that local variable goes out of scope you have a stray pointer.
And no, your allocation doesn't help, as you reassign the pointer to point to the local array, instead of copying into the allocated area. This of course means you also have a memory leak.
Regarding memory leak, you will still have a memory leak even when you fix the above problem. The reason being that you return from the function before you delete[] the pointer, and return returns from the function immediately, all code after a return statement is dead code. That means every time you call the function, it will allocate new memory which will never be free'd.
There are two obvious solutions to both the problems above: One is to allocate memory, copy the array into the allocated memory, and returning the pointer, and in the caller you do delete[] on the pointer.
The second solution is to pass in an array as argument, and use that instead of the local stats array.
p_stats is a pointer to int.
First you assign it to a newly allocated place in memory.
Then you move the pointer to point to local storage and return that. My guess is that you really wanted to return stats. Your options are:
Returns std::vector< int >. Probably simplest.
Modify your function to take a buffer to data and a length and fill it in.
Return std::array if available and you know it will be a fixed size of 6.
Although you could copy the data into p_stats then return that, it is not ideal because the calling function is then responsible to delete the data later.
If the fields have different meanings, you might want to create a struct with meaningful names for the values, and get your function to return that struct. e.g.
struct SpendAttribute // in header
{
int hp;
int endur;
int dmg;
int armor;
int agility:
int evade
};
SpendAttribute spendAttribute( int point )
{
SpendAttribute res;
// enter code here
return res;
}
There is a final option of putting the data into a smart-pointer like boost::shared_array<int> or you can use shared_ptr with an array-deleter.
For now, just return std::vector<int>

C++ Why the parenthesis?

I found this code in a book:
#include <iostream>
using namespace std;
void ChangesAreGood(int *myparam) {
(*myparam) += 10;
cout << "Inside the function:" << endl;
cout << (*myparam) << endl;
}
int main() {
int mynumber = 30;
cout << "Before the function:" << endl;
cout << mynumber << endl;
ChangesAreGood(&mynumber);
cout << "After the function:" << endl;
cout << mynumber << endl;
return 0;
}
It says:
(*myparam) += 10;
What difference would the following produce?
*myparam += 10;
To answer your question:
In your example, there is no difference except in readability.
And, as the comments on this post all suggest, please don't use the parenthesis here...
Interesting other cases
Using a property/method on the dereferenced object
On the other hand, there is a difference if you have something like
*myObject.myPropertyPtr += 10
compared to
(*myPointer).myProperty += 10
The names I chose here tell you what the difference is: the dereference operator * works on whatever is on its right hand side; in the first case the runtime will fetch the contents of myObject.myPropertyPtr, and dereference that, while in the second example it will dereference myPointer, and get myProperty from whatever is found on the object that myPointer points to.
The latter is so common that it even has its own syntax: myPointer->myProperty.
Using the ++ operator rather than +=
Another interesting example, which I thought of after reading another (now deleted) answer to this question, is the difference between these:
*myPointer++
(*myPointer)++
*(myPointer++)
The reason this is more interesting is because since ++ is a call like any other, and particularly doesn't deal with left and right hand side values, it is more ambiguous than your examples with +=. (Of course, they don't always make sense - sometimes you will end up trying to use the ++ operator on an object that doesn't support it - but if we limit our study to ints, this won't be a problem. And it should give you a compiler error anyway...)
Since you caught my curiosity, I conducted a small experiment testing these out. This is what I found out:
*myPointer++ does the same thing as *(myPointer++), i.e. first increment the pointer, then dereference. This shouldn't be so surprising - it is what we'd expect knowing the result of running *myObject.someProperty.
(*myPointer)++ does what you'd expect, i.e. first dereference the pointer, then increment whatever the pointer pointed to (and leave the pointer as is).
Feel free to take a closer look at the code I used to find this out if you want to. Just save it to dereftest.cpp, compile with g++ dereftest.cpp -o dereftest (assuming you have G++ installed) and run with ./dereftest.