I am writing a socket programming application. C++ and Java as two ends. My system
is in Java and applications using my system uses C++.
I receive a pointer from C++ which holds some data, it could be a variable or an array.
There is another variable nrOfData which tells how many elements the pointer contains.
I have to fill an Object of type String or String[] accordingly.
But my problem is, nrOfData==1 then there is posibility for both a varaible or array(array containing one element)
I am giving a sample program here(tried to get more similar one)
#include<iostream>
using namespace std;
void func(string **strPtr)
{
if(someCondition)
{
*strPtr = new string;
}
else
{
*strPtr = new string[1];
}
}
int main()
{
string *strPtr;
func(&strPtr);
/* I have to fill a variable and send to next level
strPtr contains one element in both cases. How could i determine whether
I need to fill String or String[]*/
}
I should be strict to the requirement.
Thanks for your help !
You can use "sizeof()" operator which is helpful in determining pointer to an array or pointer to a variable. When we pass an array name to "sizeof()", it gives the total size of array in bytes while when we pass a plain pointer it gives the address length.
Related
(I'm not posting my code as this is for a project, however I have tried to get help for this issue but have had no luck)
Hi there, I am trying to initialise the size of an array of pointers (char*) which is a private member variable of my class class A
I'm using the constructor to set the size by setting an integer variable (also a member variable) which will then be used to create my array of pointers.
I have done this so far:
// Constructor - 'int value' is set to a value
private:
int value;
char ** myArray = new char*[value];
So basically I want an array of pointers in which each element can point to a string. I am passing string variables to myArray by using (char*) stringVar.c_str();
Although all of this works, I am getting some pretty weird errors when trying to store variables and have even gotten this error:
free (): invalid next size (fast)
It's weird because even when myArray is of size 4, when I try to access, say, the 3rd element, I get the same error as above.
I am very new to C++ and am very intent on solving these issues. I've had to resort to this forum for help and am looking forward to some ideas from you guys :)
if you are new C++ programmer and want work with C++ String list is better work with std::vector<std::string> for complete tutorial of how using vectors see:
http://www.cplusplus.com/reference/vector/vector/
but in you question is String list size fixed?or not?
if string list is not fixed you must malloc space for array first time in constructor and then realloc array when you want insert a string in your string list for example:
class A{
private:
char** arrayy;
int arrayysize;
A(){
arrayy = (char**)calloc(1,sizeof(char*));
arrayysize = 1;
}
insertToarrayy(char* data){
strcpy(arrayy[arrayysize-1],data);
arrayy = (char**)realloc(arrayy,arrayysize+1);
arrayysize += 1;
}
}
#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.
I have a large char array which is functioning as a memory pool and want to store a pointer in the first position of the array which points to whatever the next open position in the pool is, so every time something is allocated to the pool the pointer would point to the byte that follows the ones which were just allocated. My only problem is I am not quite sure how to store the pointer in the array and then be able to modify it in other functions since the only place the pointer will exist is in the array[0] position. Can anyone point me in the right direction on this?
the char array is declared like:
char pool[size];
What you really want is an index into that array that tells you where to insert.
You could declare a structure:
struct pool
{
char poolData[size];
int insertIndex;
};
So that you always have the pool memory and index where you want to insert to together. Or, just have a separate variable and pass them together to whoever needs to use it.
char pool[size];
int insertIndex;
There's no need to "hijack" the first element of the array and use it differently than the rest of the array; just declare another variable to track the state of the pool.
If you can't follow the recommendations of the other answers because you absolutely must use the pool to store all information in it, the safest way to store the integer information in the char-array is to use memcpy (I am using C++11 syntax):
#include <cstring>
#include <iostream>
int main()
{
using size_type = std::size_t;
static constexpr size_type size = 1000;
char pool[size];
/* Store 12 as integer information at the beginning
of the pool: */
size_type next_free = 12;
std::memcpy(pool,&next_free,sizeof(size_type));
/* Retrieve it: */
size_type retrieved = 0;
std::memcpy(&retrieved,pool,sizeof(size_type));
/* This will output 12: */
std::cout << retrieved << std::endl;
return 0;
}
Of course this implies that the first sizeof(size_type) entries of the pool must not be used to store any actual characters. The lowest entry you can actually use is pool[sizeof(size_type)].
I think what you need is an index to remember where is the next empty spot on the pool (initially will be zero).
char pool[size];
int index = 0;
Then everytime you insert a new element, you just increment it:
if(index < size) {
pool[index] = 123;
index++;
}
char **pPoolEnd = (char **) pool;
to initialize the pointer you want.
*pPoolEnd = pool + sizeof(char **);
to make it point to its own end (e.g. when there's nothing else in the pool).
However, why would you want to do this? It's confusing, error prone and probably unnecessary. Others have pointed to much better alternatives. Assuming I had such a pool in the first place, I would probably go with one of those, or simply use a separate pointer, char *poolEnd along with pool.
Also, it's bad style to expose your implementation details to users ("pool end pointer is at pool[0]") and even worse to expect them to deal with them ("please update pool[0] whenever you'd like to allocate from the pool"). Think malloc and free; expose simple function interfaces to your users.
The C++ code:
typedef struct {
int bd_number; // number of boardset
int bd_copies; // how many copies
int bd_reserve; // only allocate if needed
} bd_t,*bd_p;
typedef struct boardset_info {
int bs_copies;
int bs_demand;
int bs_allocated;
int bs_ontable_avail;
int bs_ontable_needed;
pstatus bs_status;
int bs_played_sofar;
} bsi_t, *bsi_p;
FC_ERRORCODE dropin_boards(bd_p boards) {
int bs;
bs_info = (bsi_p) calloc(total_boardsets+1, sizeof(bsi_t));//total_boardsets=8
for (bs = 1; bs <= total_boardsets; bs++)
bs_info[bs].bs_status = PS_OUTPLAY;
while (boards->bd_number) { //boards-<bd_number is betweeen 1 and 8
if (boards->bd_number < 0 || boards->bd_number > total_boardsets)
{
debprint("***Error dropin_boards***\n");
debprint("boardsetnumber=%d\n",boards->bd_number);
return FC_ERR_PARAM;
}
//code does not reach this point
}
Calling code:
<StructLayout(LayoutKind.Sequential)>
Public Structure Flex_BoardSetInfo
Public SetNumber As Integer
Public Copies As Integer
Public IsReserve As Integer
End Structure
<DllImport("FlexCalc2.dll", CallingConvention:=CallingConvention.StdCall)>
Public Shared Function FlexCalcBoards(ByRef boards() As Flex_BoardSetInfo) As Flex_ErrorCode
End Function
Dim boardsets() = GetBoardSetInfo() // creates an arry of 8 BoardsetInfo Elements
_result = FlexCalcWrapper.FlexCalcBoards(boardsets)
On the last line on the debug file is logged that bd_p->board_number=517237496! The boardnumbers are initialized 1 to 8 and I can check that that has been correctly done before the code passes to the C++ dll.
How do I solve this?
EDIT:
From VB6 we used a hack to get this C++ method working:
Declare Function FlexCalcBoards Lib "FlexCalc2.dll" (firstBoard As BoardsetInfo)
ret=FlexCalcBoards(Boards(0))
So, we passed the first element of the array in stead of the array itself! (Un?)fortunately, Net does not fall for this trick...
Replace ByRef with ByVal. An array already gets marshaled as a pointer.
Using ByRef would only match a bd_t** on the C side.
Well, the answers and comments seemed to indicate that nothing should be wrong, so....
I found three things:
1. Even after rebuilding the entire solution and copying and pasting the new FlexCalc2.dll to the testproject, the old copy of the dll that resided in the Bin folders was NOT replaced.
2. I am a novice in C++, but it seems that you cannot iterate through an array using LBound to UBound when the method has only received a pointer to it. The method shown uses a nifty way to implement a kind of for each, but here it does not work because bd_p->boardnumber returns a very high number (memory address?), but bd_p[index].boardnumber returns the correct number within the range 1-8. I simply sent the length of the array as an extra parameter to the function and I was all set. (Call it the poor man's choice for all I care ;-))
3. Hans Passant was right in stating that when the method signature in C++ is theReturnValue theMethod(theStruct * theArray) that from Net you must pass the array ByVal (In VB6 this generates a syntax error and is not possible). The fact that a pointer to the array was passed is not immediately obvious since the * was already declared in the typedef of the struct.
I apologise if I'm completely misunderstanding C++ at the moment, so my question might be quite simple to solve. I'm trying to pass a character array into a function by value, create a new array of the same size and fill it with certain elements, and return that array from the function. This is the code I have so far:
char *breedMutation(char genome []){
size_t genes = sizeof(genome);
char * mutation = new char[genes];
for (size_t a = 0 ;a < genes; a++) {
mutation[a] = 'b';
}
return mutation;
}
The for loop is what updates the new array; right now, it's just dummy code, but hopefully the idea of the function is clear. When I call this function in main, however, I get an error of initializer fails to determine size of ‘mutation’. This is the code I have in main:
int main()
{
char target [] = "Das weisse leid"; //dummy message
char mutation [] = breedMutation(target);
return 0;
}
I need to learn more about pointers and character arrays, which I realise, but I'm trying to learn by example as well.
EDIT: This code, which I'm trying to modify for character arrays, is the basis for breedMutation.
int *f(size_t s){
int *ret=new int[s];
for (size_t a=0;a<s;a++)
ret[a]=a;
return ret;
}
Your error is because you can't declare mutation as a char[] and assign it the value of the char* being returned by breedMutation. If you want to do that, mutation should be declared as a char* and then deleted once you're done with it to avoid memory leaks in a real application.
Your breedMutation function, apart from dynamically allocating an array and returning it, is nothing like f. f simply creates an array of size s and fills each index in the array incrementally starting at 0. breedMutation would just fill the array with 'b' if you didn't have a logic error.
That error is that sizeof(genome); will return the size of a char*, which is generally 4 or 8 bytes on a common machine. You'll need to pass the size in as f does since arrays are demoted to pointers when passed to a function. However, with that snippet I don't see why you'd need to pass a char genome[] at all.
Also, in C++ you're better off using a container such as an std::vector or even std::array as opposed to dynamically allocated arrays (ones where you use new to create them) so that you don't have to worry about freeing them or keeping track of their size. In this case, std::string would be a good idea since it looks like you're trying to work with strings.
If you explain what exactly you're trying to do it might help us tell you how to go about your problem.
The line:
size_t genes = sizeof(genome);
will return the sizeof(char*) and not the number of elements in the genome array. You will need to pass the number of elements to the breedMutation() function:
breedMutation(target, strlen(target));
or find some other way of providing that information to the function.
Hope that helps.
EDIT: assuming it is the number of the elements in genome that you actually want.
Array are very limited.
Prefer to use std::vector (or std::string)
std::string breedMutation(std::string const& genome)
{
std::string mutation;
return mutation;
}
int main()
{
std::string target = "Das weisse leid"; //dummy message
std::string mutation = breedMutation(target);
}
Try replacing the second line of main() with:
char* mutation = breedMutation(target);
Also, don't forget to delete your mutation variable at the end.