I am working on assignment to create a container class for a dynamic array of strings. I know that it would be much easier/better done with std::vector, but that is not the point. I am having a problem finding the right way to initialize my array in the constructor. The way it is below, I am still being warned by the compiler that the variable lineArray is not used. The program compiles with a warning that lineArray is unused then hangs at runtime.
MyBag::MyBag()
{
nLines = 0;
std::string lineArray = new std::string[0] ();
}
void MyBag::ResizeArray(int newLength)
{
std::string *newArray = new std::string[newLength];
//create new array with new length
for (int nIndex=0; nIndex < nLines; nIndex++)
{
newArray[nIndex] = lineArray[nIndex];
//copy the old array into the new array
}
delete[] lineArray; //delete the old array
lineArray = newArray; //point the old array to the new array
nLines = newLength; //set new array size
}
void MyBag::add(std::string line)
{
ResizeArray(nLines+1); //add one to the array size
lineArray[nLines] = line; //add the new line to the now extended array
nLines++;
}
http://ideone.com/pxX18m
You are using a local variable called lineArray in your constructor. You want to use your data member, for example:
MyBag::MyBag()
{
nLines = 0;
lineArray = new std::string[0] ();
}
In addition to the obvious error reported by compiler (i.e. initializing a local variable rather than assigning to an instance variable) you have a more serious issue: if a value smaller than nLines is passed to ResizeArray, your code would exhibit undefined behavior by writing data past the end of the allocated region. You need to change the code as follows:
void MyBag::ResizeArray(int newLength)
{
// Add a trivial optimization:
if (newLength == nLines) {
// No need to resize - the desired size is already set
return;
}
std::string *newArray = new std::string[newLength];
//create new array with new length
for (int nIndex=0; nIndex < nLines && nIndex < newLength ; nIndex++)
{ // ^^^^^^^^^^^^^^^^^^^^^
newArray[nIndex] = lineArray[nIndex];
//copy the old array into the new array
}
delete[] lineArray; //delete the old array
lineArray = newArray; //point the old array to the new array
nLines = newLength; //set new array size
}
Warning to the rescue. Good thing that you had compiler warnings otherwise this would have been a bug which will have taken longer to figure out.
std::string lineArray = new std::string[0] ();
^^^^^^^^^^^
is declaring a new variable called lineArray with in the constructor. You are not using the class member one. The member lineArray pointer will still be pointing to some uninitialized memory.
It should be
lineArray = new std::string[0] ();
In addition to the shadowed member variable, and the ResizeArray to smaller array issue, there is a bug in your add() method, as indicated by 6602. After your call to ResizeArray, nLines has already been updated to the new value, so you are actually writing to the wrong array position, and then wrongly incrementing nLines again. Make sure to write to the correct position, and there is no need to increment.
void MyBag::add(std::string line)
{
int oldLength = nLines;
ResizeArray(nLines+1); //add one to the array size
lineArray[oldLength] = line; //add the new line to the now extended array
}
Related
i'm working on this personal project and i'm a bit confused on how the remove() function works.
header:
class IntSet {
public:
IntSet(); //Constructor
~IntSet(); //Destructor
int size() ; //
bool isEmpty();
bool contains(int number1);
void add(int number2);
void remove(int number2);
private:
int* ptr; //pointer to the array
int sizeOfArray; //current size of the array
int currentValue; //number of values currently in IntSet
};
main (only including add() part)
#include "IntSet.hpp"
#include <iostream>
IntSet::IntSet(){
sizeOfArray = 10;
currentValue = 0;
ptr = new int[10];
}
IntSet::~IntSet(){
delete[] ptr;
}
//returning the number of values in the IntSet
int IntSet::size()
{
return currentValue;
}
//Determining whether the stack is empty
bool IntSet::isEmpty()
{
if (currentValue == 0)
return true;
else
return false;
}
//defining contains() function
bool IntSet::contains(int number1)
{
for (int i = 0; i < currentValue; i++)
{
if (ptr[i] == number1)
return true;
}
return false;
}
//defining add() function
void IntSet::add(int number2)
{
if (currentValue == sizeOfArray)
{
sizeOfArray = sizeOfArray * 2; //doubling size of arrayCapacity
int* temp = new int[sizeOfArray]; //allocating new one that's twice as large
for (int i = 0; i < currentValue; i++)
{
temp[i] = ptr[i]; //copying old stuff into new one
}
delete[] ptr; //deallocate old array
ptr = temp; //set ptr to new array
}
}
//defining remove() function goes here
So for the add() function I had to take an int parameter add it to the array. When it gets full I have to double the size of the array, copy the contents of the old array into the new one, redirect the data member pointer to the new array and then deallocate the array.
For the remove() function I have to just take an int parameter and remove it from the IntSet by shifting over all the subsequent elements of the array. Should I just use parts of my add function and pretty much tell it to do the opposite for my remove() function? If not, how do I even begin to write the remove() function? I'll show the rest of my code if needed. Thank you guys so much!
Give this a try for removing:
void IntSet::remove(int number2)
{
bool bIntRemoved = false;
for(int i=0; i < currentValue; i++){
// check if we are currently searching or shifting
if(!bIntRemoved){
// still searching
// check if we should remove int at current index
if(ptr[i] == number2){
// found the int to remove
// We'll decrement i and set bIntRemoved = to true
// So the else-if code handles shifting over the array
i--;
bIntRemoved = true;
}
}else if(i < currentValue-1){
// We have spots to shift
// Check if this is the last index
ptr[i] = ptr[i+1];
} // else, we are at the last index and we have nothing to shift
}
if(bIntRemoved){
// The int was successfully located and any necessary shifting has been
// executed. Just decrement currentValue so the current last index will be
// disregarded.
currentValue--;
} // else, the int to remove could not be located
}
I haven't tested, but in theory, this should locate the first instance of the int you need to remove, shift all values left by one spot (unless the int to remove is in the last index of the array), and then decrement the currentValue variable so the previous last index of the array is disregarded and can be overwritten. Anyway, sorry if that's a poor explanation, but it's not the easiest concept to explain. I attempted to document the code fairly well, so hopefully that will make sense :P Let me know if you have any questions and let me know if this works or doesn't work for you (I find feedback to be very important.)
EDIT: Also, I intended to mention this, but I forgot, so thank you, #Viet, for mentioning this in your answer, your add() function does not seem to handle cases when the currentValue is less than the size of the array. I assume you are already handling that and you just omitted the else statement that takes care of it?
EDIT #2:
The following is code to properly handle adding new elements to the array:
void IntSet::add(int number2){
if (currentValue == sizeOfArray)
{
sizeOfArray = sizeOfArray * 2; //doubling size of arrayCapacity
// nothrow is used below to allow for graceful error handling if there is not enough
// ram to create the new array
int* temp = new (nothrow) int[sizeOfArray]; //allocating new one that's twice as large
// check if new int array could be create
if(temp == nullptr){
// new int array could not be created
/** Possibly set an error flag here or in some way warn the calling function that
the function failed to allocate the necessary memory space.
I'll leave that up to you, OP. **/
// Right now we'll just return without modifying the existing array at all
return;
}
for (int i = 0; i < currentValue; i++)
{
temp[i] = ptr[i]; //copying old stuff into new one
}
delete[] ptr; //deallocate old array
ptr = temp; //set ptr to new array
// Now we'll just let the code below add the number to the array
} // else we have enough space to add the number to the array
ptr[currentValue] = number2;
currentValue++;
}
Again, I have not tested this code, but let me know if it works or does not work for you. Also, I modified the line that makes a new array (int *temp = new int[sizeOfArray];) to now handle errors if memory cannot successfully be allocated. To do this I am using the (nothrow) object (more on that on this CPlusPlus page). If allocation fails, a temp is set to a null pointer. Without this, the method would instead throw a bad_alloc exception or the program would terminate. That's not very graceful, so I prefer properly handling the error (and handling it in a way that is less strenuous on the calling function). To use this, you will need to include the <new> header (which is where nothrow is defined).
Is your class is a set or a list? If your class is a set, it mean there are no same numbers in your class
Example: a set {1, 2, 3}, a list: {1, 2, 3, 1, 3, 2}
About your add function, i have some comments:
You does not check new element exist in your set
You does not increase current size and set value for new element in your set
You can use memcpy function to copy old data to new data pointer
About remove function, i have some ideas:
At first, you must find the position of number which need to be delete in current set
After that, you remove that number by shift left all member from next position of number which need to be delete to the left position. And you must decrease current size by 1
Example: you have a set {1, 2, 3, 4}, current size is 4. And you want to remove a number "2"
First, you find the position of 2 in your set. It is 1 (because the start index of array is start from 0)
Second, you remove it by pushing back all the values from next position on the front of its in your set.
Ex: the value of position 1 replaced by value 3, the value of position 2 replaced by value 4
Finally, you decrease current size by 1. Now, current size is 3, and you have a new set {1, 3, 4}
I want to resize the array when the rehash function is called, by copying the values of initial dictionary into it and then at last redifining the newdictionary as dictionary
void rehash ()
{
int newsize=2*Size;
node **newdictionary;
newdictionary= new node*[newsize];
//Initialising the dictionary
for (int i = 0;i < newsize;i++)
{
newdictionary[i]->name = "";
newdictionary[i]->value = -1;
}
node **temp=dictionary;
delete [] dictionary;
dictionary=newdictionary;
SIZE=newsize;
for(int i=0;i<SIZE;i++)
{
if(temp[i]->value!= -1)
insertvalue(temp[i]->name,temp[i]->value);
}
delete [] temp;
};
Earlier I have defined insertvalue as:
void insertvalue (string filedata, int code)
{
// tableindex is the position where I want to insert the value
dictionary[tableindex]->name= filedata;
dictionary[tableindex]->value=code;
};
You didn't actually explain what problem(s) you're having, but your code has several issues:
void rehash ()
{
int newsize=2*Size;
node **newdictionary;
newdictionary= new node*[newsize];
At this point, newdictionary is simply an array of uninitialized pointers.
//Initialising the dictionary
for (int i = 0;i < newsize;i++)
{
newdictionary[i]->name = "";
newdictionary[i]->value = -1;
}
So the loop above is trying to access the members of node objects that don't yet exist.
node **temp=dictionary;
delete [] dictionary;
These two lines don't make sense. dictionary and temp point to the same memory. So when you delete dictinoary you've deleted the memory that temp is pointing to.
dictionary=newdictionary;
SIZE=newsize;
for(int i=0;i<SIZE;i++)
{
if(temp[i]->value!= -1)
insertvalue(temp[i]->name,temp[i]->value);
}
Even if you hadn't just deleted the memory out from under temp, you're now trying to access temp from 0 to the new size, not the old size. In other words, this would access temp beyond its bounds.
Those are the major problems that I've noticed in the code so far. You at least need to correct all of them before there's any hope of this working. You probably need to spend some time really stepping through your logic to ensure it makes sense in the end.
I'm trying to implement an unbounded array: What is an unbounded array?
More details on this page:
http://www.cs.cmu.edu/~fp/courses/15122-s11/lectures/12-ubarrays.pdf
This is the code:
#include <iostream>
#include <cstdlib>
using namespace std;
class UBArray
{
public:
int *arr, *arrN, j, *pos; //Initial array is arr. The position of arr is stored in pos. arrN is the new array created when size = limit.
int size, limit; //size is the current size of the array and limit is the total size available untill a new array is created.
UBArray()
{
size = 0;
limit = 10;
arr = new int[10];
pos = arr;
}
private:
void increment()
{
// New array arrN is created and then the values in the old arrays is put into the new array.
// Limit is increased by 10 - this is the extra space the new array contributres.
// pos which carries the address of the current array now carries the address of the new array.
// Later when a new array is created its address will be on the heap which is empty. This address is replace the address stored
// in the arrN. The older array can still be accessed for the array updation process by using the variable pos.
// IMPORTANT: I had initially tried to delete the older array to space space but while trying to debug the segmentation fault, I have
// removed it. I will be adding it again once the error has been fixed.
arrN = new int[size + 10];
for (j = 0; j < size; j++)
{
arrN[j] = pos[j];
}
limit = limit + 10;
pos = arrN;
}
public:
void push(int n)
{
if (size<limit)
{
size++;
pos[size-1]=n;
}
else
{
increment();
push(n);
}
}
int pop()
{
int p = pos[size-1];
size--;
return p;
}
};
int main()
{
UBArray array;
int num;
cout << "Enter 36 elements: ";
for (int k = 0; k<36; k++)
{
cin >> num;
array.push(num);
}
cout << endl << "The last element is : " << array.pop();
}
I have tried to give comments in the code to make it understandable to the reader. I'm copying some of it here:
Initial array is arr. The position of arr is stored in pos. arrN is the new array created when size = limit.
size is the current size of the array and limit is the total size available until a new array is created.
New array arrN is created and then the values in the old array are put into the new array.
Limit is increased by 10 - this is the extra space the new array contributres.
pos which carries the address of the current array now carries the address of the new array.
Later when a new array is created its address will be on the heap which is empty. This address is replaced the address of arrN. The older array can still be accessed for the array updation process by using the variable pos which will be updated by the old values have been copied to the new one.
I get segmentation fault during execution. I have tried to use cout statements to debug the code but it seems really confusing. I could see loops both inside and outside the for loop inside the increment method. I'm unable to figure out much. Any help is appreciated.
UPDATE: As pointed out by jrok, I changed the code and the seg fault is gone. But I'm getting seg fault again at the creation of the 3rd array.
UPDATE 2 Everything fixed now. Thank you.
arr = new int(10*sizeof(int));
That creates a single int, initialized to the value of 10*sizeof(int). The loop you wrote right after this statement runs out of bounds and it's cause of segmentation fault.
What you want is the array form of new:
arr = new int[10]; // note 10 only, new expression knows the size
// of the type it allocates
Note that when you assign the pointer to the new array to the pointer to the old array you lose the handle to it and create a memory leak:
int* arr = new int[10];
int* new_arr = new int[20];
arr = new_arr; // original array at arr has leaked
You need to delete[] arr before you reassign it. Also, I see no use for the third (pos) pointer. Not even for arrN, for that matter. One will do. Create a local pointer inside increment and assign it to arr when you're done deallocating the old array.
Finally, what people have been telling you in the comments, unless this is a learning exercise, don't try to reinvent the wheel and use std::vector instead.
An unbounded array only needs 3 data members (rather than 6): the address of the beginning of the data buffer, the capacity of the buffer, and the actual size (of the part of the buffer used so far). When expanding, you will temporarily need to hold the address of the new buffer in an automatic variable. Also, you should avoid leaking the memory of previous buffers. A simple layout is like this:
struct ua
{
int size,capacity,*buff; // 3 data members only
ua(int n) // constructor: n = initial capacity
: size(0) // initially empty
, capacity(n<0?0:n) // guard against n<0
, buff(capacity?new int[capacity]:0) {} // only allocate if n>0
~ua() { delete[] buff; } // destructor: note: delete[] 0 is ok
void empty() const { return size==0; } // is array empty?
void push(int x) // add another datum at back
{
if(size==capacity) { // buffer is full: we must expand
if(capacity) capacity+=capacity; // double capacity
else capacity=1; // but ensure capacity>0
int*nbuff=new int[capacity]; // obtain new buffer
if(size)
memcpy(nbuff,buff,size*sizeof(int)); // copy data from old to new buffer
delete[] buff; // free memory form old buffer
buff=nbuff; // set member buff to new buffer
}
buff[size++]=x; // write; increment size (post-fix)
}
int pop() // ill-defined if empty()
{ return buff[--size]; } // read; decrement size (pre-fix)
int operator[](int i) const // ill-defined if i<0 or i>=size
{ return buff[i]; }
int&operator[](int i) // ill-defined if i<0 or i>=size
{ return buff[i]; }
// you may add more functionality, for example:
void shrink(); // reduces capacity to size
void reserve(int n); // extends capacity to n, keeping data
ua(ua const&other); // copy buffered data of other
void swap(ua&other); // swap contents with other (no copying!)
};
I have an array which might contain empty/null positions (e.g: array[2]=3, array[4]=empty/unassigned). I want to check in a loop whether the array position is null.
array[4]==NULL //this doesn't work
I'm pretty new to C++.
Thanks.
Edit: Here's more code;
A header file contains the following declaration
int y[50];
The population of the array is done in another class,
geoGraph.y[x] = nums[x];
The array should be checked for null in the following code;
int x=0;
for(int i=0; i<sizeof(y);i++){
//check for null
p[i].SetPoint(Recto.Height()-x,y[i]);
if(i>0){
dc.MoveTo(p[i-1]);
dc.LineTo(p[i]);
}
x+=50;
}
If your array is not initialized then it contains randoms values and cannot be checked !
To initialize your array with 0 values:
int array[5] = {0};
Then you can check if the value is 0:
array[4] == 0;
When you compare to NULL, it compares to 0 as the NULL is defined as integer value 0 or 0L.
If you have an array of pointers, better use the nullptr value to check:
char* array[5] = {nullptr}; // we defined an array of char*, initialized to nullptr
if (array[4] == nullptr)
// do something
You can use boost::optional (or std::optional since C++17), which was developed in particular for decision of your problem:
boost::optional<int> y[50];
....
geoGraph.y[x] = nums[x];
....
const size_t size_y = sizeof(y)/sizeof(y[0]); //!!!! correct size of y!!!!
for(int i=0; i<size_y;i++){
if(y[i]) { //check for null
p[i].SetPoint(Recto.Height()-x,*y[i]);
....
}
}
P.S. Do not use C-type array -> use std::array or std::vector.
std::array<int, 50> y; //not int y[50] !!!
If the array contains integers, the value cannot be NULL. NULL can be used if the array contains pointers.
SomeClass* myArray[2];
myArray[0] = new SomeClass();
myArray[1] = NULL;
if (myArray[0] != NULL) { // this will be executed }
if (myArray[1] != NULL) { // this will NOT be executed }
As http://en.cppreference.com/w/cpp/types/NULL states, NULL is a null pointer constant!
There is no bound checking in array in C programming. If you declare array as
int arr[50];
Then you can even write as
arr[51] = 10;
The compiler would not throw an error. Hope this answers your question.
I have a function whose signature is as follows:
GetCustomers( wchar_t** Name,int *count);
In main method: Call to customer looks like this:
GetCustomers( Name,&count);
The body of the function is as follows: (since count of customers is unknown , I am trying to allocate meomry dynamically)
GetCustomers( wchar_t** Name,int *count)
{
//Logic to get customer count : Stored in int myCustomersCount
Names = new wchar_t*[myCustomersCount];
for (int i=0; i < myCustomersCount; i++ )
{
Names[i] = new wchar_t;
}
//Logic to get customer names in wchar_t* strName = "Name1";
Names[0] = strName;
*count = myCustomersCount;
}
I would think that this implementation would allow array Name to be passed back correctly to the Main() function with memory allocation on heap but it seems not to work. What is wrong here? myCustomersCount seems to be correct in caller.
PS: The code compile and executes but array received in Main is garbage.
You seem to be thinking in terms of C, not really C++. I'd use something like:
std::vector<std::string> GetCustomers();
or (probably preferred):
template <class outIt>
void GetCustomers(outIt output_iterator);
The latter you'd use something like:
std::vector<std::wstring> customers;
GetCustomers(std::back_inserter(customers));
The third obvious possibility would be to just equip your customers class with a begin() and end() member functions that return iterators to the customers data.
Edit2: Here's some tested demo code:
#include <stdio.h>
#include <string.h>
#include <wchar.h>
void GetCustomers(wchar_t ***names, int *count) {
static wchar_t *myCustomers[] = {
L"You",
L"Him",
L"Her"
};
int myCustomersCount = 3;
wchar_t **temp = new wchar_t *[myCustomersCount];
*count = myCustomersCount;
for (int i=0; i<myCustomersCount; i++) {
temp[i] = new wchar_t[wcslen(myCustomers[i])+1];
wcscpy(temp[i], myCustomers[i]);
}
*names = temp;
}
int main() {
wchar_t **customers;
int count;
GetCustomers(&customers, &count);
for (int i=0; i<count; i++)
printf("%S\n", customers[i]);
return 0;
}
I'm really not sure what you're trying to do here; from what I understand about your code; you're trying to store some strings into an array of an array of character pointers.
GetCustomers(wchar_t **Name, int *count) {
Name = new wchar_t*[myCustomersCount];
for(int i = 0; i < myCustomersCount; i++) {
/* Get your customer name and store into strName */
Name[i] = strName;
}
*count = myCustomersCount;
}
In main, presumably you've got something like this
wchar_t *Name = NULL;
and then you say
GetCustomers( Name,&count);
This passes Name by value, but you want to pass it by reference:
GetCustomers( &Name,&count);
And presumably it's just a typo, but your parameter name is Name (singular) but you refer to it as Names (plural) in the function:
GetCustomers( wchar_t** Name,int *count)
{
//Logic to get customer count : Stored in int myCustomersCount
Names = new wchar_t*[myCustomersCount];
In any case, you want to assign to where Name is pointing, not to itself:
*Names = new wchar_t*[myCustomersCount];
Then for each element in Names you allocate one character, but then overwrite the first one with strName. The allocation is unnecessary (and in fact is a memory leak), and you should assign from strName to each element within the loop, as Suroot's answer does.
2 definite issue and 1 potential issue with your code. The main issue causing your problem first: Name itself is passed by value. That means when you you assign to it in the very first line of your function when you new the memory, you're assigning to the copy, not the original! You have three options: 1) keep the double pointer, make the caller responsible for allocating the memory, and add a third parameter for number of names that the array can hold (recommended) or 2) make Name a triple pointer (wchar_t*** Name) and then you can assign to it by dereferencing it: *Name = new wchar_t*[myCustomersCount]; or 3) just return the wchar_t** since you don't use the passed value for anything.
Then another definite issue: when you allocate memory for each name, you need to use the new[] operator there as well because otherwise you're only allocating room for a single wchar_t.
Finally, the potential issue. You don't show how exactly this code is getting each customer name. But if strName points to memory that is getting reused for each customer name as you put them all in your array, you're going to have to wstrcpy each name into the array. If it doesn't, then you don't need to allocate memory for each Names[i] as you can just store the result right into Names[i].
A final note: just from looking at this code it seems like you're going to have lots of problems with memory management as it seems very unclear who is responsible for allocating and deallocating memory which is likely going to lead to memory leaks. Try your best to keep the responsibility for allocating and deallocating the memory in the same location and you'll reduce lots of potential headaches -- have callers allocate the memory before they call the function and have the caller deallocate the memory when they're done with it.
/* changed */
wchar_t** GetCustomers( int *count)
{
//Logic to get customer count : Stored in int myCustomersCount
wchar_t **Names = new wchar_t*[myCustomersCount];
for (int i=0; i < myCustomersCount; i++ )
{
/* changed */
Names[i] = new wchar_t[MAX_NAME_SIZE];
}
//Logic to get customer names in wchar_t* strName = "Name1";
Names[0] = strName; /* possible wstrcpy needed here? */
*count = myCustomersCount;
/* changed */
return Names;
}
Edit
If you really absolutely can't change the function signature, the only solution I can think of is to flatten your array and use C memory functions (you could also just use a long series of news and deletes, but why not use realloc when this is what it's made for and you're managing memory without using other C++ features like the STL anyways?):
GetCustomers( wchar_t **Names, int *count)
{
//Logic to get customer count : Stored in int myCustomersCount
size_t names_size = 0;
for (int i=0; i < myCustomersCount; i++ )
{
strName = ???; // whatever you use to get the next name
size_t old_names_size = names_size;
names_size += (wstrlen(strName) + 1) * sizeof(wchar_t); //+1 for NULL
*Names = realloc(*Names, names_size);
if (!*Names) {
// Memory allocation failed, log it, abort, do whatever
}
wstrcpy(Names[old_names_size], strName);
}
*count = myCustomersCount;
}
Note that this assumes that Name has already been initialized and points to memory where you can store a wchar_t*, just like the original version assumed count has been initialized and points to memory where you can store an int.
I thought I'd make a fresh start in a new answer.
Here's a simple program that does what I think you're trying to do, with the constraint that the signature of GetCustomers must not be altered.
void GetCustomers(wchar_t** Names,int *count)
{
// Allocate the array of names
wchar_t **ar = new wchar_t*[3];
// Allocate space for each name in the array
ar[0] = new wchar_t[10];
ar[1] = new wchar_t[10];
ar[2] = new wchar_t[10];
// Fill in the names
wcscpy(ar[0],L"joe");
wcscpy(ar[1],L"jim");
wcscpy(ar[2],L"bob");
// Return the array through the bad GetCustomers signature
*Names = (wchar_t*)ar;
*count = 3;
}
int wmain(int argc, wchar_t* argv[])
{
// names is an array of strings
wchar_t **names = NULL;
int count;
// Squeeze names into the dodgy GetCustomers signature
GetCustomers((wchar_t**)&names,&count);
// Delete each name
for(size_t x = 0; x < count; ++x)
delete[] names[x];
// Delete the array
delete[] names;
return 0;
}
Note that I've matched the cast inside the function with another one in main. This way we keep everything as it should be, except for that pesky GetCustomers signature.
Does this help?