help passing pointer to char array as argument

  • Thread starter rob.kirkpatrick
  • Start date
R

rob.kirkpatrick

Hello

I need to populate an array of char arrays at run-time. A very
simplifed version of the code is below.

char ** list should contain cnt char arrays. The values of char ** list
are set by the function foo(). A pointer to char ** list is passed to
foo() as an argument.

The problem is that when foo() returns, char ** list contains rubbish
and does not always contain cnt char arrays. Can anyone tell me what
I'm doing wrong? Note that I don't want to use the vector or string for
efficiency. Note that the code that get the time has nothing to do with
the real programme. It's just a simplification for the purpose of this
posting.


(I have noticed that if the values are constant char arrays there is no
problem)

//*********************************************************************************
#include <iostream.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>

void foo(char *** array, int cnt){

char buf[256];

for(int i=0; i<cnt; i++){
long t = time(NULL); // just for demonstration
itoa(t, buf, 10);
(*array) = buf;
cout << i << " " << (*array) << '\n';
}
}

int main(int argc, char ** argv){

int cnt = 10;
char ** list = new char*[10];

foo(&list, cnt);

for(int i=0; i<cnt; i++){
cout << i << " " << list << "\n";
}

delete [] list;

return 0;
}
//*********************************************************************************

Thanks!!!!!
 
T

Tim Love

void foo(char *** array, int cnt){
char buf[256];
This fixes the value of buf for the duration of the function, so
(*array) = buf;

will set all the elements to the same value - the value of buf.

Also, buf is a local variable, so when foo ends, the space used by buf can be recycled.

The short answer to your question is to reconsider using containers.
 
T

tragomaskhalos

Hello


void foo(char *** array, int cnt){

char buf[256];

for(int i=0; i<cnt; i++){
long t = time(NULL); // just for demonstration
itoa(t, buf, 10);
(*array) = buf;
cout << i << " " << (*array) << '\n';
}
}


For starters, you're assigning the same local buffer 'buf' multiple
times, then that's going out of scope at the end of the function.
No offence mate, but you're clearly struggling juggling three levels of
indirection; you're going to be a lot better off using std::vector and
std::string. They are designed precisely to allow programmers to avoid
these sorts of gymnastics and pitfalls. Your concerns about
"performance" are misplaced, get the thing working in a clear and
understandable way and then worry about tweaking it for performance
*if* you need to. Which you won't.
 
I

Ian Collins

Hello

I need to populate an array of char arrays at run-time. A very
simplifed version of the code is below.

char ** list should contain cnt char arrays. The values of char ** list
are set by the function foo(). A pointer to char ** list is passed to
foo() as an argument.

The problem is that when foo() returns, char ** list contains rubbish
and does not always contain cnt char arrays. Can anyone tell me what
I'm doing wrong? Note that I don't want to use the vector or string for
efficiency. Note that the code that get the time has nothing to do with
the real programme. It's just a simplification for the purpose of this
posting.
Why not just use std::vector<std::string> and save yourself a lot of
trouble?
 
R

rob.kirkpatrick

Tim said:
void foo(char *** array, int cnt){
char buf[256];
This fixes the value of buf for the duration of the function, so
(*array) = buf;

will set all the elements to the same value - the value of buf.

Also, buf is a local variable, so when foo ends, the space used by buf can be recycled.

The short answer to your question is to reconsider using containers.


Thanks, Tim.
I might be wrong but I'm using a pointer to char ** list and assigning
the value of buf. char ** list's values should persist after foo()
returns. Isn't that right? Thanks!!!

Rob
 
T

TB

(e-mail address removed) skrev:
Tim said:
void foo(char *** array, int cnt){
char buf[256];
This fixes the value of buf for the duration of the function, so
(*array) = buf;

will set all the elements to the same value - the value of buf.

Also, buf is a local variable, so when foo ends, the space used by buf can be recycled.

The short answer to your question is to reconsider using containers.


Thanks, Tim.
I might be wrong but I'm using a pointer to char ** list and assigning
the value of buf. char ** list's values should persist after foo()
returns. Isn't that right? Thanks!!!


You're assigning the address of 'buf' to each pointer, and 'buf' only
exists within the scope of 'foo()', not outside in 'main()'. The address
points to some location on the stack, which is recycled and overwritten
by subsequent stack operations, like the following call to
std::basic_ostream::eek:perator<<(...).

You need to allocate the buffer with 'new' if you want it to persist,
or dismiss any thoughts of efficiency and do as others have replied,
skip deep indirection and use the provided framework of containers.

For example:

#include <sstream>
#include <vector>
#include <string>
#include <ctime>
#include <ostream>
#include <algorithms>

void foo(std::vector<std::string> &v, unsigned cnt) {
std::eek:stringstream strm;
for(unsigned i = 0; i < cnt; ++i) {
strm << std::time(0);
v.push_back(strm.str());
strm.str("");
}
}

int main(int argc, char* argv[])
{
std::vector<std::string> v;
foo(v,10);
std::copy(v.begin(),
v.end(),
std::eek:stream_iterator<std::string>(std::cout,"\n"));
return 0;
}
 
R

rob.kirkpatrick

TB said:
You're assigning the address of 'buf' to each pointer, and 'buf' only
exists within the scope of 'foo()', not outside in 'main()'. The address
points to some location on the stack, which is recycled and overwritten
by subsequent stack operations, like the following call to
std::basic_ostream::eek:perator<<(...).

You need to allocate the buffer with 'new' if you want it to persist,
or dismiss any thoughts of efficiency and do as others have replied,
skip deep indirection and use the provided framework of containers.

TB @ SWEDEN

Thanks to you and others who have got back to me. I'll take this
advice; but I'm still curious as to the following:

Essentially: is it possible to manipulate the values an array of chars
from within the scope of a function so that they persist?

foo(char *** list){
// manipulate list elements
}

I assume if I allocate memory with "new", for example...

(*array) = new char[256];

....how can I then free the memory? I assume "delete [] list" won't do
it.

Thanks!!!
Rob
 
T

TB

(e-mail address removed) skrev:
TB said:
You're assigning the address of 'buf' to each pointer, and 'buf' only
exists within the scope of 'foo()', not outside in 'main()'. The address
points to some location on the stack, which is recycled and overwritten
by subsequent stack operations, like the following call to
std::basic_ostream::eek:perator<<(...).

You need to allocate the buffer with 'new' if you want it to persist,
or dismiss any thoughts of efficiency and do as others have replied,
skip deep indirection and use the provided framework of containers.

TB @ SWEDEN

Thanks to you and others who have got back to me. I'll take this
advice; but I'm still curious as to the following:

Essentially: is it possible to manipulate the values an array of chars
from within the scope of a function so that they persist?

foo(char *** list){
// manipulate list elements
}

I assume if I allocate memory with "new", for example...

(*array) = new char[256];

...how can I then free the memory? I assume "delete [] list" won't do
it.


#include <iostream>
#include <ctime>
#include <cstdlib>

void foo(char **& array, unsigned cnt){
for(unsigned i = 0; i < cnt; ++i){
char * buf = new char[256];
long t = std::time(0);
std::itoa(t, buf, 10);
array = buf;
std::cout << i << " " << array << std::endl;
}
}

int main(int argc, char ** argv){
unsigned cnt = 10;
char ** list = new char*[10];

foo(list, cnt);

for(unsigned i = 0; i < cnt; ++i) {
std::cout << i << " " << list << std::endl;
}

for(unsigned i = 0; i < cnt; ++i) {
delete[] list;
}
delete[] list;

return 0;
}
 
R

rob.kirkpatrick

#include <iostream>
#include <ctime>
#include <cstdlib>

void foo(char **& array, unsigned cnt){
for(unsigned i = 0; i < cnt; ++i){
char * buf = new char[256];
long t = std::time(0);
std::itoa(t, buf, 10);
array = buf;
std::cout << i << " " << array << std::endl;
}
}

int main(int argc, char ** argv){
unsigned cnt = 10;
char ** list = new char*[10];

foo(list, cnt);

for(unsigned i = 0; i < cnt; ++i) {
std::cout << i << " " << list << std::endl;
}

for(unsigned i = 0; i < cnt; ++i) {
delete[] list;
}
delete[] list;

return 0;
}


Thanks very much TB!!!

Rob
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top