I read Google’s native client tutorial on how to build my own C++ based PNaCl module several times and somehow I'm not getting wiser, I know that if I want to implement a messaging functionality. I have the following in the .cc file as basis for a PNaCl code, all this is taken from Googles's Hello World tutorial:
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var_array.h"
#include "ppapi/cpp/var.h"
namespace {
// The expected string sent by the browser.
const char* const kHelloString = "hello";
// The string sent back to the browser upon receipt of a message
// containing "hello".
const char* const kReplyString = "hello from NaCl";
} // namespace
class job1Instance : public pp::Instance {
public:
explicit job1Instance(PP_Instance instance): pp::Instance(instance) {}
virtual ~job1Instance() {}
virtual void HandleMessage(const pp::Var& message) {
if (!message.is_string()) {
return;
}
std::string message_txt = message.AsString();
pp::Var reply;
if (message_txt == kHelloString) {
reply = pp::Var(kReplyString);
PostMessage(kReplyString);
}
}
};
class job1 : public pp::Module {
public:
job1() : pp::Module() {}
virtual ~job1() {}
virtual pp::Instance* CreateInstance(PP_Instance instance) {
return new job1Instance(instance);
}
};
namespace pp {
Module* CreateModule() {
return new job1();
}
} // namespace pp
As I understand the PNaCl modules don’t use a main() function and yet let’s say I have an old C++ code that creates 2 arrays unsorted1 and unsorted2 with random numbers which I want to use in my PNaCl module:
#include <iostream>
#include <stdint.h>
#include <unistd.h>
#include <array>
// a function to create a random number between min and max
int32_t rangeRandomAlg (int32_t min, int32_t max) {
int32_t num = max - min + 1;
int32_t remainder = RAND_MAX % num;
int32_t x;
do {
x = rand();
} while (x >= RAND_MAX - remainder);
return min + x % num;
}
// a function to create arrays with random numbers
void unsortedArrays(int32_t unsorted1[], int32_t unsorted2[],int32_t arrayElements, int32_t minNum, int32_t maxNum){
for(int32_t i = 0; i <= arrayElements; i++) {
if (i < arrayElements/2) {
unsorted1[i] = rangeRandomAlg(minNum, maxNum);
} else {
unsorted2[i] = rangeRandomAlg(minNum, maxNum);
}
}
}
// the main function
int32_t main(int32_t argc, char *argv[]) {
// declare all the zises
int32_t minNum = 0;
int32_t maxNum = 100;
int32_t arrayElements = maxNum;
// the arrays
int32_t unsorted1[arrayElements/2];
int32_t unsorted2[arrayElements/2];
// fill the arrays with random numbers
unsortedArrays(unsorted1, unsorted2, arrayElements, minNum, maxNum);
return 0;
}
My problem is that I didn’t quite understand how can I integrate this code into the PNaCl module and use the HandleMessage() function to sent the unsorted1 and unsorted2 arrays back to the JavaScript with the PostMesage() function. I know I have to work with arrays and not strings in the HandleMessage() function.
I hope to get some help here, since I’m really new to this whole native client thing.
Well here is the solution that took some hours to get to:
// pepper includes
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var_array.h"
#include "ppapi/cpp/var.h"
#include "json/json.h"
#include <sstream>
// cpp includes
#include <stdint.h>
#include <unistd.h>
#include <array>
#include <string>
//static variables
namespace {
// The expected string sent by the browser.
const char* const kHelloString = "Bereit fuer dein Modul";
// The string sent back to the browser upon receipt of a message
// containing "hello".
const char* const kReplyString = "PNaCl hat Ergebnisse geschickt";
} // namespace
class job1Instance : public pp::Instance {
public:
explicit job1Instance(PP_Instance instance): pp::Instance(instance) {}
virtual ~job1Instance() {}
virtual void HandleMessage(const pp::Var& message) {
/*
if (!message.is_string()) {
return;
}
std::string message_txt = message.AsString();
pp::Var reply;
if (message_txt == kHelloString) {
reply = pp::Var(kReplyString);
PostMessage(kReplyString);
}
*/
/*** my functions and data for the cpp code to integrate start here ***/
// declare all the zises
int32_t minNum = 0;
int32_t maxNum = 100;
int32_t arrayElements = maxNum;
// the arrays
int32_t unsorted1[arrayElements/2];
int32_t unsorted2[arrayElements/2];
// fill the arrays with random numbers
unsortedArrays(unsorted1, unsorted2, arrayElements, minNum, maxNum);
std::string outRes1, outRes2;
arrayToString(unsorted1, arrayElements/2, outRes1);
arrayToString(unsorted2, arrayElements/2, outRes2);
PostMessage(outRes1); // send the unsorted1 array as a string to the JavaScript back
}
private:
// function to create a random number between min and max
int32_t rangeRandomAlg (int32_t min, int32_t max) {
int32_t num = max - min + 1;
int32_t remainder = RAND_MAX % num;
int32_t x;
do {
x = rand();
} while (x >= RAND_MAX - remainder);
return min + x % num;
}
// function to create arrays with random numbers
void unsortedArrays (int32_t unsorted1[], int32_t unsorted2[],int32_t arrayElements, int32_t minNum, int32_t maxNum) {
for(int32_t i = 0; i <= arrayElements; i++) {
if (i < arrayElements/2) {
unsorted1[i] = rangeRandomAlg(minNum, maxNum);
} else {
unsorted2[i] = rangeRandomAlg(minNum, maxNum);
}
}
}
// convert the arrays to string
void arrayToString (int32_t array[], int32_t arraySize, std::string& arrayString) {
for (int32_t i = 0; i <= arraySize; ++i){
arrayString+= std::to_string(array[i]);
if (i != arraySize) {
arrayString+= ',';
}
}
}
};
/*** my functions and data for the cpp code to integrate end here ***/
class job1 : public pp::Module {
public:
job1() : pp::Module() {}
virtual ~job1() {}
virtual pp::Instance* CreateInstance(PP_Instance instance) {
return new job1Instance(instance);
}
};
namespace pp {
Module* CreateModule() {
return new job1();
}
} // namespace pp
This is only the precompiled C++ code of the PNaCl module with my code integrated in it, it sends only the outRes1 variable = unsorted1 array variable as string to the JavaScript code in the index.html file. You have to have the .nmf and the index.html files written separately. If anyone wants to see my code of those files, which has the basic and working code for this PNaCl module should write me a comment and I’ll post those to.
Related
What I am trying to do is add cards to a vector that is to be a Blackjack hand, but each time I enter the function that uses push_back to add a card to the vector, the vector starts out empty. The problem is in my Hand class in the addCardToHand function, and the same issue is present in the same class in my showHand function. I have whittled the code down as much as I could but still present a full working version with the issue. I cannot figure out why my Hand class treats the hand as brand new every time I call a function in the class. Please advise.
// Card.h
#ifndef CARD_H
#define CARD_H
#include <string>
#include <array>
class Card {
private:
int rank;
int suit;
int hardValue;
int softValue;
static const std::array<std::string,14> ranks;
static const std::array<std::string,5> suits;
public:
Card();
Card(int rank, int suit);
int getHardValue() const;
int getSoftValue() const;
std::string toString() const;
};
#endif
// Card.cpp
#include "Card.h"
const std::array<std::string,14> Card::ranks {"","A","2","3","4","5","6","7","8","9","10","J","Q","K"};
const std::array<std::string,5> Card::suits {"","C","D","H","S"};
Card::Card() : rank(0), suit(0) {
hardValue = 0;
softValue = 0;
}
Card::Card(int rank, int suit) : rank(rank), suit(suit) {
if (rank == 1) {
hardValue = 1;
softValue = 11;
}
else if (rank <= 10) {
hardValue = rank;
softValue = rank;
}
else {
hardValue = 10;
softValue = 10;
}
}
int Card::getHardValue() const {
return hardValue;
}
int Card::getSoftValue() const {
return softValue;
}
std::string Card::toString() const {
return ranks[rank] + suits[suit];
}
// Shoe.h
#ifndef SHOE_H
#define SHOE_H
#include <vector>
#include <random>
#include "Card.h"
class Shoe {
private:
int numDecksInShoe;
std::vector<Card> shoe;
static int currentCard;
static int maxDealCard;
static const unsigned long int seed;
static std::mt19937 randEng;
void renewShoe();
public:
Shoe();
explicit Shoe(int numDecksInShoe);
std::vector<Card> getShoe() const;
int getCurrentCard() const;
int getMaxDealCard() const;
void shuffle();
Card dealCard();
};
#endif
// Shoe.cpp
#include <ctime>
#include "Shoe.h"
const unsigned long int Shoe::seed = static_cast<unsigned long int>(std::time(nullptr));
std::mt19937 Shoe::randEng(seed);
int Shoe::currentCard = 0;
int Shoe::maxDealCard = 51;
Shoe::Shoe() {
}
Shoe::Shoe(int decksInShoe) {
numDecksInShoe = decksInShoe;
int count = 0;
for (int i = 0; i < numDecksInShoe; i++) {
for (int suit = 4; suit >= 1; suit--) {
for (int rank = 1; rank <= 13; rank++) {
Card card(rank,suit);
shoe.push_back(card);
count += 1;
}
}
}
currentCard = 0;
maxDealCard = count - 1;
}
std::vector<Card> Shoe::getShoe() const {
return shoe;
}
int Shoe::getCurrentCard() const {
return currentCard;
}
int Shoe::getMaxDealCard() const {
return maxDealCard;
}
void Shoe::shuffle() {
Card temp;
std::uniform_int_distribution<int> deckDist(0,numDecksInShoe*52-1);
int index;
for (int i = 0; i < numDecksInShoe*52; i++) {
do {
index = deckDist(randEng);
} while (index == i);
temp = shoe[index];
shoe[index] = shoe[i];
shoe[i] = temp;
}
std::uniform_int_distribution<int> maxDeal(10,41);
int tempMax = (numDecksInShoe-1)*52 - 1;
maxDealCard = tempMax + 51 - maxDeal(randEng);
}
Card Shoe::dealCard() {
if (currentCard == maxDealCard) {
renewShoe();
}
Card dealCard = shoe[currentCard];
currentCard += 1;
return dealCard;
}
void Shoe::renewShoe() {
Shoe newShoe(numDecksInShoe);
shoe = newShoe.getShoe();
shuffle();
}
here is my Hand class
// Hand.h
#ifndef HAND_H
#define HAND_H
#include <vector>
#include <string>
#include "Card.h"
class Hand {
private:
std::vector<Card> hand;
public:
Hand();
std::vector<Card> getHand() const;
void addCardToHand(Card card);
void clearHand();
Card revealBottomCard();
std::string showHand() const;
std::string peakHand() const;
};
#endif
// Hand.cpp
#include <iostream>
#include "Hand.h"
Hand::Hand() {
}
std::vector<Card> Hand::getHand() const {
return hand;
}
void Hand::addCardToHand(Card card) {
std::cout << card.toString() << std::endl;
hand.push_back(card);
}
void Hand::clearHand() {
hand.clear();
}
std::string Hand::showHand() const {
std::string returnString = "";
for (int i = hand.size()-1; i >= 1; i--) {
returnString += hand[i].toString() + "\n";
}
returnString += "XX\n";
return returnString;
}
std::string Hand::peakHand() const {
std::string returnString = "";
for (int i = hand.size()-1; i >= 0; i--) {
returnString += hand[i].toString() + "\n";
}
return returnString;
}
here is the Table class that has the code that calls the Hand class functions
// Table.h
#ifndef TABLE_H
#define TABLE_H
#include "Shoe.h"
#include "Player.h"
class Table {
private:
Shoe shoe;
public:
explicit Table(Shoe shoe);
Shoe getShoe() const;
void clearHand(std::vector<Player> players);
void dealHand(std::vector<Player> players);
};
#endif
// Table.cpp
#include <iostream>
#include "Table.h"
Table::Table(Shoe shoe) : shoe(shoe) {
}
Shoe Table::getShoe() const {
return shoe;
}
void Table::clearHand(std::vector<Player> players) {
for (Player &player : players) {
player.getHand().clearHand();
}
}
void Table::dealHand(std::vector<Player> players) {
for (int i = 0; i <= 1; i++) {
for (Player &player : players) {
player.getHand().addCardToHand(shoe.dealCard());
}
}
}
// Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include "Hand.h"
class Player {
private:
std::string name;
Hand hand;
double money;
public:
explicit Player(std::string name, double money = 1000.0);
std::string getName() const;
Hand getHand() const;
double getMoney() const;
};
#endif
// Player.cpp
#include "Player.h"
Player::Player(std::string name, double money) : name(name), money(money) {
}
std::string Player::getName() const {
return name;
}
Hand Player::getHand() const {
return hand;
}
double Player::getMoney() const {
return money;
}
and finally here is a short driver that runs and displays the issue
// blackjack testing
#include <iostream>
#include "Player.h"
#include "Table.h"
int main() {
std::vector<Player> players {Player("Tom",1500.0),Player("Sue"),Player("Dave")};
Shoe shoe1(6);
Table table1(shoe1);
table1.dealHand(players);
for (Player player : players) {
std::cout << player.getName() << "'s hand\n";
std::cout << player.getHand().showHand() << "\n\n";
}
}
The output is below. I printed out the cards that were added to the hand vector (and then 'forgotten') and below that above the XX's, if everything were to work correctly you should see the 4, 5 and 6 of spades since I did not shuffle the deck. The XX's are to simulate face down bottom card.
AS
2S
3S
4S
5S
6S
Tom's hand
XX
Sue's hand
XX
Dave's hand
XX
Sorry for dumping all this code in here, but I wanted to provide a full working solution and this is as small as I could get it. Thanks for any help.
player.getHand().addCardToHand(...);
player.getHand() returns a temporary Hand object that's a copy of player.hand. Then you add a card to that temporary object. Then that temporary object dies, added card and all. player.hand remains unchanged. This line of code is an elaborate no-op.
To add on #Igor's answer, the best way to fix this should probably return a reference instead:
const Hand& Player::getHand() const {
return hand;
}
I made this a const because returning a non-const could (potentially) allow you to break constness of a constant Player object. That is just inviting potential bugs.
Because of this, you may want to add a non-const version too:
Hand& Player::getHand() {
return hand;
}
Now you can't modify a const Player object, yet modify it properly when you need to.
This is my code:
#include <cstdlib>
#include <ctime>
#include <stdio.h>
#include <vector>
#define ENTITY(A) entity##A
#define ALM(A) alm##A
struct TEntity{
private:
int sumx;
int sumy;
const char * rep;
int m_ix;
int m_iy;
public:
TEntity(int x, int y, int sum_x, int sum_y, const char * txt);
};
TEntity::TEntity(int x, int y, int sum_x, int sum_y, const char * txt) {
m_ix = x;
m_iy = y;
sumx = sum_x;
sumy = sum_y;
rep = txt;
}
class IAlmacenable {
private:
void * element;
public:
IAlmacenable(void * e);
IAlmacenable();
void * getValue();
};
IAlmacenable::IAlmacenable(void *e) {
element = e;
}
IAlmacenable::IAlmacenable() {
element = nullptr;
}
void * IAlmacenable::getValue() {
return element;
}
class TList {
private:
std::vector<IAlmacenable*> elementos;
int position;
public:
TList();
int Size();
int Push(IAlmacenable* psz);
};
TList::TList() {
elementos = std::vector<IAlmacenable*>();
position = 0;
}
int TList::Size() {
return elementos.size();
}
int TList::Push(IAlmacenable* psz) {
int res = 0;
if (elementos.size() >= elementos.max_size()) {
res = -1;
}
else {
elementos.push_back(psz);
}
return res;
}
int main(){
srand(time(NULL));
TList *list = new TList();
//we can put entities in the list and the rest will be filled up to 5
int size = list->Size();
for(int i = size; i<5;i++){
const char c[] = {(rand() % 2 ? 65 + rand() % 25 : 97 + rand() % 25), '\0'};
TEntity ENTITY(i)(rand() % 10, rand() % 10, rand() % 5, rand() % 5, c);
IAlmacenable ALM(i)(&ENTITY(i));
list->Push(&ALM(i));
size++;
}
//do things like printing their value...
delete list;
return 0;
}
I need to create a new variable everytime it run the "TEntity ENTITY(i)" line,
the problem is that it creates the same variable always, I think it is because it creates the variable entityi and therefore it is overwriting on the same variable, besides it seems that the random it generates is always the same number since all entities have the same values in all its parameters. The c variable create a const char * random variable between a-z, A-Z , I don't put the print code because it is unnecessary, so what can I do? Is there any way to dynamically create variables of entities whose values are random?
EDIT
Here is the new code fixed (the macros have been eliminated since they were not necessary and the necessary code has been included to be able to execute it) but there is still the same problem that they are generated with the same parameters (since they are still the same variable):
#include <cstdlib>
#include <ctime>
#include <stdio.h>
#include <vector>
#include <conio.h>
#include <windows.h>
struct TEntity{
private:
int sumx;
int sumy;
const char * rep;
int m_ix;
int m_iy;
public:
TEntity(int x, int y, int sum_x, int sum_y, const char * txt);
void movimiento();
void pinta();
};
TEntity::TEntity(int x, int y, int sum_x, int sum_y, const char * txt) {
m_ix = x;
m_iy = y;
sumx = sum_x;
sumy = sum_y;
rep = txt;
}
void TEntity::movimiento() {
m_ix += sumx;
m_iy += sumy;
}
void TEntity::pinta() {
gotoxy(static_cast<short int>(m_ix), static_cast<short int>(m_iy));
printf("%s", rep);
}
void gotoxy(short int x, short int y)
{
COORD pos = {x, y};
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output, pos);
}
void clear()
{
system("cls");
}
class IAlmacenable {
private:
void * element;
public:
IAlmacenable(void * e);
IAlmacenable();
void * getValue();
};
IAlmacenable::IAlmacenable(void *e) {
element = e;
}
IAlmacenable::IAlmacenable() {
element = nullptr;
}
void * IAlmacenable::getValue() {
return element;
}
class TList {
private:
std::vector<IAlmacenable*> elementos;
int position;
public:
TList();
int Size();
int Push(IAlmacenable* psz);
IAlmacenable* First();
IAlmacenable* Next();
};
TList::TList() {
elementos = std::vector<IAlmacenable*>();
position = 0;
}
int TList::Size() {
return elementos.size();
}
int TList::Push(IAlmacenable* psz) {
int res = 0;
if (elementos.size() >= elementos.max_size()) {
res = -1;
}
else {
elementos.push_back(psz);
}
return res;
}
IAlmacenable* TList::First() {
IAlmacenable* res;
if (elementos.empty()) {
res = nullptr;
}
else {
res = elementos.front();
position = 1;
}
return res;
}
IAlmacenable* TList::Next() {
IAlmacenable* res;
if (elementos.empty()) {
res = nullptr;
}
else {
int pos = position;
int size = elementos.size();
if (pos < size) {
res = elementos.at(position);
position++;
}
else {
res = this->First();
}
}
return res;
}
int main(){
srand(time(NULL));
TList *list = new TList();
//we can put entities in the list and the rest will be filled up to 5
int size = list->Size();
for(int i = size; i<5;i++){
const char c[] = {(rand() % 2 ? 65 + rand() % 25 : 97 + rand() % 25), '\0'};
TEntity *entity = new TEntity(rand() % 10, rand() % 10, rand() % 5, rand() % 5, c);
IAlmacenable *alm = new IAlmacenable(entity);
list->Push(alm);
size++;
}
while(true){
clear();
for (int i = 0; i < size; i++) {
reinterpret_cast<TEntity *>(list->Next()->getValue())->pinta();
reinterpret_cast<TEntity *>(list->Next()->getValue())->movimiento();
}
Sleep(2000);
}
delete list;
return 0;
}
There is some confusion here.
Some points:
The macro is not fit-for-purpose, as you already know; you're just creating a variable name entityi each time;
That doesn't matter! The object only exists for the duration of the loop iteration anyway; C++ doesn't let you create multiple objects with the same name at the same time. In fact you can get rid of the entire macro stuff and just call the object entity;
Now that that's out of the way, you're getting repeated results because you're storing a pointer to each iteration of that local variable — on each occasion, that's a dangling pointer to an object that's been destroyed. Don't store dangling pointers!
You can either:
Dynamically allocate the objects that you're adding to the list, or
Store actual objects rather than pointers-to-objects.
Either way, the local-scope name is irrelevant and certainly need not change repeatedly for each loop iteration.
I'm trying to make an Arduino library, for a build that I'm going to be using throughout a few sketches, and I haven't been able to figure out why I keep getting this error. Searching on multiple forums, comes up with no working answers. This is my code:
charLCD.h:
#ifndef charLCD
#define charLCD
#include "Arduino.h"
class charLCD
{
public:
charLCD(int pin1,int pin2,int pin3,int pin4,int enable);
void sendChar(unsigned char c);
private:
int _pin1;
int _pin2;
int _pin3;
int _pin4;
int _enable;
};
#endif
charLCD.cpp:
#include "Arduino.h"
#include "charLCD.h"
#include <limits.h>
charLCD::charLCD(int pin1,int pin2,int pin3,int pin4,int enable) {
_pin1 = pin1;
_pin2 = pin2;
_pin3 = pin3;
_pin4 = pin4;
_enable = enable;
}
void sendChar(unsigned char c) {
// Send char to item
}
char* chartobin ( unsigned char c )
{
static char bin[CHAR_BIT + 1] = {0};
int i;
for ( i = CHAR_BIT - 1; i >= 0; i-- )
{
bin[i] = (c % 2) + '0';
c = c/2;
}
return bin;
}
The problem is on the line where I define the constructor in the header.
Because of
#define charLCD
this is what your compiler sees:
class
{
public:
(int pin1,int pin2,int pin3,int pin4,int enable);
void sendChar(unsigned char c);
private:
int _pin1;
int _pin2;
int _pin3;
int _pin4;
int _enable
};
::(int pin1,int pin2,int pin3,int pin4,int enable) {
_pin1 = pin1;
_pin2 = pin2;
_pin3 = pin3;
_pin4 = pin4;
_enable = enable;
}
// ...
Pick a better header guard.
You also need to qualify the definitions of member functions:
void charLCD::sendChar(unsigned char c) {
// Send char to item
}
My MCVC is compiling but is not functioning as intended. The goal is a genetic algorithm that performs the basics i.e. crossover,mutation,evolution. In the code I have provided should print out the good job statements but thats not the case. I am a new programmer, sorry.
My questions are:
1) The cpu and ram are rev'ed up, is this array declaration and implementation the cause for the uncontrolled spike?
std::array<std::auto_ptr<Individual>,50>myarray;
2) Is my 2.53 GHz Intel Core 2 Duo not up for it?
3) Should I cut down the amount of loops?
Any help is always welcomed !
Individual.h
#include <stdio.h>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <array>
#include <iostream>
class Individual
{
public:
inline int getRandomNumber(int min = 0, int max = 1)
{
srand(static_cast<unsigned int>(time(0)));
static const double fraction = 1.0 / (static_cast<double>(RAND_MAX) + 1.0);
return static_cast<int>(rand() * fraction * (max - min + 1) + min);
}
private:
int defaultGeneLength = 64;
std::vector<char>genes;
int fitness = 0;
public:
Individual()
{
std::cout<<"Good Job";
}
//setters and getters
void generateIndividual();
void setDefaultGeneLength(int length);
char getGene(int index);
void setGene(int index, char value);
//public methods
unsigned int size();
int getFitness();
std::string toString();
};
Individual.cpp
#include "Individual.h"
void Individual::generateIndividual()
{
for (int i = 0; i < size(); i++)
{
genes.push_back(getRandomNumber());
}
}
//setters and getters
void Individual::setDefaultGeneLength(int length)
{
defaultGeneLength = length;
}
char Individual::getGene(int index)
{
return genes.at(index);
}
void Individual::setGene(int index, char value)
{
genes[index] = value;
fitness = 0;
}
//public methods
unsigned int Individual::size()
{
return genes.max_size();
}
int Individual::getFitness()
{
if(fitness == 0)
{
fitness = 1;
} return fitness;
}
std::string Individual::toString()
{
std::string geneString = "";
for (int i = 0; i < size(); i++)
{
geneString.append(getGene(i),1);
}
return geneString;
}
Population.h
#include "Individual.h"
class Population
{
std::array<std::auto_ptr<Individual>,50>myarray;
public:
Population(int populationSize, bool initialise)
{
std::cout<<"Good Job2";
if(initialise)
{
for (int i = 0; i < populationSize; ++i)
{
std::auto_ptr<Individual>newIndividual(new Individual());
myarray.at(i) = newIndividual;
myarray.at(i)->generateIndividual();
saveIndividual(i,*(myarray.at(i)));
}
}
std::cout<<"Good Job 3";
}
Individual getIndividual(int index);
Individual getFittest();
unsigned long size();
void saveIndividual (int index, Individual indiv);
~Population()
{
}
};
Population.cpp
#include "Population.h"
Individual Population::getIndividual(int index)
{
return *myarray.at(index);
}
Individual Population::getFittest()
{
Individual fittest = *myarray.at(0);
for (int i = 0; i < myarray.max_size(); i++)
{
if (fittest.getFitness() <= getIndividual(i).getFitness())
{
fittest = getIndividual(i);
}
}
return fittest;
}
unsigned long Population::size()
{
return myarray.max_size();
}
void Population::saveIndividual (int index, Individual indiv)
{
*myarray.at(index) = indiv;
}
Main.cpp
int main(int argc, const char * argv[]) {
Population *mypop = new Population(2,true);
delete mypop;
mypop = nullptr;
return 0;
}
unsigned int Individual::size()
{
return genes.max_size();
}
Your genes is a:
std::vector<char> genes;
The C++ standard defines std::vector::max_size() as follows:
distance(begin(), end()) for the largest possible container
It is not specified what "largest possible container" means. "Possible" could mean anything, like, if the system had a ten terabyte hard drive, so that the operating system could use the entire hard drive to page its virtual memory address space. That's certainly "possible", in some sense of the word. But it goes without saying that paging out ten terabytes will take a while.
With 64 bit gcc, the following simple program:
#include <iostream>
#include <vector>
int main()
{
std::vector<char> c;
std::cout << c.max_size() << std::endl;
return 0;
}
Produces the following output:
18446744073709551615
However, my chances of being able to actually create a vector of such size are not very good.
But let's get back to your code:
void Individual::generateIndividual()
{
for (int i = 0; i < size(); i++)
{
genes.push_back(getRandomNumber());
}
}
Ok. You must be feeling quite lucky. You believe that it will be possible for you to create a vector<char> that's max_size() big.
Are you quite sure about that?
I'm somewhat skeptical.
Since I cannot answer my own question in 8 hours after asking, I'm posting my solution here.
Made some mistakes in the incoming channel number and number of the vector element. Setting the value of channel-1 instead of channel fixed to problem.
My new function is as follows:
void input(long inlet, t_symbol *s, long ac, t_atom *av){
// GET VARIABLES
long channel = atom_getlong(av);
double value = atom_getfloat(av + 1);
long v_size = v_chan.size();
if(channel && v_size < channel){
for(int i = v_size; i < channel; i++){
v_chan.push_back(n_chan);
}
v_chan[channel - 1].value = value;
}
else if(channel){
v_chan[channel - 1].value = value;
}
}
I've got a vector containing structs, which I like to push_back with a new, empty struct.
Example code:
struct channels{
double value;
// eventually more variables
};
vector<channels> v_chan;
channels n_chan;
void push(){
v_chan.push_back(n_chan);
}
The problem is, if my vector contains elements, push_back add an element, but also overwrites the last element.
For example, if my vector size is 1 and element 0 has a value of 0.2, after push_back my vector size is 2, but element 0 and 1 have a value of 0.
What am I doing wrong here?
Real Code: (MAX/MSP external, function input is called in Max)
#include <maxcpp6.h>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
struct bind{
string param;
double* value;
int track;
double base;
double multiplier;
};
struct channels{
double value;
vector<int> bind;
};
vector<channels> v_chan;
vector<bind> v_bind(19);
channels n_chan;
class rec : public MaxCpp6<rec> {
public:
rec(t_symbol * sym, long ac, t_atom * av) {
setupIO(1, 1); // inlets / outlets
}
~rec() {}
// methods:
//SET BIND FUNCTION
void setBind(long inlet, t_symbol *s, long ac, t_atom *av){
}
void output(long track, long type){
}
void input(long inlet, t_symbol *s, long ac, t_atom *av){
// GET VARIABLES
long channel = atom_getlong(av);
double value = atom_getfloat(av + 1);
long v_size = v_chan.size();
if(v_size <= channel){
v_chan.push_back(n_chan);
}
else{
v_chan[channel].value = value;
}
}
void dump(long inlet){
for(int i = 1; i <= v_chan.size(); i++){
post("%d %.2f", i, v_chan[i].value);
}
}
void clearTrackBinds(long inlet){
}
void reset(long inlet){
clearTrackBinds(0);
}
};
C74_EXPORT int main(void) {
// create a class with the given name:
rec::makeMaxClass("solar_receiver");
REGISTER_METHOD_GIMME(rec, input);
REGISTER_METHOD_GIMME(rec, setBind);
REGISTER_METHOD(rec, dump);
REGISTER_METHOD(rec, clearTrackBinds);
REGISTER_METHOD(rec, reset);
}