How can I return an array? - c++

Is there any way to return an array from a function? More specifically, I've created this function:
char bin[8];
for(int i = 7; i >= 0; i--)
{
int ascii='a';
if(2^i-ascii >= 0)
{
bin[i]='1';
ascii=2^i-ascii;
}
else
{
bin[i]='0';
}
}
and I need a way to return bin[].

You can't do that but you can:
return a dynamicaly allocated array - best owned by a smart pointer so that the caller does not have to care about deallocating memory for it - you could also return something like an std::vector this way.
populate an array/vector passed to you as an argument by pointer (suggested) or a non const reference.

Your array is a local variable allocated on the stack. You should use new [] to allocate it on the heap. Then you can just say: return bin;. Beware that you will have to explicitly free it with delete [] when you are done with it.

You are really asking the wrong question. If you want to do string processing in C++, use the std::string and/or std::vector classes, not arrays of char. Your code then becomes:
vector <char> func() {
vector <char> bin(8);
for( int i = 7; i >= 0; i-- ) {
int ascii='a';
if ( 2 ^ i - ascii >= 0 ) {
bin[i] = '1';
ascii = 2^i - ascii;
}
else {
bin[i] ='0';
}
}
return bin;
}

I think your best bet is to use a vector. It can function in many ways like an array and has several upsides (length stored with type, automatic memory management).
void Calculate( std::vector<char>& bin) {
for(int i = 7; i >= 0; i--)
{
int ascii='a';
if(2^i-ascii >= 0)
{
bin.push_back('1');
ascii=2^i-ascii;
}
else
{
bin.push_back('0');
}
}
}

If you want to return a copy of the array (might make sense for small arrays) and the array has fixed size, you can enclose it in a struct;
struct ArrayWrapper {
char _bin[8];
};
ArrayWrapper func()
{
ArrayWrapper x;
// Do your stuff here using x._bin instead of plain bin
return x;
}
Or just use a std::vector as has been already suggested.

Similar implemented to #ari's answer, i want to say there is already a boost solution, boost::array solving your problem:
boost::array<char, 8> f() {
boost::array<char, 8> bin;
for(int i = 7; i >= 0; i--) {
int ascii = 'a';
if(2 ^ i-ascii >= 0) {
bin[i] = '1';
ascii = 2 ^ i-ascii;
} else {
bin[i] = '0';
}
}
}
...
boost::array<char, 8> a(f());
[I'm not sure what you want to do with that algorithm though, but note that i think you want to do 1 << i (bit-wise shift) instead of 2 ^ i which is not exponentiation in C++.]
Boost array is a normal array, just wrapped in a struct, so you lose no performance what-so-ever. It will also be available in the next C++ version as std::array, and is very easy to do yourself if you don't need the begin()/size()/data()-sugar it adds (to be a container). Just go with the most basic one:
template<typename T, size_t S>
struct array {
T t[S];
T& operator[](ptrdiff_t i) { return t[i]; }
T const& operator[](ptrdiff_t i) const { return t[i]; }
};
But as usual, use the tools already written by other people, in this case boost::array. It's also got the advantage of being an aggregate (that's why it has no user declared constructor), so it allows initializing with a brace enclosed list:
boost::array<int, 4> a = {{ 1, 2, 3, 4 }};

you need to pass array bin as an argument in your function.
array always pass by address, therefore you dont need to return any value.
it will automatically show you all changes in your main program
void FunctionAbc(char bin[], int size);
void FuncationAbc(bin, size)
{
for(int i = 7; i >= 0; i--)
{
int ascii='a';
if(2^i-ascii >= 0)
{
bin[i]='1';
ascii=2^i-ascii;
}
else
{
bin[i]='0';
}
}
}

You'll want to pass by reference, as follows:
void modifyBin(char (&bin)[8])
{
/* your function goes here and modifies bin */
}
int main()
{
char bin[8];
modifyBin(bin);
/* bin has been updated */
return 0;
}

I think that everyone else answered this one... use a container instead of an array. Here's the std::string version:
std::string foo() {
int ascii = 'a';
std::string result("00000000");
for (int i=7; i>=0; --i) {
if (2^i-ascii >= 0) {
result[i] = '1';
ascii = 2^i-ascii;
}
}
return result;
}
I'm not really sure if 2^i-ascii is want you want or not. This will be parsed as (2 ^ (i - ascii)) which is a little strange.

Related

Arrays with unknown size on Arduino

I'm doing an Arduino project and I need to pass arrays with different sizes as parameter to my function.
The problem is that std::vector is not an option.
How can I do that?
The fallback is to pass a pointer to the first element in the array and the size:
void foo(int* arr, size_t size);
The reason for std::vector not being available on some platforms is that on some platforms dynamic allocations is a bad idea. However, once you are dynamically allocating arrays:
int* x = new int[42];
foo(arr,42); // array decays to pointer
delete[] x;
then you could as well use std::vector.
If std::vector is not available to you, then either search for an alternative (maybe this?) or write your own. The pointer + size approach is fragile and not recommended unless absolutely necessary. The power of std::vector is from the abstract concept to encapsulate the array, its size and capacity. Nobody can prevent you to apply that concept even if you cannot use std::vector.
In case you are talking about statically sized arrays, then thats not quite the use case for std::vector. You do not need dynamic allocation, and you can pass arrays by reference. I won't repeat here what you can find in this answer (std::array) or here (c-arrays).
Something like this should work
template<size_t N>
void DaFunction(std::array<int, N>& daArray)
you can do it without having to deal with memory allocation or pointers just by creating a string variable and a limited size array and then you start shifting
#include <Arduino.h>
class ArrayShifter
{
private:
// String Reservoire Tank
String _text;
// a fixed size array of 5 in my case (depending on the amount of data you expect)
String _viewPortArray[5];
int _size = 0;
// Methode to fill the array
bool shiftArray(int position);
public:
ArrayShifter(/* args */);
// Method that gets the text from Serial
String getSerialText();
// get data from the array
String getArrayData(int index);
// array size getter
int getSize();
//clear the array
void clearArray();
//remove item
void removeArrayItem(int index);
};
ArrayShifter::ArrayShifter(/* args */)
{
}
String ArrayShifter::getSerialText()
{
// lesteing to the serial and returning the value
_text = Serial.readString();
return _text;
}
bool ArrayShifter::shiftArray(int position)
{
/*Assuming that the data is comming separated with ";" for each row and ":" for each value
to optimize the size of array in this way :
name:value;age:value;gender:value;
*/
String text = getSerialText();
int index = 0;
_size = 0;
if (text.length() > 0) // text isn't empty
{
if (position <= 5) // if the data belongs to the first 5 range
{
for (int i = 0; i < 5; i++)
{
// get the index of our separator that we've chosed to be ";"
index = text.indexOf(";");
if (index > 0)
{
// index found
_size++;
// putting the value before ";" in the array
_viewPortArray[i] = text.substring(0, index);
// deleting the value from the tank
text = text.substring(index + 1);
}
}
}
else
{
_size = 0;
// to wich range the desired index belongs
unsigned int dataRange = ((position - position % 5));
int ghostIndex = 0;
// looping throught all ";" to get indexes
for (int i = 0; i < dataRange; i++)
{
ghostIndex = text.indexOf(";");
if (ghostIndex > 0)
{
_size++;
text = text.substring(ghostIndex + 1);
}
}
// grabing just 5 of the data
for (int i = 0; i < 5; i++)
{
if (ghostIndex > 0)
{
_size++;
_viewPortArray[i] = text.substring(0, ghostIndex);
text = text.substring(ghostIndex + 1);
}
// updating ghost index
ghostIndex = text.indexOf(';');
}
}
return true;
}
return false;
}
String ArrayShifter::getArrayData(int index)
{
// turn the roulette
if (shiftArray(index))
{
if (index <= 5)
{
// yes we have this
return _viewPortArray[index];
}
else
{
// but we have to put it in the range of 5
index = index - 5;
return _viewPortArray[index];
}
}
}
int ArrayShifter::getSize()
{
return _size;
}
void ArrayShifter::clearArray()
{
for(int i = 0 ; i <5 ; i ++)
{
_viewPortArray->remove(i);
_size = 0;
}
}
void ArrayShifter::removeArrayItem(int index)
{
_viewPortArray->remove(index);
_size--;
}
main class :
#include <Arduino.h>
#include <ArrayShifter.h>
ArrayShifter array;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while (!Serial){}
}
void loop() {
if(Serial.available()>0)
{
Serial.println(array.getArrayData(7));
int sizeOption2 = array.getSize();
Serial.println(sizeOption2);
array.removeArrayItem(7);
Serial.println(array.getArrayData(7));
}
}
please check my github repository
https://github.com/Riadam/ViewPort-Array-Shifter-for-Arduino-Uno.git

C++ Initialise array size after declaration?

This is for an assignment so I'm restricted to what operators, etc. I can use. I can't use vectors.
My program takes an input of a maze and solves it.
Originally I had this array bring used:
Crumb* crumbs[MAX_SIZE];
The maze was originally a fixed-sized and we, therefore, could initialise the crumbs array to it's max possible size. However, now we have to change it so that the maze is dynamically sized and we also have to dynamically assign memory using the 'new' operator (and delete).
We've been told to change the above code to:
Crumb** crumbs;
I'm now not really sure how to fix up my class to use this new declaration. The below code is my full class that handles the array (which is an array of Crumb objects);
Trail::Trail() {
}
Trail::~Trail() {
}
int Trail::size() {
return length;
}
Crumb* Trail::getPtr(int i) {
return crumbs[i];
}
void Trail::addCopy(Crumb* t) {
crumbs[length] = new crumb(*t);
length++;
}
bool Trail::contains(int x, int y) {
bool contains = false;
for(int i = 0; i < length; i++){
if(crumbs[i]->getX() == x && crumbs[i]->getY() == y){
contains = true;
}
}
return contains;
}
bool Trail::containsStale(int x, int y) {
bool contains = false;
for(int i = 0; i < length; i++){
if(crumbs[i]->getX() == x && crumbs[i]->getY() == y){
if(crumbs[i]->isStale() == true){
contains = true;
}
}
}
return contains;
}
I've handled reading the input and the size, so at this point of calling on this class I know the size of the maze, I'm just not sure how to now intialise and use the crumbs array.
C++ Initialise array size after declaration?
You cannot. The size of an array variable must be known when declared.
Simply allocate a dynamic array instead. Simplest solution is to use std::vector, but if you cannot use it, then implement your own vector class.

Dynamically Set Array Size C++

I don't know any C++ at all but I am trying to make a very small update to a C++ library that my application is using. Before I start hacking away at this, I am hoping someone can tell me the proper syntax for the following:
I have the following lines of code:
#define A_NUMBER 100
#define ANOTHER_NUMBER 150
enum {
type1,
type2,
};
static int someMethod(int type)
{
char command[A_NUMBER];
//...more code
}
What I need to be able to do is based on the type argument (type1 or type2) I need to be able to set the size of the array to be either A_NUMBER or ANOTHER_NUMBER.
In pseudo code it would be something like:
if (type == type1) {
char command [A_NUMBER]
}
else if (type == type2) {
char command [ANOTHER_NUMBER]
}
Is there a way to dynamically define the size?
Yes, you can use an std::vector<char>:
if (type == type1) {
std::vector<char> x(A_NUMBER);
} else if (type == type2) {
std::vector<char> x(ANOTHER_NUMBER);
}
Remember to include the header with:
#include <vector>
While your example code matches the "pseudo code" in the question, I think part of the question is how to decide the size via type and then use the resulting storage unconditionally, i.e. outside the conditional blocks.
Then it gets as simple as:
std::vector<char> x;
if (type == type1) {
x.resize(A_NUMBER);
} else if (type == type2) {
x.resize(ANOTHER_NUMBER);
}
I believe this is what you want
std::vector<char> x; // x is empty, with size 0
if (type == type1) {
x.resize(A_NUMBER); // change size to A_NUMBER
} else if (type == type2) {
x.resize(ANOTHER_NUMBER); // change size to ANOTHER_NUMBER
}
Yes and no. In standard C++, you cannot keep the array on the stack and have its size determined in runtime.
However, you can turn the array into a dynamically-allocated one (i.e. on the heap). In C++, the standard way to do this is to use std::vector:
std::vector<char> command(A_NUMBER); // or ANOTHER_NUMBER
Indexing will work just as before: command[5]
However, if you need to pass the array to something which expects a C-style array (i.e. a char *), you'll have to use one of these:
command.data(); // if your compiler supports C++11
&command[0]; // if it does not
And of course, to use std::vector, you'll have to #include <vector>.
Here's an example that works in C and C++:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
char *opt;
if(argc == 2) {
opt = *++argv;
}
else {
printf("Usage: %s [small|large]\n", *argv);
return EXIT_FAILURE;
}
int *arr;
int arrlen = 0;
if (strcmp(opt, "small") == 0) {
arrlen = 3;
arr = (int *) malloc(arrlen*sizeof(int));
int i;
for(i = 0; i < arrlen; i++)
arr[i] = i+1;
}
else if (strcmp(opt, "large") == 0) {
arrlen = 5;
arr = (int *) malloc(arrlen*sizeof(int));
int i;
for(i = 0; i < arrlen; i++)
arr[i] = i+1;
}
if (arrlen > 0) {
int i;
for(i = 0; arr[i]; i++)
printf("%i, ", arr[i]);
printf("\n");
free(arr);
}
return EXIT_SUCCESS;
}
Example:
[gyeh#gyeh stackoverflow]$ ./dynarr
Usage: ./dynarr [small|large]
[gyeh#gyeh stackoverflow]$ ./dynarr small
1, 2, 3,
[gyeh#gyeh stackoverflow]$ ./dynarr large
1, 2, 3, 4, 5,
The raw C++ way is new and delete
char * command = new char[A_NUMBER];
// and later delete it like this
delete[] command;
Of course you'll have to manage the memory, and it is not recommended to use this approach because of many reasons you should be able to find online. So in conclusion... don't use this method if vector is an option
If using a big array the best way would be to use C++ vector, you could even consider other data structures like list based on your needs (for example a lot of insert, deletions operations on your array).

dynamic memory allocation with arrays in c++

I am trying to insert an int into an array that is in a class object, and I cannot figure out what I am doing wrong. The current state of my code never inserts the int into the array.
Basically what I am trying to do is when i call insert(int) it will check to to see if there is any room left in the array, and if there is it will add it, otherwise it would reallocate with 8 more spaces in the array.
here is some relevant class info
private:
unsigned Cap; // Current capacity of the set
unsigned Num; // Current count of items in the set
int * Pool; // Pointer to array holding the items
public:
// Return information about the set
//
bool is_empty() const { return Num == 0; }
unsigned size() const { return Num; }
unsigned capacity() const { return Cap; }
// Initialize the set to empty
//
Set()
{
Cap = Num = 0;
Pool = NULL;
}
here is the code i am working on
bool Set::insert(int X)
{
bool Flag = false;
if (Num == Cap)
{
//reallocate
const unsigned Inc = 8;
int * Temp = new int[Cap+Inc];
for (unsigned J=0;J<Num;J++)
{
Temp[J] = Pool[J];
}
delete [] Pool;
Pool = Temp;
Cap = Cap+Inc;
}
if(Num < Cap)
{
Pool[Num+1] = X;
Flag = true;
}
return Flag;
}
Your insert function never updates Num. Try Pool[Num++] = X; or something like that.
You probably want to increment the number of element but only after copying the new element in: the first element should have index 0. Basically, your insert() function should look something like this:
bool Set::insert(int X)
{
if (Num == Cap)
{
const unsigned Inc(std::max(8, 2 * Cap));
std::unique_ptr<int[]> Temp(new int[Cap+Inc]);
std::copy(Pool.get(), Pool.get() + Num, Temp.get());
Pool.swap(Temp);
Cap += Inc;
}
Pool[Num] = X;
++Num;
return true;
}
Of course, this assumes that Pool is reasonably declared as std::unique_ptr<int[]> (or something with similar functionality which is easy to write if necessary). The reason to use std::unique_ptr<int[]> rather than raw pointers is that they automatically clean up resources when they are destroyed. Copying a sequence of ints won't throw an exception but if int get's replaced by a std::string or a template parameters there is potential to throw exceptions.

Vectors of pointers to other vector's elements

EI have function which takes as parameter pointer to vector:
void Function(std::vector<type>* aa)
Now inside this function I want to filter out data from that vector to another vector and I want to change data of original vector by changing values of this temporary one. Damn it's hard to understand something like:
void Function(std::vector<type>* aa)
{
std::vector<type*> temp; //to this vector I filter out data and by changning
//values of this vector I want to autmatically change values of aa vector
}
I have something like that:
void Announce_Event(std::vector<Event>& foo)
{
std::vector<Event> current;
tm current_time = {0,0,0,0,0,0,0,0,0};
time_t thetime;
thetime = time(NULL);
localtime_s(&current_time, &thetime);
for (unsigned i = 0; i < foo.size(); ++i) {
if (foo[i].day == current_time.tm_mday &&
foo[i].month == current_time.tm_mon &&
foo[i].year == current_time.tm_year+1900)
{
current.push_back(foo[i]);
}
}
std::cout << current.size() << std::endl;
current[0].title = "Changed"; //<-- this is suppose to change value.
}
That does not change original value.
I think you may be having trouble communicating your intentions, so this calls for a psychic answer.
void Func(std::vector<type> & aa)
{
std::vector<type*> temp;
// I wish <algorithm> had a 'transform_if'
for(int i=0; i<aa.size(); ++i)
{
if( some_test(aa[i]) )
temp.push_back(&aa[i])
}
// This leaves temp with pointers to some of the elements of aa.
// Only those elements which passed some_test(). Now any modifications
// to the dereferenced pointers in temp will modify those elements
// of aa. However, keep in mind that if elements are added or
// removed from aa, it may invalidate the pointers in temp.
}
Do not use a pointer to a vector, use a reference instead:
void Function(std::vector<type>& aa)
inside the function you can now access the vectors contents as usual.
void Function(std::vector<type>& aa)
{
std::vector<type>& temp = aa;
// if you now append something to temp, it is also appended to aa
aa.push_back(type());
}
I don't know why you want two references to one vector, but hey, you asked :)
EDIT: removed typo, see comments. thanx
As an aside, start formatting your code better. Messy code is difficult to understand and makes it harder for you to figure out what you're trying to do.
This will do what you want:
void Oglos_Wydarzenie(std::vector<Wydarzenie>& zmienna)
{
std::vector<Wydarzenie *> obecne;
tm AktualnyCzas = {0,0,0,0,0,0,0,0,0};
time_t czas;
czas = time(NULL);
localtime_s(&AktualnyCzas,&czas);
for (unsigned i = 0; i < zmienna.size(); ++i) {
if (zmienna[i].dzien == AktualnyCzas.tm_mday &&
zmienna[i].miesiac == AktualnyCzas.tm_mon &&
zmienna[i].rok == AktualnyCzas.tm_year+1900)
{
obecne.push_back(&zmienna[i]);
}
}
std::cout << obecne.size() << std::endl;
obecne[0]->tytul = "Changed"; //<-- this is suppose to change value.
}
You could do this with all pointers and no references at all, but then it looks much more confusing:
void Oglos_Wydarzenie(std::vector<Wydarzenie>* zmienna)
{
std::vector<Wydarzenie *> obecne;
tm AktualnyCzas = {0,0,0,0,0,0,0,0,0};
time_t czas;
czas = time(NULL);
localtime_s(&AktualnyCzas,&czas);
for (unsigned i = 0; i < zmienna->size(); ++i) {
if ((*zmienna)[i].dzien == AktualnyCzas.tm_mday &&
(*zmienna)[i].miesiac == AktualnyCzas.tm_mon &&
(*zmienna)[i].rok == AktualnyCzas.tm_year+1900)
{
obecne.push_back(&((*zmienna)[i]));
}
}
std::cout << obecne.size() << std::endl;
obecne[0]->tytul = "Changed"; //<-- this is suppose to change value.
}