Change variable at array index, not the actual list - c++

Somewhere in my code I have the following:
_buttonStates[0] = _upButtonState; _buttonStates[1] = _leftButtonState;
is there a way to do this:
buttonStates[0] = true;
changing the variable _upButtonStates, instead of replacing it with the value 'true'?
I am doing the following:
for(int i = 0; i < sizeof(_buttons)/sizeof(_buttons[0]); i++){
if(_buttonStates[i] != digitalRead(_buttons[i])){
_stateChanged[i] = true;
_buttonStates[i] = digitalRead(_buttons[i]);
}
else{
_stateChanged[i] = false;
}
But later references to '_upButtonState' end up being outdated.
How do I change the value of a variable in the list instead of overwriting it when accessing it via its index?

You are passing the literal values in now; you want to store pointers (memory addresses of the variables) in the array instead.
Example

Related

Is this allowed at runtime? How do you extract the top N elements of a stack-like thing?

I'm trying to do something like this - copy the top N elements of the stack to an array. I want to use it to define the invokevirtual, invokespecial, invokestatic, invokeinterface, and invokedynamic instructions for a Java Ahead-Of-Time Compiler. The stack is a linked list and __pop() unwinds and returns the top of the stack.
public : void __sipop(){
topframe = topframe->prev;
}
public : void __longpop(){
topframe = topframe->prev->prev;
}
public : jvalue __pop(){
//also shared with bytecode
jvalue value = topframe->value;
if(topframe->type == 'J' || topframe->type == 'D'){
__longpop();
} else{
__sipop();
}
return value;
}
public : jvalue* __extract(int count){
jvalue extracted [count];
for(int i = 0; i < count; i++){
extracted[count - i - 1] = __pop();
}
return extracted;
}
Will my implementation crash at runtime?
Will my implementation crash at runtime?
Maybe. You exhibit Undefined Behaviour at least in:
jvalue* __extract(int count){
jvalue extracted [count];
for (int i = 0; i < count; i++){
extracted[count - i - 1] = __pop();
}
return extracted;
}
Your function returns a pointer to a local variable whose lifetime ends as the function returns. For additional information, you should read this excellent answer on Sotack Overflow: Can a local variable's memory be accessed outside its scope? (tl; dr: no).
The simplest solution would be to return a vector:
#include <vector> // preferably in the first lines of your header file (.hpp)
std::vector<jvalue> extract(int count)
{
auto extracted = std::vector<jvalue>(count);
for (int i = 0; i < count; i++) {
extracted[count - i - 1] = __pop();
}
return extracted;
}
You may also be interested by std::generate.
Additionally, as mentioned in the comments, names staring by two underscores (__) are reserved to the implementation.
Unrelated note, I understand your wish to feel comfortable in C++ by mimicking aspects of the Java language, but you should write idiomatic C++ and not repeat the access modifier (public) before each member function.
Yes. Returning the address of a stack-local object (extracted) is undefined behavior. Return a heap-allocated array (auto extracted = new jvalue[count];) or std::vector<jvalue> instead.

swig perl typemap(out) std::vector<std::string> doesn't return the desired output in perl

I am trying to type a typemap(out) std::vector.
I want it to get to the perl code as an array instead I am getting an array of arrays which after a double dereference contains the desired data.
how can I make it an array of strings in perl?
I have tried to edit the typemap myself and to use the typemaps in the "std_vector.i" and in "std_string.i" without editing and they all give the same results.
this is the typemap code:
%typemap(out) std::vector<std::string> {
int len = $1.size();
SV *svs = new SV[len];
for (int x = 0; x < len; x++) {
SV* sv = sv_newmortal();
sv_setpvn(sv, $1[x].data(), $1[x].size());
svs[x] = SvPV(sv, $1[x].size());
}
AV *myav = av_make(len, svs);
delete[] svs;
$result = newRV_noinc((SV*) myav);
sv_2mortal($result);
argvi++;
}
my code for testing the output:
#this return a std vector<string> in the cpp code
my #commitReturn = $SomeClass->commit();
print "\n";
#this should return a string instead it returns an array.
print $commitReturn[0];
print "\n";
#this should not work, instead it returns the desired output.
print $commitReturn[0][0];
the output is:
ARRAY(0x908c88)
20790
instead of:
20790
Can't use string ("20791") as an ARRAY ref while "strict refs"
Your commit method is just returning an array reference, not an array of array references. Maybe it looks like an array of array references because you are assigning the result to an array?
In any case, without touching the typemap code, you can dereference the function call
#commitReturn = #{$SomeClass->commit()};
or create a wrapper method to dereference it for you
package SomeClass;
...
sub commit_list {
my $self = shift;
#{$self->commit()};
}
...
#commitReturn = $SomeClass->commit_list();
To return an array instead of a reference to an array, you have to manipulate the stack such that Perl knows that more than one scalar is returned.
According to the documentation:
The current value of the argument stack pointer is contained in a
variable argvi. Whenever a new output value is added, it is critical
that this value be incremented. For multiple output values, the final
value of argvi should be the total number of output values.
So the following typemap should be sufficient:
%typemap(out) std::vector<std::string> {
int len = $1.size();
for (int x = 0; x < len; x++) {
$result = sv_newmortal();
sv_setpvn($result, $1[x].data(), $1[x].size());
argvi++;
}
}

I need to update a Vector of pointers in C++ in a unique way

So I have a vector of pointers to a class I defined. I have a function that takes the 0 index of the pointer and returns it. After that I need to remove the data in that index then take the item in the last index of the vector and put it into the 0 index. As of right now I am just setting the pointers to NULL if I return them, and then I pushback the final object in the vector and finally pop it back. I am not sure if this method is the best way of solving my issue. Here is my code though:
Instrument* loanOut() {
for (int i = 0, i < library.size(), i++) {
if (library[i] != NULL) {
return library[i];
}
else {
return NULL;
}
}
library[0] = NULL;
library.push_back(library[library.size()]);
}
Algorithmically, this is what you are describing :
Object PopFrontAndReplace(std::vector<Object>& objects) {
if (!objects.size()) {return Object();}
Object o = objects[0];
objects[0] = objects.back();
objects.pop_back();
return o;
}
Does that answer the question?

Values being overwritten in array of pointers

I'm Java guy trying to solve discrete knapsack problem in c++. However, I'm having trouble with pointers. I have an object with a field
Item ** items;
representing array of items to choose from. I also created a method to add an item which works like insertion sort (at least I hope so).
void Knapsack::addItem(Item item) {
int k = itemCount - 1;
if (this->items[k] != NULL) {
return;
}
while (k > 0 && this->items[k - 1] == NULL) {
k--;
}
if (k == 0) {
this->items[0] = &item;
} else {
int i = 0;
while (i < k && item < *(this->items[i])) {
i++;
}
for (int n = k; n > i; n--) {
this->items[n] = this->items[n - 1];
}
this->items[i] = &item;
}
}
Later, in my main I invoke the method by
knapsack->addItem(*(new Item(values.at(0), values.at(1))));
values being a vector of ints. The method itself seems to work fine, however, debugger shows that everytime I invoke the method with new Item, the previous values already put in my array are set to the same values as the new item.
(ex. if items[0] has value of 5, and I invoke the method with an item valued as 10, the items[0] instantly is set to 10).
Why are the values overwritten? I am creating a new object everytime I invoke the method.
EDIT:
Problem was fixed by replacing
this->items[0] = &item;
this->items[i] = &item;
with
this->items[0] = new Item(item.getWeight(), item.getValue());
this->items[i] = new Item(item.getWeight(), item.getValue());
SECOND EDIT:
The answer shows better (and probably correct) way to do this. Now the function takes a pointer instead of an object.
void Knapsack::addItem(Item * item);
this->item[i] = item;
knapsack->addItem(new Item(values.at(0), values.at(1)));
You are storing a pointer to a temporary copy of an Item object in the array in your addItem function, once the function returns the temporary object will be destroyed and you will be left with an invalid pointer. Make sure to allocate an Item object on the heap and passing a pointer to your addItem function or just use a vector of type std::vector<Item> and save your objects in there.

Copy elements of an old array of pointers into new array of pointers?

I need some assistance with a C++ project. What I have to do is remove the given element from an array of pointers. The technique taught to me is to create a new array with one less element and copy everything from the old array into the new one except for the specified element. After that I have to point the old array towards the new one.
Here's some code of what I have already:
I'm working with custom structs by the way...
Data **values = null; // values is initialized in my insert function so it is
// populated
int count; // this keeps track of values' length
bool remove(Data * x) {
Data **newArray = new Data *[count - 1];
for (int i = 0; i < count; i++) {
while (x != values[i]) {
newArray[i] = values[i];
}
count -= 1;
return true;
}
values = newArray;
return false;
}
So far the insert function works and outputs the populated array, but when I run remove all it does is make the array smaller, but doesn't remove the desired element. I'm using the 0th element every time as a control.
This is the output I've been getting:
count=3 values=[5,6,7] // initial insertion of 5, 6, 7
five is a member of collection? 0
count=3 values=[5,6] // removal of 0th element aka 5, but doesn't work
five is a member of collection? 0
count=4 values=[5,6,5] // re-insertion of 0th element (which is stored in
five is a member of collection? 0 // my v0 variable)
Could anyone nudge me in the right direction towards completing this?
First of all, your code is leaking memory like no good! Next you only copy the first element and not even that if the first element happens to be the one you want to remove. Also, when you return from your function, you haven't changed your internal state at all. You definitely want to do something along the lines of
Data** it = std::find(values, values + count, x);
if (it != values + count) {
std::copy(it + 1, values + count, it);
--count;
return true;
}
return false;
That said, if anybody taught you to implement something like std::vector<T> involving reallocations on every operation, it is time to change schools! Memory allocations are relatively expensive and you want to avoid them. That is, when implementing something like a std::vector<T> you, indeed, want to implement it like a std::vector<T>! That is you keep an internal buffer of potentially more element than there are and remember how many elements you are using. When inserting a new element, you only allocate a new array if there is no space in the current array (not doing so would easily result in quadratic complexity even when always adding elements at the end). When removing an element, you just move all the trailing objects one up and remember that there is one less object in the array.
Try this:
bool remove(Data * x)
{
bool found = false;
// See if x is in the array.
for (int i = 0; i < count; i++) {
if (x != values[i]) {
found = true;
break;
}
}
if (!found)
{
return false;
}
// Only need to create the array if the item to be removed is present
Data **newArray = new Data *[count - 1];
// Copy the content to the new array
int newIndex = 0;
for (int i = 0; i < count; i++)
{
if (x != values[i])
newArray[newIndex++] = values[i];
}
// Now change the pointers.
delete[] values;
count--;
values = newArray;
return true;
}
Note that there's an underlying assumption that if x is present in the array then it's there only once! The code will not work for multiple occurrences, that's left to you, seeing as how this is a school exercise.