c++ use & to create pointer member from objects in array [error] - c++

Hello I am sorry this shouldn't be a hard problem. Im trying to get the pointer to call that objects function in the array. the block id is the key, however i cannot seem to get it running.
blocks* objects[28];
int index = 0;
for (int i = 0; i < 6; i++)
{
for (int j = i + 0; j < 6; j++)
{
objects[index] = new blocks(key, i, j);
key = key + 1; //used to make sure each block can id with a key
index = index + 1;
}
}
for (int i = 0; i < 28; i++)
{
double id = objects[i]->getblockid(); //FIXED
cout << "Object is: " << i << " id is: " << id << endl;
}

Are you saying that your code doesn't compile? It seems fine for me.
Howerver I can see see a few problems at runtime.
First, in inner loop you are instantiating block object 21 times, but you operate on only first 6 elements of this array. So when you are iterating from 0 to 28 in last loop, you will get exception thrown since 7th and further elements are not instantiated. This is because 7th element of this array is not instantiated. It points to some memory location which is just a garbage.
The other problem is that when you overwrite your pointers, you loose information of created objects, this causes memory leaks. Perhaps you should familiarize yourself with smart pointers concept?
Use std::vectors instead of vanila arrays. Alternatively use std::array.
You should also familiarize with concept of iterators.

Related

Storing array's of integers on the heap and accessing them via pointers

I'm hoping someone can shed some light on where I am going wrong with pointers.. I've read countless web pages and tried various things but for some reason my code is returning jibberish (which I'm guessing may be the memory addresses instead of the data within my array). The purpose of the program is to create an array of 100 elements on the heap, pass this array by a pointer to a function (along with two integer variables start and end); a new array will be created on the heap (this comprises of a chunk of the original array using the start and end variables) and the pointer to this array is passed back to the main method so that the new array can be outputted. My problem is not only is the output seeming to be the location not the value, but also it seems 100 values are outputted not 20 as should be expected. I've spent hours trying to figure out where I have gone wrong and just when I think I understand the concept of pointers my faith is destroyed by red squigglies and incorrect outputs. Please HELP! My code is as follows:
#include "stdafx.h"
#include <iostream>
#include <time.h>
using namespace std;
double* getSubArray(double*, int, int);// Declare a function that will get the sub array
int _tmain(int argc, _TCHAR* argv[])
{
const int size = 100;// Declare the size of the array
double* pA;// Declare the variable to hold the pointers to the data in array
double* pB;
int start = 15;
int end = 35;
pA = new double[size];// Create space for the array
srand(clock());// Seed the program to the computers current time so that random gets a different set of random numbers everytime it is run
// Use a for loop to traverse through each element of the array (starting at index 0) placing a number defined by the random function that is no higher than 250
for (int i = 0; i < size; i++)
{
pA[i] = rand()%250;
}
cout << "An Array of 100 numbers is created and stored in the heap, these values are:" << endl;
// Output the Array for the user to see
for (int j = 0; j < size; j++)
{
// Place 10 numbers on each line
if (j % 10 == 0)
{
cout << endl;
}
cout << *(pA + j) << " ";
}
cout << endl << "The program will build a second array using the data between the indexes " << start << " & " << end << endl;
pB = getSubArray(pA, start, end);// Pass the data to the method
// Output second array for user to compare
for (int k = 0; k < size; k++)
{
// Place 10 numbers on each line
if (k % 10 == 0)
{
cout << endl;
}
cout << *(pB + k) << " ";
}
system("pause");
return 0;
}
double* getSubArray(double* pA, int start, int end)
{
double* pB = new double[end-start];// Declare space in the heap for the new array whoes size is the size of the criteria given
for (int i = 0; i < (end - start); i++)
{
for (int j = start; j < end; j++)
{
*(pB + 0) = pA[j];
}
}
return pB;
}
*(pB + 0) = pA[j];
That keeps writing to the first element of the array. Surely you want to write to each element in turn:
for (int i = start; i < end; ++i) {
pB[i-start] = pA[i];
}
or if you don't want to write your own loop
std::copy(pA+start, pA+end, pB);
Don't forget to delete[] everything you new[] or, to save mucking around with low-level memory management, use std::vector to manage the dynamic arrays for you.

vector.push_back

I am writing an application that reads from data files of a given format. In the file, I've dynamically created a 2D array of pointers to vector objects. Basically, it reads through the file, and when it finds a given string pattern, it stops and reads
while(getline(inputFile,tempTestString)){
// first for ACCEL
if(string::npos != tempTestString.find(ACCEL)){
sstream.str(tempTestString);
sstream >> pushBack;
cout << "position 1" << endl;
array[tempDim1][tempDim2].vectorName->push_back(pushBack);
cout << "position 2" << endl;
break;
}
}
now, pushBack is a large number, could be up to 20000, but it varies between files.
The problem with this code is that I'm not getting any run-time errors, or even any exceptions thrown, I tried catching them. The program simply finishes! To be sure, I added the cout << "position1" << endl; and cout << "position2" << endl; lines and the latter prints.
In case you haven't guessed:
tempTestString and ACCEL - string objects
sstream - stringstream object
array - 2D struct array in dynamic memory
vectorName - pointer to vector object, member of struct pointed to by array
ADDENDUM:
So, in response to some comments, here is the other portion of the code, where all the variables were created:
array
array = new structName* [tempDim1];
for(int i = 0; i < tempDim2; i++){
array[i] = new structName [tempDim2];
}
structName
struct structName{
vector<double>* vectorName;
vector<double>* vectorName1;
vector<double>* vectorName2;
};
tempDim1 and tempDim2 are both const ints, of values 2 and 3, respectively. pushBack can have a value of up to 20000
Try to correct this:
array = new structName* [tempDim1];
for(int i = 0; i < tempDim2; i++){
array[i] = new structName [tempDim2];
}
=>
array = new structName* [tempDim1];
for(int i = 0; i < tempDim1; i++){
array[i] = new structName [tempDim2];
}
You're using the wrong number of elements in your initialization.
array = new structName* [tempDim1];
for(int i = 0; i < tempDim2; i++){
array[i] = new structName [tempDim2];
}
i < tempDim2 is wrong; the array has tempDim1 elements.
I don't know if this is the problem, but it is a problem. If tempDim1 > tempDim2 then some elements of array[] are going to be uninitialized. (And if it's the other way around, you're corrupting memory.) The only way this would work is if tempDim1 and tempDim2 are the same by coincidence.

Declaring vectors inside for loop

I have an array of pointers to vectors vector<int> *F[12]; and I wish to initialize some vectors and store their addresses in F.
for(uint i = A; i <= B; ++i){
vector<uint> newvec(pow2(i), 0);
F[i] = &newvec;
}
But when I try to access them later, I find that they are not all zero:
for(uint i = A; i <= B; ++i){
for(uint j = 0; j <= pow2(i); ++j){
if((*F[i]).at(j) != 0){
cout << i << "/" << j << "/" << (*F[i]).at(j) << "|";
}
}
}
I assume this has something to do with the scope of the declared vector. Why has the memory been freed? Do I have to use malloc and create a vector from that?
newvec is being created on the call stack each iteration. Each time through the loop you create it, make a pointer to it, then it vanishes. You want to use the 'new' operator to create a longer-lasting instance of the vector in the heap.
newvec goes out of scope when the loop exits. Any existing reference or pointer to it is invalid at that point. You'll need to declare the object at the appropriate scope (I don't know what that is for you in this case, but certainly outside the for loop).

Segmentation fault and mysterious loop behavior

I am working on a homework assignment with a few specific requirements. There must be a class named TestScores that takes an array of scores as its argument. It throws an exception if any scores are negative or greater than 100. Finally, it must have a member function that returns an average for all the scores. I wasn't clever enough to find a way to only pass the array into the constructor, so I also added in an int that tells the size of the array.
Running the code (I haven't even gotten around to testing the exceptions yet), I keep getting a Segmentation fault error. Valgrind and gdb have been rather unhelpful, outputting messages like:
==9765== Jump to the invalid address stated on the next line
==9765== at 0x2200000017: ???
Even more mysteriously (to me at least), in the for loop in the client code, my incrementor, i, somehow gets bumped from 0 to a seemingly random two-digit number right after creating the TestScores object. In previous versions, before I started using rand() to populate the array, i just never incremented and did the infinite loop thing.
Here's the contents of TestScores.cpp:
#include <iostream>
using std::cout;
using std::endl;
#include "TestScores.h"
#include <stdexcept>
using std::runtime_error;
// Constructor.
TestScores::TestScores(int a[], int s):
_SIZE(s), _scores()
{
// Look at each item in a[], see if any of them are invalid numbers, and
// only if the number is ok do we populate _scores[] with the value.
for (int i = 0; i < _SIZE; ++i)
{
if (a[i] < 0)
{
throw runtime_error ("Negative Score");
}
else if (a[i] > 100)
{
throw runtime_error ("Excessive Score");
}
_scores[i] = a[i];
cout << _scores[i] << " ";
}
cout << endl;
}
// Finds the arithmetic mean of all the scores, using _size as the number of
// scores.
double TestScores::mean()
{
double total = 0;
for (int i = 0; i < _SIZE; ++i)
{
total += _scores[i];
}
return total / _SIZE;
}
// median() creates an array that orderes the test scores by value and then
// locates the middle value.
double TestScores::median()
{
// Copy the array so we can sort it while preserving the original.
int a[_SIZE];
for (int i = 0; i < _SIZE; ++i)
{
a[i] = _scores[i];
}
// Sort the array using selection sort.
for (int i = 0; i < _SIZE; ++i)
{
int min = a[i];
for (int j = i + 1; j < _SIZE; ++j)
{
if (a[j] < min)
{
min = a[j];
a[j] = a[i];
a[i] = min;
}
}
}
// Now that array is ordered, just pick one of the middle values.
return a[_SIZE / 2];
}
And here's the client code:
#include <iostream>
#include "TestScores.h"
#include <stdexcept>
#include <cstdlib>
#include <ctime>
using std::exception;
using std::cout;
using std::endl;
int main()
{
const int NUM_STUDENTS = 20,
NUM_TESTS = 4;
int test [NUM_TESTS][NUM_STUDENTS];
// Make random seed to populate the arrays with data.
unsigned seed = time(0);
srand(seed);
// Populate the scores for the individual tests graded for the semester.
// These will all be values between 0 and 100.
for (int i = 0; i < NUM_TESTS; ++i)
{
for (int j = 0; j < NUM_STUDENTS; ++j)
{
test[i][j] = rand() % 100;
cout << test[i][j] << " ";
}
cout << endl;
}
// Now we have the data, find the mean and median results for each test.
// All values should be valid, but we'll handle exceptions here.
for (int i = 0; i < NUM_TESTS; ++i)
{
cout << "For Test #" << i + 1 << endl;
try
{
cout << "i = " << i << endl; // i = 0 here.
TestScores results(test[i], NUM_STUDENTS);
cout << "i = " << i << endl; // i = some random number here.
cout << "Mean: " << results.mean() << endl;
cout << "Median:" << results.median() << endl << endl;
}
catch (exception &e)
{
cout << "Error, invalid score: " << e.what() << endl;
}
cout << "For Test #" << i + 1 << endl;
}
return 0;
}
Edit:
The header was requested as well:
#ifndef TEST_SCORES_H
#define TEST_SCORES_H
class TestScores
{
private:
const int _SIZE;
int _scores[];
public:
// Constructor
TestScores(int a[], int);
double mean() const,
median() const;
};
#endif
I played around with making the array dynamic, and didn't initialize the array as empty, which fixed my problems, so that's what I ended up turning in. That leads me to a few follow-up questions.
Before going dynamic, I played around with initializing the array, _scores, by trying to give it the size value that was supposed to already be initialized. This led to compiler problems. I talked with my teacher about that, and he said that you can't allocate space for an array unless there's a hardwired global constant. That is, you can't pass a size value in the constructor to initialize an array. Is that true, and if so, why?
Stepping back a bit, it seems to me that dynamic arrays are better if you need a lot of values, because then you don't need a contiguous block of space in memory. So if you are making small arrays, it seems like a waste of space and time typing to make dynamic arrays. Is this untrue? Should I be doing all arrays from now on as dynamic? This experience certainly changed my opinion on the utility of regular arrays, at least as they pertain to classes.
Also, though I got full credit on the assignment, I feel like I violated the spirit by passing an argument for size (since the literal problem statement reads: "The class constructor should accept an array of test scores as its argument"). Aside from a hardwired global constant or having a size argument, is there a way to pass just the array? I swear I spent a good hour trying to think of a way to do this.
It seems you don't initialize _scores at all. You need _scores = new int[s]; at the top of the constructor (and also delete[] s; in the destructor).
Without initializing _scores, you write things to undefined memory locations.
Without TestScores.h one has to guess, but given what you say about the value of i being corrupted in the loop where you're creating the TestScores objects, that points to your _scores member variable not being properly initialized and when you're trying to load it you are actually trashing memory.
Once TestScores.h is visible, I'll revisit this answer taking the file into account.
Updated now that TestScores.h is available.
The problem is that you are not initializing _scores. You are not actually allocating any memory to hold the array, let alone setting the pointer to point to that memory. So when you attempt to store things into the array you're just trashing memory somewhere.
The first line in your constructor should be:
_scores = new int[_SIZE];
That will allocate memory to hold _SIZE ints and set _scores to point to that memory. Then your assignments to _scores[i] will actually go into defined memory belonging to your program.
Of course, you also have to release this memory (C++ won't do it for you) when instances of TestScore get destroyed. So you will need to define and implement a destructor for TestScores and that destructor needs to contain the line:
delete [] _scores;
This will free the block of memory that _scores points to. You can read docs on the delete operation to see why the [] have to be there in this case.

Removing elements from dynamic arrays without changing the index order

I've been trying to erase an element from an array without changing the index order, for instance:
class MyObject
{
int id;
public:
MyObject() { }
void setId( int i ) { id = i; }
void showId() { std::cout << "ID: "<< id << "\n"; }
};
MyObject *myArray;
int main ( )
{
myArray = new myArray[6];
for( int i = 0; i < 6; i++ )
{
myArray[i]->setId(i);
myArray[i]->showId();
}
}
I want to remove myArray[3] without changing the index of the others. e.g:
myArray[0] = ID: 1
myArray[1] = ID: 2
myArray[2] = nothing
myArray[3] = ID: 4
myArray[4] = ID: 5
myArray[5] = ID: 6
I've tried to use use memset(), but it didn't work.
memset(&myArray[3],0,sizeof(MyObject));
There's no such thing as "nothing" in C++ language. Once you have an array, all elements of that array will contain "something". There's no way to make an array element just disappear with keeping all other elements in their original places. You can't create a hole in the array.
All you can do in this case is simply label some element as "deleted" and then later recognize it as such. The element will, of course, continue to exist physically. It is you who'll have to recognize it as "deleted" and ignore it in your further processing. You can either add some bool is_deleted field to your object, or you can use some reserved value of id (like -1) to indicate a deleted element.
In your example with memset you essentially set the id to zero. Is 0 a valid id value? If it is not, then 0 is a good choice to mark a deleted element. In that sense your memset attempt works perfectly fine, as it should. Although I'd recommend doing it by explicitly assigning zero to id, without using memset.
You are calling memset to write a bunch of zeros over the top of an object instance. Do not do this! You may get away with it if your class is a true POD class. You might end up just setting the ID to 0. But maybe there is more to your class that you aren't showing. In anycase, even if it isn't POD, don't use memset like that.
You can either store pointers to object and use the null pointer to indicate there is nothing there. I'd do this with std::vector<MyObject*>. Or you use a sentinel object instance, for example with ID of -1.
The other thing that could be a problem is that you appear to be using 1-based indices. C++ arrays are 0-based, so the first element is myArray[0] and not myArray[1].
Using memset that way is setting all the bytes of that object to 0. This is usually equivalent to setting id to 0, because the memory of an object is the memory of its members (not counting vtables, padding, etc). But don't do that anyway.
One way to do this is to use new and have an array of pointers.
MyObject* myArray[6];
int main ( )
{
for( int i = 0; i < 6; i++ )
{
myArray[i] = new MyObject;
myArray[i]->setId(i);
myArray[i]->showId();
}
}
Then to display them all:
for (int i = 0; i < 6; i++) {
cout << "myArray[" << i << "] = ";
if (myArray[i])
myArray[i]->showId();
else
cout << "nothing" << endl;
}
Then when you want to remove an object, delete it and set its pointer to NULL:
delete myArray
myArray[3] = NULL;
Then when you do anything with one of the objects in myArray, you must check if it is NULL to see if it's a valid object.
Consider boost::optional:
typedef boost::optional<MyObject> MyObjectOpt;
MyObjectOptArr *myArray;
The syntax/usage is a bit different (resembles using pointer):
for (int i = 0; i < 6; ++i) {
if (myArray[i])
cout << "myArray[" << i << "] = " << *(myArray[N]);
else
cout << "nothing" << endl;
}
To unset value do:
myArray[N] = boost::none;