views:

214

answers:

2

I'm trying to build a char array for storing the return value of a function. In the following function the data is stored in ***valv. How to build a extern variable to access the data?

int credis_lrange(REDIS rhnd, const char *key, 
                   int start, int end, char ***valv) 
{
  int rc;

  if ((rc = cr_sendfandreceive(rhnd, CR_MULTIBULK, "LRANGE %s %d %d\r\n", 
                                key, start, end)) == 0) 
  {
    *valv = rhnd->reply.multibulk.bulks;
    rc = rhnd->reply.multibulk.len;
  }

  return rc;
}

Solution:

char **elements;

int size = credis_lrange(this->redis,"object_2",600,603,&elements);

for (int i=0; i<size;i++) {
    cout << "element: " << elements[i] << endl; 
}

Thanks to everyone!

+4  A: 
char ***element[size];

Is not exactly a 3D array, but an array of size elements of pointers-to-pointers-to-pointers to char.

Use any one of the following:

char e[ D1 ][ D2 ][ D3 ]; /* D1, D2, D3 are integral constants */
char *e[ D2 ][ D3 ];
char e[][ D2 ][ D3 ];

Also, you can pass it on by simply speficying e as the argument to your function.

On further reading, it appears that the parameter is not really a 3D array but a pointer to an array of C-style strings. Note, the syntax may be the same, the intent is different.

In that case, you'll need to do two things:

  • Specify the number of strings you want to store in the array
  • For each string
    • Allocate memory
    • Copy string data to the char array

And finally, you'll be passing in the address of this array of strings on to the credis_lrange function.

dirkgently
Hi Dirk, thanks for your super fast reply. So I have to make 3 for loops and allocate memory for each element per array level?
dan
If you use Dirks first suggestion, you don't need to do any memory allocation. That's all allocated in one contiguous lump. Although when you use "e" it will act a lot like a pointer (to a pointer to a pointer to a char), that doesn't imply a need to allocate/free memory from the heap.
Steve314
In Dirk's first example you don't need to allocate memory. In the 2nd example you need to loop through once and allocate memory.
Jagannath
I've tried Dirks first suggestion but getting this error: cannot convert 'char (*)[1024][1024]' to 'char***' for argument '5' to 'int credis_lrange(_cr_redis*, const char*, int, int, char***)'
dan
@dirk: thanks again for your help. I'm getting almost the same error: cannot convert 'char ( * )[1024][1024][1024]' to 'char***' for argument '5' to 'int credis_lrange(_cr_redis*, const char*, int, int, char***)'
dan
dirkgently
A: 

I only found one hit on Google for this, but it looks like the cr_sendfandreceive function allocates its rhnd->reply.multibulk.bulks member, so you don't actually have to pass it back (since you were passed rhnd in the first place).

If you want to copy it, then you would declare elements as a char** and pass its address (or use references), and then inside the method you would clone the bulks member and also each string in the array (in a loop).

Neil
Hi Neil, thanks for your reply. Could you give any sample code on this?
dan
This is the basic idea, but obviously without any error checking:char** clone(int argc, char **argv){ char** result = (char**)malloc(argc * sizeof(char*)); while (argc--) result[argc] = strdup(argv[argc]); return result;}
Neil