I have a class in which vectors of doubles are stored like this this:
class clsHalfphoneUnitJoinFeatures : public CBaseStructure
{
private:
vector<double> m_content;
protected:
virtual void ProcessTxtLine(string line);
public:
vector<double> &Content();
void Add(vector<double> &jf);
};
However, when I want to add a new vector of doubles, it won't work:
void clsHalfphoneUnitJoinFeatures::ProcessTxtLine(string line)
{
line = CompactLine(line);
if (line == "")
return;
int b = 0;
int n = line.find("\t");
string s = "";
int idx = 0;
vector<double>jf;
jf.resize(16);
int i = 0;
for(;;)
{
if (n == -1)//if this is the last item in this line
{
s = line.substr(b,line.length()-b);
jf[i++] = atof(s.c_str());
break;
}
s = line.substr(b,n-b);
jf[i++] = atof(s.c_str());
b = n+1;
n = line.find("\t",b);
}
m_content.push_back(jf);
}
The error I am getting is in
m_content.push_back(jf);
error C2664: 'void std::vector<_Ty>::push_back(_Ty &&)': Conversion of parameter 1 from 'std::vector<_Ty>' in 'double &&' not possible
Can somebody tell me where I went wrong?
Thank you!
jf and m_content have the same type, you can't push jf as an element of m_content.
Try change
m_content.push_back(jf);
To:
m_content = jf;
If you want to have a vector of vector of double type, you need to declare m_content as:
std::vector<std::vector<double> > m_content;
a) Error m_content.push_back(jf);. You are trying to push vector to a vector which can store double. so the compiler is giving error.
You can resolve it by assigning jf to m_context
m_content = jf;
b) Else if your implementation needs vector of vector follow the steps below
Declare m_content as vector of double vector.
vector<vector<double>> m_content;
...
m_content.push_back(jf);
Related
for (auto enemy : this->enemies)
{
if (enemy->getHP() <= 0)
{
enemies.erase(enemy);
}
}
I have a vector enemies containing multiple of Enemy* elements and i want to erase an enemy if their hp is 0 or below
I write the code above and it gave me this error message:
No instance of overloaded function "std::vector<_Ty, _Alloc>::erase [with _Ty=Enemy *, _Alloc=std::allocator<Enemy *>]" matches the argument list
argument types are: (Enemy*)
object type is: std::vector<Enemy*,std::allocator<Enemy*>>
I assume that is not the right way to do it, so how?
Im new in stackoverflow and im still learning english so sorry if i made mistakes
EDIT:
It's my almost complete code:
struct enemyType
{
public:
int type;
sf::Vector2f pos;
}
std::vector<std::vector<enemyType>> enemyList = {
{
{ trashMonster, sf::Vector2f(5.f * 16, 18.f * 16) }
}
}
std::vector<Enemy*> enemies;
std::vector<Enemy*>* GetEnemy(int level)
{
for (int i = 0; i < enemyList[level].size(); i++)
{
switch (enemyList[level][i].type)
{
case trashMonster:
n_TrashMonster->setPosition(enemyList[level][i].pos);
enemies.emplace_back(n_TrashMonster);
break;
default:
std::cout << "Error to get an enemy\n";
break;
}
}
return &enemies;
}
//Code in different file
std::vector<Enemy*> enemies;
this->enemies = *GetEnemy(lvl);
for (auto enemy : this->enemies)
{
enemy->update(player->getCollisionBox());
//collision enemies to tilemap
collision::MapCollision(*this->map.getTilesCol(), *enemy);
if (enemy->getHP() <= 0)
{
enemies.erase(enemy);
}
}
Didn't include that because my code is a complete mess so I was afraid people won't get the point of my question and it's my first question here
The std::vector<T>::erase function does not have a erase(T a) overload. And if you want to remove elemennts from a vector you can't iterate over them like that. I suggest a convencional loop.
for (size_t i=0; i<this->enemies.size();++i){
if (this->enemies[i]->getHP()){
std::swap(enemies[i],enemies::back());
delete enemies::back();//Only if you don't free the space elsewere
enemies.pop_back();
}
}
Edit:
This will mess up the order of the vector. If you don't want that you can use erase(enemies.begin()+i) iinstead of swaping it back and removeing it
When using STL containers usually you don't even need an (explicit) for loop. Use std::remove_if like this
#include <vector>
#include <algorithm>
#include <iostream>
class Enemy
{
public:
// not explicit on purpose, so I can initalize vector more quickly (in real code you should have explicit constructors if they have one argument of a different type)
Enemy(int hp) :
m_hp{ hp }
{
};
int getHP() const noexcept
{
return m_hp;
}
int m_hp;
};
int main()
{
// create a test vector with enemies with given hitpoints
std::vector<Enemy> enemies{ 1,2,0,4,5,6,0,7,8 };
// boolean lambda function that determines if an enemy is dead.
auto enemy_is_dead = [](const Enemy& enemy) { return enemy.getHP() <= 0; };
// use remove_if (this will move all the items to be removed to the end
auto remove_from = std::remove_if(enemies.begin(), enemies.end(), enemy_is_dead );
// then shrink the vector
enemies.erase(remove_from, enemies.end());
for (const auto& enemy : enemies)
{
std::cout << enemy.getHP() << " ";
}
return 0;
}
I have an insertion sort function
void insertionSort(ArrayList<int> myData)
{
for (int i = 1; i < myData.getSize(); i++) {
int index = myData[i];
int j = i;
while (j > 0 && myData[j-1] > index) {
myData.swap(j - 1, j);
j--;
}
myData[j] = index;
}
}
which uses this swap function
template<class TYPE>
void ArrayList<TYPE>::swap(int from, int to) throw(std::out_of_range)
{
int temp = 0;
temp = this->items[from];
this->items[from] = this->items[to];
this->items[to] = temp;
swapNum++;
}
This is how my private methods look like
TYPE * items;
int currentLength;
static int swapNum;
I have an overloaded [] operator and a getSize() function that I think I wrote well and not contributing to my problem. Now if I do this in my main.cpp
ArrayList<int>m_Data(1);
and append say 4,2,9,1 on the m_Data and call
insertionSort(m_Data);
I get two errors
1. Error C2440 '=': cannot convert from 'std::string' to 'int'
on the swap function and
2. The insertion sort doesn't work
First problem: it should be something like TYPE temp = this->items[from]. After repairing it (I used STL swap) function works. Well, it works on STL vector and swap. If you still do have problem, then your array structure is probably invalid.
EDIT: In function 'insertionSort' shouldn't you have template (as in swap function)?
public:
typedef ics::pair<KEY,T> Entry;
typedef int (*hashfunc) (const KEY& a);
private:
int (*hash)(const KEY& k); //Hashing function used (from template or constructor)
enum bin_state {bs_empty, bs_occupied, bs_was_occupied};
Entry* map = nullptr; //Entry array
bin_state* state = nullptr; //bin_state[] describes the state of map[i]
double load_threshold; //used/bins <= load_threshold
int bins = 1; //# bins in array (should start at 1 so hash_compress doesn't % 0)
int used = 0; //Cache for number of key->value pairs in the hash table
int mod_count = 0; //For sensing concurrent modification
//Helper methods
int hash_compress (const KEY& key) const; //hash function ranged to [0,bins-1]
int find_key (const KEY& key) const; //Returns index to key's bin or -1
int next_unoccupied (int bin) const; //this bin or next beyond that is unoccupied
void ensure_load_threshold(int new_used); //Reallocate if load_factor > load_threshold
HashOpenMap<KEY,T,thash>::HashOpenMap(double the_load_threshold, int (*chash)(const KEY& k)): hash(thash != (hashfunc)undefinedhash<KEY> ? thash : chash), load_threshold(the_load_threshold)
{
if (hash == (hashfunc)undefinedhash<KEY>)
throw TemplateFunctionError("HashMap::default constructor: neither specified");
if (thash != (hashfunc)undefinedhash<KEY> && chash != (hashfunc)undefinedhash<KEY> && thash != chash)
throw TemplateFunctionError("HashMap::default constructor: both specified and different");
map = new Entry[bins];
for (int b=0; b<bins; ++b)
map[b] = new bin_state[];
}
I am new to c++. I am currently writing the Constructors for the HashOpenMap. For the above code, I got the following error:
no viable overloaded '='
map[b] = new bin_state[];
any idea how to fix it? thanks in advance.
Make sure you instantiate the same type as the target array element
map[b] = new Entry{};
Also, consider not using new/delete in C++. Or raw C arrays.
I have a Shop template class and a Cookie class and trying to create a dynamic array of Cookie kind (or something else's kind since it is a template) and add more if required as follows in my main function such as:
template <typename shopType>
class Shop {
private:
int noi; // number of items
double totalcost;
shopType * sTptr; // for dynamic array
public:
Shop(shopType &);
void add(shopType &);
.....
and
int main() {
.....
Cookie cookie1("Chocolate Chip Cookies", 10, 180);
Cookie cookie2("Cake Mix Cookies", 16, 210);
Shop<Cookie> cookieShop(cookie1); // getting error here
cookieShop.add(cookie2); // and here
.....
with constructor and methods I wrote like:
template<typename shopType>
Shop<shopType>::Shop(shopType & sT)
{
sTptr = new shopType;
sTptr = sT; // not allowed, how can I fix ?
noi = 1;
totalcost = sT.getCost();
}
template<typename shopType>
void Shop<shopType>::add(shopType & toAdd)
{
if (noi == 0) {
sTptr = new shopType;
sTptr = toAdd; // not allowed, how can I fix ?
totalcost = toAdd.getCost();
noi++;
}
else {
shopType * ptr = new shopType[noi + 1];
for (int a = 0; a < noi; a++) {
ptr[a] = sTptr[a];
}
delete[] sTptr;
sTptr = ptr;
sTptr[noi++] = toAdd;
totalcost += toAdd.getCost();
}
}
and I am naturally getting C2440 '=': cannot convert from 'Cookie' to 'Cookie *' error...
I understand what I am doing wrong but I can't figure it out how to do it in the right way...
Should creating a new Cookie pointer and copying the one in parameter to it would work, or something else? Any suggestions ? Thanks in advance.
The error message from the compiler is pretty clear. You are trying to assign a shopType to a shopType* in the line:
sTptr = toAdd;
Unless you have very strong reasons for managing memory for the array yourself, use a std::vector to store the objects in a Shop.
template <typename shopType>
class Shop {
private:
// There is no need for this.
// int noi; // number of items
double totalcost;
std::vector<shopType> shopItems;
// ...
};
Then, Shop::add can be implemented simply as (I changed the argument type to a const reference):
template<typename shopType>
void Shop<shopType>::add(shopType const& toAdd)
{
shopItems.push_back(toAdd);
}
I am making a program where I have 2 vectors (clientvec and productslist) and I need to create a 2D boolean matrix where the columns is the size of productslist vector and the lines is the size of clientvec vector, but it gives me this error:
"expression must have a constant value"
Here is the code I used:
unsigned int lines = clientvec.size();
unsigned int columns = productslist.size();
bool matrixPublicity[lines][columns] = {false};
Pls help me..
Edit: I am new at c++ so assume I know nothing xD
Edit2: I already know for the answers that I cannot initialize an array with non constant values, now the question is how can I put them after initialize...
The error message is clear: :expression must have a constant value"
It means the array dimension cannot be of variable type. Only enums or pre-processor defined constants are valid.
See for more info:
Why can't I initialize a variable-sized array?
Edit: Since you mentioned you are new to C++, here is a piece of code that might help you:
#include <iostream>
#include <vector>
#include <bitset>
int main()
{
unsigned int lines = 10;
const unsigned int columns = 5;
std::vector<std::bitset<columns>> matrixPublicity;
matrixPublicity.resize(lines);
for(int i=0; i < lines; i++)
{
for(int j=0; j < columns; j++)
std::cout << matrixPublicity[i][j] <<' ';
std::cout<<'\n';
}
}
note that in this case, columns must be constant.
Edit 2: And if the size of lines are not the same, then you must stick to vector types:
typedef std::vector<bool> matrixLine;
std::vector<matrixLine> matrixPublicity;
now you can use resize method for the i-th line of the matrix, e.g.
matrixPublicity[1].resize(number_of_columns_in_line_2);
What you are trying to do would be the same as this:
std::vector<unsigned int> v1 { 1, 2, 3, 4, 5 };
std::vector<unsigned int> v2 { 6, 7, 8, 9 };
bool mat[v1.size()][v2.size()] = false;
This is how the compiler will interpret it without the temporaries and this is invalid. When you declare an array of any type its size has to be known at compile time.
bool mat[2][3] = false; // still invalid
bool mat[2][3] = { false }; // Okay
const int x = 5;
const int y = 7;
bool mat[x][y] = false; // invalid
bool mat[x][y] = { false }; // okay
// Even this is invalid
std::vector<int> v1{ 1, 2, 3 };
std::vector<int> v2{ 4, 5, 6, 7 };
const std::size_t x1 = v1.size();
const std::size_t y1 = v2.size();
bool mat2[x1][y1] = { false }; // Still won't compile.
Value to declare an array must be a constant expression.
Instead of making an array as you have tried to do, you could make a class template that will construct a matrix like object for you. Here is what I have come up with, now the overall design or pattern of this template will fit your condition but the actual implementation to generate the internal matrix will depend on your data and what you intend.
#include <vector>
#include <iostream>
#include <conio.h>
template <class T, class U>
class Matrix {
private:
std::vector<T> m_lines;
std::vector<T> m_cols;
std::vector<U> m_mat;
std::size_t m_size;
std::size_t m_lineCount;
std::size_t m_colsCount;
public:
Matrix() {};
Matrix( const std::vector<T>& lines, const std::vector<T>& cols ) :
m_lines(lines),
m_cols(cols),
m_lineCount( lines.size() ),
m_colsCount( cols.size() )
{
addVectors( lines, cols );
}
void addVectors( const std::vector<T>& v1, const std::vector<T>& v2 ) {
m_lines = v1;
m_cols = v2;
m_lineCount = m_lines.size();
m_colsCount = m_cols.size();
for ( unsigned int i = 0; i < m_lineCount; ++i ) {
for ( unsigned int j = 0; j < m_colsCount); j++ ) {
// This will depend on your implementation and how you
// construct this matrix based off of your existing containers
m_mat.push_back(m_lines[i] & m_cols[j]);
}
}
m_size = m_mat.size();
}
std::size_t size() const { return m_size; }
std::size_t sizeRows() const { return m_lineCount; }
std::size_t sizelColumns() const { return m_colsCount; }
std::vector<U>& getMatrix() const { return m_mat; }
std::vector<T>& getLines() const { return m_lines; }
std::vector<T>& getColumns() const { return m_columns; }
bool operator[]( std::size_t idx ) { return m_mat[idx]; }
const bool& operator[]( std::size_t idx ) const { return m_mat[idx]; }
};
int main() {
std::vector<unsigned> v1{ 1, 0, 1, 1, 0 };
std::vector<unsigned> v2{ 0, 1, 1, 1, 0 };
Matrix<unsigned, bool> mat1( v1, v2 );
int line = 0;
for ( unsigned u = 0; u < mat1.size(); ++u ) {
line++;
std::cout << mat1[u] << " ";
if ( line == mat1.sizeRows() ) {
std::cout << "\n";
line = 0;
}
}
std::cout << "\nPress any key to quit.\n" << std::endl;
_getch();
return 0;
}
Output
0 1 1 1 0
0 0 0 0 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0
With this template class you can create a matrix of any type U by passing in two vectors for type T. Now how you construct the matrix will be implementation dependent. But this class is reusable for different types.
You could have two vectors of type doubles, and construct a matrix of unsigned chars, or you could have two vectors of user defined class or struct types and generate a matrix of unsigned values. This may help you out in many situations.
Note: - This does generate a compiler warning, no errors though and it prints and displays properly, but the compiler warning generated by MSVS 2015 is warning C4800: unsigned int: forcing value to bool true or false (performance warning)
This is generated for I am doing a bit wise & operation on to unsigned values; but that is why I set my initial vectors to be passed to this class template's constructor to have all 1s & 0s as this is meant for demonstration only.
EDIT - I made an edit to the class because I noticed I had a default constructor and had no way to add vectors to it, so I added an extra member variable, and an addVectors function, and moved the implementation from the defined constructor to the new function and just ended up calling that function in the defined constructor.
Creating an array isn't that difficult :)
A matrix (2D/3D/...-array) is unfortunately a little bit different if you want to do it your way!
But first of all you should know about the stack and the heap!
Lets have a look at these 2:
Stack:
A stack variable/array/matrix/... is only valid between the nearest 2 -> {} <- which you normally call a "codeblock". The size of it was defined during the "compile time" (the time where the compiler translates your code into the machine language). That means the size of your array needs to be set.
Example:
#include <iostream>
#define MACRO 128
int arraySize(int size){
std::cin >> size;
return size;
}
int main() {
//this is valid
int intArray[128] = {}; //the size(here: 128) needs to be a number like
//or a macro like 'MACRO' which is
//compile-time-only as well
//this is valid
int intArray2[MACRO] = {};
//this is not valid!
int intArray[size()] = {};
return 0;
}
Heap:
A heap variable/array/matrix/... is valid until you delete it. That also means that a heap var is created during the run-time(from starting your program until you close/stop it)! This is allows you to define it's size.
Example:
#include <iostream>
#define MACRO 128
int arraySize(int size){
return size;
}
int main() {
//this is valid
int intArray[128] = {}; //the size(here: 128) needs to be a number like
//or a macro like 'MACRO' whic is
//compile-time-only as well
//this is valid
int intArray2[MACRO] = {};
//creating an array with a non-static size
//works like this:
//int can also be a 'bool'
int* intArray = new int[arraySize()];
// ^ the star means you are pointing to
//an adress inside of your memory which has
//the size of an int (per element)
//That's why they are called "pointers"!
//Right now it points to the beginning of the
//array.
// ^ the keyword "new" says that
//you are allocating memory on the heap.
// ^
//then you have to say which kind of array
//it is which is the same you gave the pointer
// ^
//now you give it the size of that array
//this time it can be return value or the size
//of a variable
//as I mentioned...you have to delete this array on your own
//if you dont do that your program will crash
//maybe not after starting but it will!
//SO NEVER NEVER NEVER... forget about it
delete intArray[];
//^ write delete
// ^
//then the name of your array
// ^
//at the end of it write these 2 brackets
//thex say you wanna remove the whole array!
//why? because you can also create/delete
//heap variables not only arrays.
return 0;
}
Creating a matrix on the heap is unfortunately not that easy.
But it is essential to know how a 1D-array works before going to further dimensions! That's why I did this tutorial!
Klick here to see how to create a matrix on the heap
Klick here to learn more about the heap
Klick here to choose the best result of this theme
I hope I could help you :)!