Copy an array into another array - arduino

char arrA[ 6 ] = { 1, 2, 3, 4, 5, 0 };
char arrB[ 6 ] = {};
void setup(){
strcpy( arrB, arrA );
}
Hi all, I obtained the code above from here. My case is I need to use int arrA[6] instead of char arrA[6] when initializing variables so that it remains as values and not string. May I ask how do I actually accomplish it with arduino code. The link above only uses string as array and not numbers. Thank you for reading and have a nice day !!!

You can write a for loop to copy the contents of arrA to arrB.
int arrA[ 6 ] = { 1, 2, 3, 4, 5, 0 };
int arrB[ 6 ];
void setup(){
for(int i = 0; i < (sizeof(arrA)/sizeof(arrA[0])); i++)
{
arrB[i] = arrA[i];
}
}

Related

Arduino is giving a weird output when using toInt()

I'm trying to convert a string to an integer (which is actually a binary number) so that I can output the DEC value, but where the answer SHOULD be 63 (00111111), it's giving me -19961 as an output? It would be great if someone can help me correctly convert the string to an int :)
// C++ code
//
const int button = 13;
int buttonPressed = 0;
int counter = 0;
int myInts[] = {0, 0, 1, 1, 1, 1, 1, 1};
void setup()
{
Serial.begin(9600);
pinMode(button, INPUT);
}
void loop()
{
buttonPressed = digitalRead(button);
if (buttonPressed == HIGH){
counter = count();
//rial.println(counter);
}
else{
Serial.println("Button not pressed");
}
delay(1000);
}
int count()
{
String myString = ""; //Empty string for constructing
int add = 0;
int i = 0;
//Should add all the values from myInts[] into a string
while(i < 8){
myString = String(myString + myInts[i]);
Serial.println(add);
delay(1000);
add++;
i++;
}
Serial.println(myString);
int myNumber = myString.toInt(); //Convert the string to int
Serial.println(myNumber, DEC); //Should print 63 in this case
return add;
}
Your code currently does the following:
Concatenates all your integers together to make a string "00111111"
Attempts to convert it (as a string holding a base 10 integer) to the integer 111,111 (one hundred eleven thousand, one hundred eleven)
Hits integer overflow. The range of an Arduino int is -32768 to 32767 (65536 possible values), so the number you really have is 111111 - 2*65536 = -19961.
I don't believe that there's an overload of Arduino's ToInt that converts a binary string to an integer. Depending on the C++ support in Arduino, you may be able to use std::stoi as described here.
Instead, you may choose to do the conversion yourself - you can keep track of a number sum, and at each loop iteration, double it and then add the next bit:
int sum = 0;
for(int i = 0; i < 8; i++) {
sum *= 2;
sum += myInts[i];
// print and delay if you want
}
Over the eight iterations, sum ought to have values 0, 0, 1, 3, 7, 15, 31, and finally 63

PROTECTing elements in VECSXP

In the "Writing R Extensions" manual it says
Protecting an R object automatically protects all the R objects pointed to in the
corresponding SEXPREC, for example all elements of a protected list are automatically
protected.
Does this mean that I do not need to protect individual SEXP elements of a VECSXP. For example consider the following which contains two methods that I hope illustrate where I need clarification:
#include <Rinternals.h>
#include <R.h>
SEXP copy_int_vec(int *x, int size) {
SEXP ans = allocVector(INTSXP, size);
PROTECT(ans);
int *pans = INTEGER(ans);
for (int i = 0; i < size; i ++) {
pans[i] = x[i];
}
UNPROTECT(1);
return ans;
}
// method 1 - protect VECSXP when allocated BUT NOT individual array entries
SEXP method_one() {
// setup for rep example
int N = 3;
int *graph[N];
int tmp1[3] = {1, 2, 3};
int tmp2[4] = {1, 2, 3, 4};
int tmp3[2] = {3, 4};
graph[0] = tmp1;
graph[1] = tmp2;
graph[2] = tmp3;
int neighbours[3] = {3, 4, 2};
// method
SEXP ans = allocVector(VECSXP, N);
PROTECT(ans);
for (int i = 0; i < N; i++){
SET_VECTOR_ELT(ans, i, copy_int_vec(graph[i], neighbours[i]));
}
UNPROTECT(1);
return ans;
}
// method 2 - protect VECSXP when allocated AND ALSO individual array entries
SEXP method_two() {
// setup for rep example
int N = 3;
int *graph[N];
int tmp1[3] = {1, 2, 3};
int tmp2[4] = {1, 2, 3, 4};
int tmp3[2] = {3, 4};
graph[0] = tmp1;
graph[1] = tmp2;
graph[2] = tmp3;
int neighbours[3] = {3, 4, 2};
// method 2
SEXP ans = allocVector(VECSXP, N);
PROTECT(ans);
for (int i = 0; i < N; i++){
SEXP tmp = copy_int_vec(graph[i], neighbours[i]);
PROTECT(tmp);
SET_VECTOR_ELT(ans, i, tmp);
}
UNPROTECT(N + 1);
return ans;
}
I'm hoping the answer is the first method but would appreciate clarification.
I believe method_one is fine.
To do the analysis, you need to know every point in your code that does allocations, because an allocation might trigger garbage collection, and that will release any unprotected object.
So stepping through method_one:
SEXP method_one() {
// setup for rep example
int N = 3;
int *graph[N];
int tmp1[3] = {1, 2, 3};
int tmp2[4] = {1, 2, 3, 4};
int tmp3[2] = {3, 4};
graph[0] = tmp1;
graph[1] = tmp2;
graph[2] = tmp3;
int neighbours[3] = {3, 4, 2};
None of the code above uses R's allocator; those allocations are all on the C stack, so they are safe.
// method
SEXP ans = allocVector(VECSXP, N);
PROTECT(ans);
This does an R allocation, and then immediately protects it. A more common way to write this is
SEXP ans;
PROTECT(ans = allocVector(VECSXP, N));
which makes it harder to mess things up by inserting a statement in between the allocation and protection.
for (int i = 0; i < N; i++){
SET_VECTOR_ELT(ans, i, copy_int_vec(graph[i], neighbours[i]));
}
The copy_int_vec does allocations, so garbage collection could occur in any step of this loop. However, the allocated object is immediately assigned into ans, so each one is protected and safe.
UNPROTECT(1);
Nothing is protected now; remember not to insert any code before the return.
return ans;
}

Longest Increasing Subsequence Recursive version

Traditional Longest Increasing Subsequence problem.
This is recursion version ( not DP version )
I realized that version1 code had a bug, so I changed it to version2.
I don't clearly understand why version2 works and version1 has a bug for input A0
Please see version 1 and version2 below:
static int lis1(int[] v) {
int maxLen = 1;
for(int i = 1; i < v.length; i++) {
List<Integer> w = new ArrayList<Integer>();
for( int j = 0; j < i; j++) {
if( v[j] < v[i] ) {
w.add(v[j]);
}
}
// it used to be the following one line which has bug for input A0
//cand = lis1(l2a(w)) + 1; // version1
// so I changed it to the following, but can't clearly understand why it works.
// without this part, it has but for input A0
int cand = 1; // version2
if(v[i-1] < v[i])
cand = lis1(l2a(w)) + 1;
else
cand = lis1(l2a(w));
maxLen = Math.max(maxLen, cand);
}
return maxLen;
}
public static void main(String[] args) {
int[] A0 = {3, 2, 5, 6}; // for this input version1 had a bug which printed out 4 ( instead of 3 )
int[] A1 = {1, 2, 3, 3, 2, 4, 6, 7}; // 6
int[] A2 = { 10, 22, 9, 33, 21, 50, 41, 60, 80 }; // 6
int[] A3 = { 5, 0, 4, 2, 3, 7, 1 }; // 4
int[] A4 = { 2, 7, 3, 4, 9, 8, 12 }; // 5
int[] A5 = {3, 4, 2, 5 }; // 3
Actually... neither of your version works. Try putting A0={3,2,7,6}, your v2 returns 2, obviously wrong.
As for v1, for v={3,2} the answer should be 1, right? Let's see what your code does. When index i=1, your w after inner for loop equals {}. Then you made a recursive call to w={}, which should've returned 0, but it returns 1. Why, because of your maxlen variable, which is wrongly initialized with 1. This error propagates to entire {3,2,5,6} and gives wrong answer.
v2 accidentally solves this problem because your if condition then fails (3<2), and it returns the previously returned 1.
Just delete entire version 2, correct maxlen initialization. And start outer loop for(int i = 1; i < v.length; i++) with i=0, else you will get 0 for single-element array.
static int lis1(int[] v) {
int maxLen = 0;
for(int i = 0; i < v.length; i++) {
List<Integer> w = new ArrayList<Integer>();
for( int j = 0; j < i; j++) {
if( v[j] < v[i] ) {
w.add(v[j]);
}
}
cand = lis1(l2a(w)) + 1; // version1
maxLen = Math.max(maxLen, cand);
}
return maxLen;
}

genie HashTable of string, STRUCT

NOTE: my question is array, not [ Array or GenericArray ]
this is my code:
init
var h = new HashTable of string, Int? (str_hash, str_equal)
h["a"] = Int ({1, 2, 3})
h["b"] = Int ({5, 6, 7}) // HERE: WORKS FINE
// ERROR HERE:
// Array concatenation not supported for public array variables and parameters
h["a"].data += 4
struct Int
data: array of int
construct (a: array of int)
this.data = a
how to fix this?
Not really an answer, but an alternative way to express this:
init
var h = new HashTable of string, Int? (str_hash, str_equal)
h["a"] = Int ({1, 2, 3})
h["b"] = Int ({5, 6, 7})
h["a"].append ({4})
struct Int
data: array of int
construct (a: array of int)
this.data = a
def append (a: array of int)
this.data = this.data + a
Now there is no mixing of "variables and parameters" going on anymore, which solves the compiler error your original code is triggering.
The problem is that this also results in a compiler error:
resize_array.gs:14.21-14.33: error: Incompatible operand
this.data = this.data + a
Which can be simplified to this code:
init
x: array of int = {1, 2, 3}
y: array of int = {4, 5, 6}
z: array of int = x + y
Which also produces the same compiler error.
resize_array.gs:21.23-21.27: error: Incompatible operand
z: array of int = x + y
I have added a new question based on this:
How to concatenate two arrays?
As it turns out concating arrays (it works for string though!) is not a trivial task in Vala/Genie.
See the other question for solutions on how to do this.
I'd personally use Gee containers for this (if I don't have to frequently call some C functions that need a plain array).
The solution using Array of int:
init
var h = new HashTable of string, Int? (str_hash, str_equal)
h["a"] = Int ({1, 2, 3})
h["b"] = Int ({5, 6, 7})
h["a"].append ({4})
struct Int
data: Array of int
construct (a: array of int)
data = new Array of int;
append (a)
def append (a: array of int)
data.append_vals (a, a.length)
A bug of Genie? maybe?
I try that in Vala, Works fine.
The output:
1, 2, 3, 4, 55, 666,
struct Int {
int[] data;
Int(int[] a){
this.data = a;
}
}
void main(){
var h = new HashTable<string, Int?> (str_hash, str_equal);
h["a"] = Int({1, 2, 3});
h["b"] = Int({4, 5, 6});
h["a"].data += 4;
h["a"].data += 55;
h["a"].data += 666;
for (var i = 0; i < h["a"].data.length; i++) {
stdout.printf("%d, ", h["a"].data[i]);
}
}

Three statements within if

I'm currently working on a small Arduino project, and I'm kinda stuck. Here's my code so far:
#include "_init.h"
void setup() {
ds_init();
Serial.begin(9600);
randomSeed(analogRead(LIGHT_SENSOR_PIN));
int rol1[] = {1, 2, 3, 4, 5};
int rol2[] = {3, 5, 1, 2, 4};
int rol3[] = {5, 1, 4, 3, 2};
int rol1Mid = random(0, 5);
int rol1Bov = rol1Mid + 1;
int rol1Ond = rol1Mid - 1;
if (rol1Bov == 5){
rol1Bov = 0;
}
if (rol1Ond == -1){
rol1Ond = 4;
}
int rol2Mid = random(0, 5);
int rol2Bov = rol2Mid + 1;
int rol2Ond = rol2Mid - 1;
if (rol2Bov == 5){
rol2Bov = 0;
}
if (rol2Ond == -1){
rol2Ond = 4;
}
int rol3Mid = random(0, 5);
int rol3Bov = rol3Mid + 1;
int rol3Ond = rol3Mid - 1;
if (rol3Bov == 5){
rol3Bov = 0;
}
if (rol3Ond == -1){
rol3Ond = 4;
}
Serial.println(rol1[rol1Bov]);
Serial.println(rol1[rol1Mid]);
Serial.println(rol1[rol1Ond]);
Serial.println("----");
Serial.println(rol2[rol2Bov]);
Serial.println(rol2[rol2Mid]);
Serial.println(rol2[rol2Ond]);
Serial.println("----");
Serial.println(rol3[rol3Bov]);
Serial.println(rol3[rol3Mid]);
Serial.println(rol3[rol3Ond]);
if(rol1[rol1Mid] && rol2[rol2Mid] == rol3[rol3Mid]){
Serial.println("Yaay!");
} else {
Serial.println("Jammer, probeer het nogmaals.");
}
/*
if(rol1[positieBov] && rol2[positieBov] == rol3[positieBov]){
Serial.println("Yaay!");
} else {
Serial.println("Jammer, probeer het nogmaals.");
}
if(rol1[positieOnd] && rol2[positieOnd] == rol3[positieOnd]){
Serial.println("Yaay!");
} else {
Serial.println("Jammer, probeer het nogmaals.");
}
*/
}
void loop() {
// put your main code here, to run repeatedly:
}
Basically, I'm trying to create a slot machine. There's probably tons of things wrong with my code, but for the time being, I'm stuck on the if statement that checks if the user won or not.
I know I shouldnt be coding in the setup() part of Arduino, but as soon as this all works, I'm going to put it in a function in the loop(), where I will use my dangershield's buttons to operate the three roll's separately.
Okay, managed to fix it... I feel silly now
if(rol1[rol1Mid] == rol2[rol2Mid] && rol2[rol2Mid] == rol3[rol3Mid])

Resources