Using deque to insert unsigned char arrays - c++

I want to push_back two dimensional char arrays into deque. The following did not work. How should defined m_message data variable in order push_back those data.
unsigned char message_data[2][1500]; //definition
func1(message_data[0]);
func1(message_data[1]);
std::deque<unsigned char*> m_messagedata;
m_messagedata.push_back(&message_data[0]);
m_messagedata.push_back(&message_data[1]);

You're pushing back pointers, not arrays. If those arrays die, your pointers dangle. You didn't tell us what your problem is, but this is likely to be it.
Also you seem to be declaring two arrays with the same name, with different bounds, one of which is illegal (0). I presume that this was a mistake with your question, rather than your original code: please post your real testcase next time.
Nowadays, C++ has a wrapper around what were previously uncopyable arrays, allowing them to be stored directly inside standard containers; that wrapper is called std::array. So, try:
#include <array>
#include <deque>
typedef std::array<unsigned char, 1500> ArrayType;
int main()
{
std::array<ArrayType, 2> message_data;
std::deque<ArrayType> q;
q.push_back(message_data[0]);
q.push_back(message_data[1]);
}
Note that the container now contains copies of the two inner arrays.

The other solutions are right but since you want your code to remain the same as far as possible maybe you could do this:
unsigned char message_data[2][1500]; //definition
//using CharArrPtr = unsigned char(*)[1500];
typedef unsigned char (*CharArrPtr)[1500];
std::deque<CharArrPtr> m_messagedata;
m_messagedata.push_back(&message_data[0]);
m_messagedata.push_back(&message_data[1]);
As was mentioned earlier what is being done here is pushing pointers to possibly local variables. So you will have to be sure that they remain valid when they are used.

Related

How does one pass an integer, to a pointer, to an std::array<double, integer>, while satisfying a constnt expression?

I have a function noise.cpp which is currently of the form,
double* noise(int* steps, ...)
//some code
std::array<double, *steps> NoiseOut;
//rest of code
Which is being tested and accessed by cppnoise.cpp,
#include <random>
#include <cmath>
#include<stdio.h>
#include <iostream>
#include "noise.h"
main(){
double* out;
int steps = 8;
int* ptr = &steps;
out = noise(ptr, 1, 1000, 0.1, 1, 3);
printf("TEST \n");
std::cout << out[0];
}
With header file,
extern double* noise(int*, double, double, double, double, double);
Previously I accessed the noise.cpp function through Python where the NoiseOut array was initially, double* NoiseOut = new double[steps]; with desirable results, but this method resulted in a memory leak.
Initially I tried deleting the allocated memory. But the function returns NoiseOut, so I am not sure if that's possible? So, instead I found out that the modern way is to use std::array as it comes with some form of garbage collection. If I tried to do,
double* noise(int steps, ...)
std::array<double, steps> NoiseOut;
I was told steps was not a constant expression. I tried every which way of constexpr, const, and static but, with no success. Usually with the same error error: ‘steps’ is not a constant expression. Also, the reason I pass a pointer from cppnoise.cpp to noise.cpp is because I read somewhere that the pointer is easier to work with, later in compile-time? Such that maybe I could convert it to a constant expression? Probably a fever dream.
So, how can I declare an integer value in a program, which I pass to a function, which is usable in an std::array without causing that error?
NOTE: I am very new to c++ and work primarily with SQL, Python, R, and SageMath.
std::array is ill suited for this because you don't know what size you need until the code runs. std::array needs to know the size when it is compiled.
Using new gives a dynamic array size at run time, which is why you could use it before.
If you are concerned about memory leaks (or actually, in general), then I suggest using an std::vector instead:
#include <vector>
//...
std::vector<double> NoiseOut;
NoiseOut.reserve(*steps);
An std::vector should allow you to do most everything an std::array or C Array would allow you to so, though I suggest reading up on its documentation (linked above). Note that std::vector also comes with its own garbage collection of sorts in the same way std::array does.

Concatenation with arrays in C++?

#include <iostream>
using namespace std;
void mystrcat(char destination[], const char source[]){
int counter = 0;
while(source[counter] != '/0'){
destination += source[counter];
counter++;
}
destination += '/0';
}
int main(){
}
For my code, when I try to concatenate with the function mystrcat, my school's test bed says that there was a segmentation error. The purpose of my function is to concatenate while removing the NULL from the end of destination and adding it to the end of source. Is there a segmentation error because I am not removing NULL? If so, how do I access the last element of the array? The number of elements is unknown so I don't know if I can use pop_back. Thank you.
Edit:
#include <iostream>
using namespace std;
void mystrcat(char destination[], const char source[]){
int counter = 0;
int counter2 = 0;
while(destination[counter2] != '/0'){
counter2++;
}
while(source[counter] != '/0'){
destination[counter2 - 1] = source[counter];
counter++;
}
destination[counter] = '/0';
}
int main(){
}
is my edited code but now the testbed says that it is taking too long and crashes.
Arrays in C++ have an interesting property where they can easily decay to pointers.
destination += source[counter]; does not append source[counter] to the end of destination.
Instead, destination has decayed to a pointer and this operation is doing pointer arithmatic on destination.
Instead, you want to do destination[destinationLocation] = source[counter]; to actually set the character in destination.
Don't forget to set destination[end] = '\0'; at the end to null terminate the destination array.
One final thing to watch out for is that C++ will not make sure that your arrays are properly sized. If destination is not of the proper size, the code will fail at run time with a segmentation fault.
For future reference, you might want to look into using C++'s std::vector class. std::vector is a variable sized array-like container which automatically keeps track of its size and memory usage. Using pure arrays in C++ is sometimes difficult and error prone (as you have just seen), so std::vector can make things easier.
Static arrays are a fixed sized in C++. That means you can't extend or shrink them at all under any circumstance.
There are three main alternatives to achieve what you're trying to do. From your code, it looks like the best one would be to use the std::string class (since you're using chars). It contains all the code to manage and concatenate the data very easily.
If you absolutely need an array, then std::vector would be the next best choice. It allows push and pop operations etc., and will automatically resize the underlying dynamic array as needed.
Finally, you could use a dynamic array directly. You would create and destroy it using new [] and delete []. When you need to extend the array, you need to create a new one with the new size, copy the old data over, and destroy the old one. It's a lot of unnecessary extra work though, so the other two options are much better.

Dynamic Memory Allocation in C++ structs

I don't understand the syntax required for dynamically allocating members of a struct in c++. Basically, I need to fill char array members to exact size using a temp array and strlen. Here is my struct:
struct card
{
char *rank;
char *suit;
char color;
bool dealt;
char *location;
};
Here is the function that uses the struct:
bool importCard(card *deckPtr, char *deckName);
I created an array of 52 cards and assigned a pointer to it, and passed it to the function as the first parameter. (deckPtr) Here is a loop in the function that is supposed to read in card info to the struct data members.
for(index=0;index<52;index++,deckPtr++)
{
fin >> *temp;
charCount=stringLength(temp);
deckPtr.*rank = new char[charCount+1];
stringCopy(*temp, deckPtr.*rank);
fin >> *temp;
charCount=stringLength(temp);
deckPtr.*suit = new char[charCount+1];
stringCopy(*temp, deckPtr.*suit);
if(deckPtr.*suit==('d')||deckPtr.*suit==('h'))
{
(*deckPtr).color='r';
}
else
{
(*deckPtr).color='b';
}
(*deckPtr).dealt=false;
deckPtr.*location = new char[11];
stringCopy(unshPtr, deckPtr.*location);
}
I am getting three compile errors: "rank" "suit" and "location" are "not declared in this scope." What am I doing wrong? Thanks!
The syntax is deckPtr->rank, deckPtr->suit, deckPtr->location = new char[...];.
But your coding style is more like C than C++. Instead, if you use modern C++, with convenient RAII classes like std::string, your code becomes much more simplified: just use std::string instead of raw char* pointers, and you don't have to pay attention to memory allocation and memory freeing: it's all automatically managed by std::string and destructors.
#include <string>
struct card
{
std::string rank;
std::string suit;
char color;
bool dealt;
std::string location;
};
And instead of your custom stringCopy() function you can just use the "natural" operator= overload for std::string (i.e. destString = sourceString;).
And to build an array of 52 cards, just use std::vector:
#include <vector>
std::vector<card> cards(52);
Again, memory allocation is automatically managed by std::vector (and, unlike raw C arrays, you can query the vector for its own element count, using its size() method).
You probably want to use deckPtr->rank, deckPtr->suit, and deckPtr->location to assign something to the char pointers (alternatively, (*deckPtr).rank etc.). Note that * in char *var is not part of the name of the variable. It just states that the variable is a pointer to char.
You need deckPtr->foo instead of deckPtr.*foo
Your problem is that the dereference operator is operating on foo, not on deckPtr, which makes no sense to the C++ compiler, so it uses instead the pointer to member operator. This operator is used to execute member function pointers on an object, which is completely different from accessing a member. Chances are good that in an intro-level c++ class (like it appears you are in) you will never have to worry about using or understanding that operator.
In general, in C/C++ whenever you have a pointer to a struct, you want to use the -> operator, not .. foo->bar is equivalent to (*foo).bar, but it keeps you from messing up and forgetting the parentheses. There's a reason that C had an arrow operator - it's easier and clearer. In my not-so-humble opinion, teachers that impose such arbitrary restrictions actually teach students to write bad code and reinvent wheels, but I don't have their experience in teaching programming...

C++ pass array argument to a function

I want to pass a reference to an array from one object GameModel to another PersonModel, store reference and then work with this array inside PersonModel just like inside GameModel, but...
I have a terrible misunderstanding of passing an array process: In the class PersonModel I want to pass an array by reference in a constructor (see code block below). But the marked line throws the compile error
PersonModel::PersonModel( int path[FieldSize::HEIGHT][FieldSize::WIDTH], int permissionLevel ) {
this->path = path; //<------ ERROR here:
//PersonModel.cpp:14:22: error: incompatible types in assignment of 'int (*)[30]' to 'int [31][30]'
this->permissionLevel = permissionLevel;
}
Here is the header file PersonModel.h
#ifndef PERSON_MODEL
#define PERSON_MODEL
#include "data/FieldSize.h"
namespace game{
class IntPosition;
class MotionDirection;
class PersonModel {
protected:
int path[FieldSize::HEIGHT][FieldSize::WIDTH];
int permissionLevel;
public:
PersonModel( int path[FieldSize::HEIGHT][FieldSize::WIDTH], int permissionLevel );
void setMotionDirection ( MotionDirection* md);
void step(long time);
void reset(long time);
};
}
#endif
As I see now, I can change the int path[FieldSize::HEIGHT][FieldSize::WIDTH]; declaration to int (*path)[FieldSize::WIDTH]; but it is much more confusing.
Help me understand this topic: what is the proper way to store the passed reference to an array to work with it later, like with usual 2D array.
UPDATE:
This array is a map of game field tiles properties represented by bit-masks, so it is read-only actually. All the incapsulated objects of GameModel class should read this array, but I definitely don't want to duplicate it or add some extra functionality.
There are no frameworks just bare Android-NDK.
I think you've fallen into the classic trap of believing someone who's told you that "arrays and pointers are the same in C".
The first thing I'd do would be to define a type for the array:
typedef int PathArray[FieldSize::HEIGHT][FieldSize::WIDTH];
You then don't need to worry about confusions between reference to array of ints vs array of references to ints.
Your PersonModel then contains a reference to one of these.
PathArray &path;
and, because its a reference it must be initialised in the constructors initialization list rather than in the constructor body.
PersonModel::PersonModel( PathArray &aPath, int aPermissionLevel ) :
path(aPath),
permissionLevel(aPermissionLevel)
{
}
Of course, holding references like this is a little scary so you might want to consider using a boost::shared_ptr or something similar instead to make the lifetime management more robust.
You cannot assign arrays as you do with value types in C++
int path[x][y] resolves to the type int (*)[y]
Possible solutions are:
Using memcpy/copy
Using std::array
You can't assign to an array like that. However you can use the fact that an array is a contiguous memory area, even when having an array of arrays, and use e.g. memcpy to copy the array:
memcpy(this->path, path, FieldSize::HEIGHT * FieldSize::WIDTH * sizeof(int));
You would have to pass a pointer to the 2d-array as you cannot pass the array as you have stated in the code snippet.
I would suggest using the STL array type. Admittedly std::array is C++ '11 standard and therefore old compiler may not support it. You can also use vector which has been around longer.
vector<vector<int>>path;
You will have to resize the 2d-vector in the constructor.
Indexing would look a bit funny:
path[1].[1] ....
With vectors, you can then pass it by reference.
the name of the array is a pointer on first element
so,
you can try
PersonModel( int (*path)[FieldSize::HEIGHT][FieldSize::WIDTH], int permissionLevel );
In C++ '=' implemented for primitive types like int and double but not for array(array is not a primitive type), so you should never use '=' to assign an array to new array, instead you should use something as memcpy to copy array. memcpy copy a memory over another memory, so you can use it to copy an array over another array:
// memcpy( dst, src, size );
memcpy( this->path, path, FieldSize::HEIGHT * FieldSize * WEIGHT * sizeof(int) );

use array in structure c++

I have a struc like this:
struct process {int PID;int myMemory[];};
however, when I try to use it
process p;
int memory[2];
p.myMemory = memory;
I get an criptic error from eclipse saying int[0] is not compatible with int[2];
what am i doing wrong?
Thanks!
Don't use static arrays, malloc, or even new if you're using C++. Use std::vector which will ensure correct memory management.
#include <vector>
struct Process {
int pid;
std::vector<int> myMemory;
};
Process p;
p.reserve(2); // allocates enough space on the heap to store 2 ints
p.myMemory.push_back( 4815 ); // add an index-zero element of 4815
p.myMemory.push_back( 162342 ); // add an index-one element of 162342
I might also suggest creating a constructor so that pid does not initially have an undefined value:
struct Process {
Process() : pid(-1), myMemory() {
}
int pid;
std::vector<int> myMemory;
};
I think you should declare myMemory as an int* then malloc() when you know the size of it. After this it can be used like a normal array. Int[0] seems to mean "array with no dimension specified".
EXAMPLE:
int *a; // suppose you'd like to have an array with user specified length
// get dimension (int d)
a = (int *) malloc(d * sizeof(int));
// now you can forget a is a pointer:
a[0] = 5;
a[2] = 1;
free((void *) a); // don't forget this!
All these answers about vector or whatever are confused :) using a dynamically allocated pointer opens up a memory management problem, using vector opens up a performance problem as well as making the data type a non-POD and also preventing memcpy() working.
The right answer is to use
Array<int,2>
where Array is a template the C++ committee didn't bother to put in C++99 but which is in C++0x (although I'm not sure of the name). This is an inline (no memory management or performance issues) first class array which is a wrapper around a C array. I guess Boost has something already.
In C++, array definition is almost equal to pointer constants, meaning that their address cannot be changed, while the values which they point to can be changed. That said, you cannot copy elements of an array into another by the assignment operator. You have to go through the arrays and copy the elements one by one and check for the boundary conditions yourself.
The syntax ...
struct process {int PID;int myMemory[];};
... is not valid C++, but it may be accepted by some compilers as a language extension. In particular, as I recall g++ accepts it. It's in support for the C "struct hack", which is unnecessary in C++.
In C++, if you want a variable length array in a struct, use std::vector or some other array-like class, like
#include <vector>
struct Process
{
int pid;
std::vector<int> memory;
};
By the way, it's a good idea to reserve use of UPPERCASE IDENTIFIERS for macros, so as to reduce the probability of name collisions with macros, and not make people reading the code deaf (it's shouting).
Cheers & hth.,
You cannot make the array (defined using []) to point to another array. Because the array identifier is a const pointer. You can change the value pointed by the pointer but you cannot change the pointer itself. Think of "int array[]" as "int* const array".
The only time you can do that is during initialization.
// OK
int array[] = {1, 2, 3};
// NOT OK
int array[];
array = [1, 2, 3]; // this is no good.
int x[] is normally understood as int * x.
In this case, it is not, so if you want a vector of integers of an undetermined number of positions, change your declaration to:
struct process {int PID;int * myMemory;};
You should change your initialization to:
int memory[2];
p.myMemory = new int[ 10 ];