Getting a segmentation error when printing my array of strings - c++

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.

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.

C++ - Value of local non-initialized variables

I was writing a simple program to test how the scope of variables works, but I'm obtaining unexpected results, so I was hoping you could give me an hand to understand them.
I compiled this code
#include<iostream>
using namespace std;
void myFunction1()
{
int e;
cout << e << endl;
e++;
cout << e << endl<<endl;
}
int main()
{
cout << "MAIN" << endl;
int a,b,c,d;
cout << "a= " << a << endl;
cout << "b= " << b << endl;
cout << "c= " << c << endl;
cout << "d= " << d << endl<<endl;
cout << "MY_FUNC" << endl;
myFunction1();
myFunction1();
myFunction1();
}
and obtained this output
MAIN
a= -1617852976
b= 32767
c= 0
d= 0
MY_FUNC
32675
32676
32676
32677
32677
32678
So, there are two things I really don't understand
1) In the main() function I'm creating 4 int variables (a,b,c,d) WITHOUT initializing them, so I expect them to assume a different value each time I run the code. Strange thing is, the first variable (a) is always different, while the others always assume the same values (b=32767, c=d=0)
2) The function output is even stranger to me.
Again, I'm creating a variable e without initializing it, so the first time it assumes a random value (in the example, e=32675).....then, I increase it by one, so that it prints 32675 and 32676, and that sounds right.
But how come the second time I call the function, e keeps the previous value (32676)? I thought e was created each time I call myFunction1() and deleted at the end of the function, so that e assumed a different random value each time (since I don't initialize it). Why is the value of e stored even if the variable goes out of scope?
Uninitialized primitive values are simply not defined. They can have any value.
It is an undefined behavior. That's why it doesn't make any sense to analyze the behavior of this program.
In the main() function I'm creating 4 int variables (a,b,c,d) WITHOUT initializing them, so I expect them to assume a different value each time I run the code
This assumption is flawed. They may have a different value each time you run the code, but they may not. Anything could happen. The point of UB is that you should drop all your assumptions.
But how come the second time I call the function, e keeps the previous value (32676)? I thought e was created each time I call myFunction1() and deleted at the end of the function, so that e assumed a different random value each time (since I don't initialize it)
It does. If you replace "random" for the more correct "arbitrary", then the results you're seeing fit that pattern just fine.
It's just pure luck, and comes down to the state you're leaving unclaimed memory in at each stage of your program's execution.
A good way to help you understand this is to explain in terms of memory allocation.
When you run a program, a certain amount of memory that is not used is assigned to your variable.
Computers are lazy, the best way to delete a data is to forget where it is stored. When you assign a chunk of memory to a variable, you are telling the computer to remember where that certain data belongs to.
If it so happens that it was used prior to you assigning the memory to the variable, it will simply read (let's say 4 bytes for a common machine) and get the data from that location.
Hope that this helps =)

Subscript operator overloading to access a private array

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;

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>

What does a double parenthesis in a function call do?

I'm using dlib.
I came across the following in one of the example programs:
cout << "p(D=0) = " << solution.probability(D)(0) << endl;
I've never seen a double parenthesis after a function call in C++. What does it do and how does it work?
What does solution.probability(D) return. If it's a functional object, or a pointer to a function, you can call it, which is probably what the second set of parentheses do.