The problem occurs in my ToDoList.cpp class file.
ToDoList.cpp:
ToDoList::ToDoList() {
arraySize = 3;
arrayData = 0;
array = new string(arraySize); //error here
}
ToDoList::ToDoList() {
array = new string(todolist.arraySize); //and error here
arraySize = todolist.arraySize;
arrayData = todolist.arraySize;
}
ToDoList.h:
class ToDoList {
public:
ToDoList();
ToDoList(const ToDoList&);
~ToDoList();
void AddItem(string item);
void ListItems();
private:
string* array;
int arraySize;
int arrayData;
};
If you want an array of strings, use
array = new string[arraySize];
You should use
array = new string[arraySize];
and
array = new string[todolist.arraySize];
In your example, you are trying to create an object of std::string class(string(arrraySize)) which is not valid. Compiler is giving the appropriate error to understand it.
EDIT
Your class may be written using std::vector which is efficient correct and easy to understand code.
class ToDoList {
public:
ToDoList() {};
~ToDoList() {};
void AddItem(std::string& item);
void ListItems();
private:
std::vector<std::string> array;
};
void ToDoList::AddItem(std::string& item) {
array.push_back(item);
}
void ToDoList::ListItems() {
for(size_t i = 0; i<array.size(); i++) {
std::cout<<array[i]<<std::endl;
}
}
There's no std::string constructor with just a length. If you want to initialise a string with something in it, you need to say what characters to use. You could use new string(arraySize, fillCharacter), but given this usage, maybe std::vector may be more appropriate.
Edit: the extra details shows you are trying to do something different. So see the other answers. However it looks like you are trying to re-invent a vector<string> , so you may find it easier to use a std::vector instead of manually allocating your array of strings.
Related
I have a class and another class with class member of 2d array from the first class type.
and I need a function that returns that class member.
class Piece
{
// something is implemented here/
};
class Board
{
private:
Piece* _pieces[8][8];
public:
Piece*** getPieces()
{
return _pieces;
}
}
but that's not working.
This is a quick version of your class I made to allow the passing of the 2d array to work.
class Board
{
private:
Piece ** _pieces = new Piece*[8];
public:
Board()
{
for(int i = 0; i<8; i++)
_pieces[i] = new Piece[8];
}
Piece** getPieces()
{
return _pieces;
}
~Board()
{
for(int i = 0; i<8; i++) delete [] _pieces[i];
delete [] _pieces;
}
};
You could std::array to create 2D array of pointers if you have access to C++11/14/17, it's a lot cleaner and expressive than using the build in array that decay to a ptr.
What follows is an example of how you create and return from Booard a 8x8 2D array of pointers to Pieces.
#include <array>
class Piece
{
// something is implemented here/
};
using Pieces=std::array<std::array<Piece*,8>,8>;
class Board
{
private:
Pieces _pieces;
public:
const Pieces& getPieces()
{
return _pieces;
}
};
As suggested by #Galik in comment, you should use std::arrays here, because the sizes are constant expressions.
It is not really mandated by the standard, but for common implementations, a std::array<std::array<T,i>,j> does have a true T[i][j] 2D array as underlying data - said differently, consecutive rows use adjacent memory. std::vector on another hand acts more as an array of pointers and data of consecutive rows are generally not adjacent in memory.
Code could become:
class Board
{
private:
std::array<std::array<Piece*, 8>, 8> _pieces;
public:
std::array<std::array<Piece*, 8>, 8>& getPieces()
{
return _pieces;
}
}
But this is still poor design, because it unnecessarily exposes the underlying implementation, so you really should think twice on what should be the public methods for the Board class.
for example,
int a[3][6];
int **p=a; // it's wrong
You should use pointer like this:
int (*p)[6];
p=a;
I have really been struggling with a piece of code for a couple days. The error message i receive when i run my code is:
error: array initializer must be an initializer list
accountStore (int size = 0) : accts(size) { }
There seem to be others with similar problems here but unfortunately I am unable to apply their solutions (either don't work or not applicable).
What I am simply attempting to do is create a container class (array, can't use vectors) of a class 'prepaidAccount' but I am just unable to get the constructor portion of the container class 'storeAccount' to work. See code snippet below:
class prepaidAccount{
public:
//prepaidAccount ();
prepaidAccount(string newPhoneNum, float newAvailBal) : phoneNumber(newPhoneNum), availableBalance (newAvailBal){} //constructor
double addBalance(double howMuch) {
availableBalance = howMuch + availableBalance;
return availableBalance;
}
double payForCall(int callDuration, double tariff) {
callDuration = callDuration/60; //convert to minutes
double costOfCall = callDuration * tariff;
if (costOfCall > availableBalance) {
return -1;
}
else {
availableBalance = availableBalance - costOfCall;
return costOfCall;
}
}
void setAvailBal(int newAvailBal) {availableBalance = newAvailBal;}
float getAvailBal() {return availableBalance;}
void setPhoneNum(string newPhoneNum) {phoneNumber = newPhoneNum;}
string getPhoneNum() const {return phoneNumber;}
private:
string phoneNumber;
float availableBalance;
};
class accountStore { //made to store 100 prepaid accounts
public:
accountStore (int size = 0) : accts(size) { }
....
private:
prepaidAccount accts[100];
}
In main I simply call accountStore Account;
Any help is absolutely welcome. I very recently started learning c++ and about classes and constructors so please bear with me.
Thanks
You can't initialize an array with int like accountStore (int size = 0) : accts(size) {}.
prepaidAccount doesn't have a default constructor, you have to write member initialization list like,
accountStore (int size = 0) : accts{prepaidAccount(...), prepaidAccount(...), ...} { }
The array has 100 elements, it's not a practical solution here.
As a suggestion, think about std::vector, which has a constructor constructing with the spicified count of elements with specified value. Such as,
class accountStore {
public:
accountStore (int size = 0) : accts(size, prepaidAccount(...)) { }
....
private:
std::vector<prepaidAccount> accts;
};
Given that you have specified that you do not want to use a container such as std::vector but would like to specify the size at runtime, your only option would be to manually implement dynamic allocation yourself. Also given that you are wanting create 100 objects at a time, I would suggest making a function that can construct a temporary object according to your needs and then use this to initialise your dynamically allocated array. Consider the below code as a good starting point. (WARNING untested code.)
class prepaidAccount {
public:
// Constructor
prepaidAccount(string newPhoneNum, float newAvailBal)
: phoneNumber(newPhoneNum), availableBalance(newAvailBal) {}
// Default Constructor needed for dynamic allocation.
prepaidAccount() {}
/* your code*/
};
// Used to construct a tempoary prepaid account for copying to the array.
// Could use whatever constructor you see fit.
prepaidAccount MakePrepaidAccount(/*some parameters*/) {
/* Some code to generate account */
return some_var;
}
class accountStore {
public:
// Explicit constructor to avoid implicit type-casts.
explicit accountStore(const int &size = 0)
: accts(new prepaidAccount[size]) {
for (int i = 0; i < size; i++) {
// Will call defualt assignment function.
prepaidAccount[i] = MakePrepaidAccount(/*some parameters*/);
}
}
// Destructor
~accountStore() {
// Cleans up dynamically allocated memory.
delete[] prepaidAccount;
}
prepaidAccount *accts;
};
Edit: Amongst the c++ community it is often questionable when choosing to use dynamic allocation when there is such an excellent and comprehensive library of smart pointers. For example an std::vector would be perfect in this situation.
I encountered an issue that I have been trying to solve for some time, and simply couldn't do it. Here is the scenario:
1) I have an Template array class that look something like this
//code taken from http://www.learncpp.com, much appreciation for Alex
#ifndef ARRAY_H
#define ARRAY_H
#include <assert.h> // for assert()
template <typename T>
class Array {
private:
int m_nLength;
T *m_ptData;
public:
Array() {
m_nLength = 0;
m_ptData = 0;
}
Array(int nLength) {
m_ptData= new T[nLength];
m_nLength = nLength;
}
~Array() {
delete[] m_ptData;
}
void Erase() {
delete[] m_ptData;
m_ptData= 0;
m_nLength = 0;
}
T& operator[](int nIndex) {
assert(nIndex >= 0 && nIndex < m_nLength);
return m_ptData[nIndex];
}
int GetLength() { return m_nLength; }
friend ostream& operator<<(ostream& out, const Array<T>& n) {
for(int i=0; i<n.m_nLength; i++) {
if(i) it << "\n";
it << n[i];
}
return it;
}
};
#endif
2) And this is the class I tried making array of and how I did it (it has dynamic memory allocation)
class Tune {
char* artist;
char* song;
public:
explicit Tune(const char* a, const char* s) {
artist = new char [strlen(a)+1]; strcpy(artist, a);
song = new char [strlen(s)+1]; strcpy(song, s);
}
...
#include "Array.h"
void main() {
Array<Tune> tunes(5); //Array of 5 elements
}
error C2512: 'Tune' : no appropriate default constructor available
1> c:\x\x\x\visual studio 2010\projects\x\x\array.h(26) : while
compiling class template member function 'Array<T>::Array(int)'
1> with
1> [
1> T=Tune
1> ]
1> c:\x\x\x\visual studio 2010\projects\x\x\main.cpp(10) : see reference to
class template instantiation 'Array<T>' being compiled
1> with
1> [
1> T=Tune
1> ]
3) Then I remembered that I could solve that issue with something like this (without using my array template class):
void main() {
Tune **tunes = new Tune*[5];
...
}
I would like to know is this the solution and how do I create Array of pointers using my template array class, and second (lest say I have overriden operator<<), how to I print one or all of the elements of the array.
The full program is huge, this is the piece of it. Most of the code is under comments, so the issue is isolated.
I am pretty stuck and this project means a lot to me, but I am an inexperienced programmer so I find it hard to handle issue like this. Thanks for help in advance.
Cheers!
First of all please show the full error message. Secondly it is not clear what is MyType and whether it has the default constructor.
If MyType is for example some arithmetic type then the code below will be compiled without errors.
#include "Array.h"
int main() {
Array<MyType> data(5); //Array of 5 elements
}
At least class Array has the default constructor though it is not used. As for the type MyType then it can be said nothing because you did not show neither the full error message nor the definition of MyType.
I suggest to check whether MyType has the default constructor.
If you want to create an array of pointers then you should write
Array<MyType *> data(5);
As for this code
void main() {
MyType **data = new MyType*[5];
...
}
then it has nothing common with the problem. Take into account that main shall be defined as having return type int.
EDIT: If do not take into account errors in the definition of class Tune, then it has no default constructor. So you should decide whether you want to create an array of obects of type Tune or an array of pointers to objects of type Tune. I already showed how fo define the array of pointers. Or define the default constructor for class Tune.
How do I create an array of pointers using my template Array class?
If your class needs an alternate way of constructing its elements, you should create another constructor that initializes it the way you wish, similar to std::vector's constructor:
Array( int count, const T& value );
The easiest way to implement this would be to declare m_ptData as a double pointer and initialize it like so:
Array( int count, const T& value ) : m_ptData(new T*[count])
{
for (int i = 0; i < count; ++i)
{
m_ptData[i] = new T(value);
}
}
The best (and most difficult) way would be to use placement-new to initialize it, this is how std::vector does it. You can use it like this:
int main()
{
Array<MyType> data(5, MyType("abc")); // Array of 5 elements,
// all initialized to MyType("abc")
}
How do I print one or all of the elements of the array?
The inserter operator<<() should be used to print the entire array, so making it do something like printing only some of the elements would be a bit confusing to maintainers of your code. As alternatives, you can create a stream manipulator if you wish to customize output, or you can use a member function that takes a count of the numbers you would like to print. Also, your class can have begin() and end() functions which return pointers to the beginning and end of the array, so the user of the class can implement the printing at their discretion. In either cases, looping should be used to print the elements.
I want to define dynamic array h of size size and later in other functions, modify and use it as here:
class definition:
static int size=10;
class hash{
public:
string h[size];
hash();
void resize();
void operations();
void print();
};
hash::hash()
{
h[size-1]="nikhil"; //size=10 now.
}
/*Defining `h` as `string* h=new string[size];` is not working.
My compiler (MinGW on Windows 7) show error: dynamic allocation is not allowed by default*/
// resizing the array
void hash::resize( )
{
string temp[2*size];
for(int i=0;i<=size;i=i+1)
{
temp[i]=h[i];
}
size=2*size;
h=temp;
}
void hash::print()
{
for(int i=0;i<size;i=i+1)
{if(!h[i].empty())
{cout<<"h["<<i<<"]="<<h[i]<<endl;}
}
}
int main()
{
hash p;
p.resize();//now size should change to 20.
p.print();
}
Where is the problem is it defining the size variable or in resizing the array?
Use std::vector if you need arrays of dynamic size.
class hash {
public:
std::vector<std::string> h;
hash();
void resize();
void operations();
void print();
};
hash::hash() : h(10) {
h[9] = "nikhil";
}
void hash::resize() {
h.resize(2 * h.size());
}
Though note that std::vector does resizing for you automatically if you add new elements using push_back. Also note that the standard library has hash table data types already (std::unordered_set and std::unordered_map), so you don’t have to write them yourself.
I do not know C++ but you haven't exactly told what is going on.
But the way your resize() method is working is the for loop goes through 2*the size of H which will cause a problem.
When you loop through 2*size it is trying to loop through more items than what you actually have in the original array. you have to loop through the original array size.
for(int i = 0; i < h.size(); i++)
{
temp[i] = h[i];
}
I can barely see the comments in your code they are too light for me so I didn't see them.
But to explain a little better i guess, lets say original array is size 5 your new one is size 10 when you loop through 10 items you dont have 10 items in the original array so you'll get errors when trying to access them.
So, I'm new to C++ (brand new), and as an assignment I have to write a class that acts as an array wrapper. Since I'm so new, I'm unsure whether my overloaded operators and such work, so if anyone could be so kind as to tell me how my code looks:
This would be the header:
class MyArray
{
private:
string* sList;
unsigned int size;
public:
MyArray(const unsigned int size = 1);
MyArray(const MyArray &toCopy);
MyArray& operator=(const MyArray& toAssign);
~MyArray();
//MyArray& operator+
string& operator[](const int index);
const int size();
};
And this would be the underlying code:
MyArray::MyArray(const unsigned int initSize)
: size(initSize)
{
sList = new string[initSize];
return;
}
MyArray::MyArray(const MyArray &toCopy)
: size(toCopy.size)
{
if(toCopy.sList)
{
sList = new string[size];
for(int a=0; a<size; a++){
strcpy(sList[a], toCopy.sList[a]);
}
}
else sList = NULL;
return;
}
MyArray& operator=(const MyArray& toAssign)
{
if(this != &toAssign)
{
if(sList)
{
delete [] sList;
}
size = toAssign.size;
if (toAssign.sList)
{
sList = new string[size];
for(int a=0; a<size; a++){
strcpy(sList[a], toCopy.sList[a]);
}
}
else
{
sList = NULL
}
}
}
MyArray::~MyArray()
{
delete [] sList;
return;
}
string& MyArray::operator[](const int index)
{
return sList[index];
}
const int MyArray::size()
{
return this.size;
}
The operator+ function still needs to be written, but I want to make sure what I have makes sense before I proceed.
How do you want your code (i.e. the class you are authoring) to be used by other programmers (including you)?
Write an example program to demonstrate the use of your class.
An example program serves as a rudimentary test set. You can start as the following.
int main() {
MyArray arr1( 5 );
MyArray arr2( arr1 );
}
Have you thought about how user code will put (string?) elements into the MyArray class?
There are couple of other issues with the current version of the code. That is okay to begin with, but it is important for you to learn to test your own code; you need to learn the skill where you have some basic confidence in your own code (not necessarily perfect code) because you cannot always ask somebody else to test your code.
Suggestion: Since you mentioned that you are new, I would suggest you to build a array wrapper class for int's first. This is because, managing strings has some extra challenges than managing ints :-). Once you do that, you can easily do it for strings.
There is a naming conflict between size and size()
Copy C++ strings using =, not strcpy (which is for char*)
Missing MyArray:: in definition of operator=
toCopy should be toAssign in operator=
Missing semicolon after sList = NULL
Missing return *this; at the end of operator=
In defintion of size(), this.size should be size, this->size or (*this).size
All of these mistakes will be discovered by a compiler (you may need to enable warnings for the missing return to be reported; on g++ use the -Wall flag). It is just a matter of understanding the compiler's error messages and knowing how to fix the problems.