pointer to a pointer problems

C

Christopher

An open book test I am taking, tasked me to write a function with the
following prototype. Yea, its a test, so don't give me the
implementation. But it is open book, so maybe I can at least get a few
questions answered.

// returns the next token in a string found seperated by the
delimeter. upon return updates str to point to the next token in
// the string after the one returned
const char * nextToken(const char ** str, const char delimeter);

When I look at this, it looks very c-style to me. I think it is
unsafe.

1) I don't see a way to return a different string without allocating
it in the function body and leaving it to the caller to clean the new
string up.

2) Why we have a pointer to a pointer as a parameter isn't clear to
me. Even after all these years with the Windows API, I don't see the
purpose here. Why not just use a const char *?

These attempts failed with compiler errors, when trying to update the
str param
str = str + indexOnePastDelimeter; // If it was a const
char *, this is what I'd do
str = &(*str + indexOnePastDelimeter); // I don't see why the
compiler complains about this one
str = &((*str)[indexOnePastDelimeter]);


I am going to submit a more c++ implementation (below) with a
different prototype, because I failed at updating the str parameter in
all my attempts and the c-style implementation came out very ugly.
However, if anyone can address those 2 issues for me, I'd like to know
what the thinking was.


#include <string>
#include <iostream>

//--------------------------------------------------------------------------------------
/// \brief Tokenizes a string
/// \detail Gets a substring from a string, from a given start
position to the position
/// of a given delimeter. If the delimiter is not found,
everything from the start
/// position to the end of the given string is returned
/// \param str The string to tokenize
/// \param delimiter Characterer that seperates one token from the
next
/// \param start_pos [IN,OUT] position of the string to start looking
for the next token.
/// When a token is found, this parameter is updated
to the start position
/// of the next token in the string. If no next token
has been found
/// before reaching the end of the string, this
parameter will be set to
/// std::string::npos.
/// \return std::string The next token found in the string from the
given start position.
/// If the str param is empty or the start_pos
param is past the end of
/// the string, then an empty string will be
returned.
std::string nextToken(const std::string & str, const char delimiter,
std::string::size_type & start_pos)
{
// Check for valid params
if( str.empty() || start_pos >= str.size() )
{
start_pos = std::string::npos;
return "";
}

std::string::size_type orig_start_pos = start_pos;
std::string::size_type delim_pos = str.find(delimiter,
start_pos);

// Check if the delimiter was not found
if( delim_pos == std::string::npos )
{
start_pos = std::string::npos;
return str.substr(orig_start_pos, std::string::npos);
}

// Update the start position
if( delim_pos + 1 < str.size() )
{
start_pos = delim_pos + 1;
}
else
{
start_pos = std::string::npos;
}

// Return a substring that is from the start position to right
before the delimeter
return str.substr(orig_start_pos, delim_pos - orig_start_pos);
}

//--------------------------------------------------------------------------------------
int main()
{
// Test 1
const std::string testString1 = "Mary,Autumn,Susie,Sally";

std::string::size_type start_pos = 0;
while( start_pos != std::string::npos )
{
std::cout << nextToken(testString1, ',', start_pos) <<
std::endl;
}

system("Pause");

// Test 2
const std::string testString2 = "C:\\Windows\\System32\\Drivers\
\Etc\\";

start_pos = 0;
while( start_pos != std::string::npos )
{
std::cout << nextToken(testString2, '\\', start_pos) <<
std::endl;
}

system("Pause");

// Test 3
const std::string testString3 = "";

start_pos = 0;
while( start_pos != std::string::npos )
{
std::cout << nextToken(testString3, ',', start_pos) <<
std::endl;
}

system("Pause");

// Test 4
const std::string testString4 = ",";

start_pos = 0;
while( start_pos != std::string::npos )
{
std::cout << nextToken(testString4, ',', start_pos) <<
std::endl;
}

system("Pause");

// Done
return 0;
}
 
V

Victor Bazarov

An open book test I am taking, tasked me to write a function with the
following prototype. Yea, its a test, so don't give me the
implementation. But it is open book, so maybe I can at least get a few
questions answered.

// returns the next token in a string found seperated by the
delimeter. upon return updates str to point to the next token in
// the string after the one returned
const char * nextToken(const char ** str, const char delimeter);

When I look at this, it looks very c-style to me. I think it is
unsafe.

In what sense is it unsafe? You're writing that function. You can
impose any requirements on the data the function receives and introduce
all checks necessary...
1) I don't see a way to return a different string without allocating
it in the function body and leaving it to the caller to clean the new
string up.

What you get is a pointer to char [by means of its address], right?
Supposedly it points to a sequence of characters. Each character in
that sequence has an address, yes? One of the characters actually
starts the "token" you need to find. The address of that character you
will need to return.
2) Why we have a pointer to a pointer as a parameter isn't clear to
me. Even after all these years with the Windows API, I don't see the
purpose here. Why not just use a const char *?

The function has the side effect - it needs to change something in
addition to returning a value. That change can only be made if you pass
the location of the object that needs to change. If outside it's a
pointer to const char that is expected to change (i.e. to start pointing
to another const char), you have to pass that pointer either by
reference or by its address.
These attempts failed with compiler errors, when trying to update the
str param
str = str + indexOnePastDelimeter; // If it was a const
char *, this is what I'd do
str =&(*str + indexOnePastDelimeter); // I don't see why the
compiler complains about this one
str =&((*str)[indexOnePastDelimeter]);


I am going to submit a more c++ implementation (below) with a
different prototype, because I failed at updating the str parameter in
all my attempts and the c-style implementation came out very ugly.
However, if anyone can address those 2 issues for me, I'd like to know
what the thinking was.

I am not sure what you'd like to get as an answer, perhaps you want to
ask more questions, so do.
[.. a solution to a problem with different requirements ..]
V
 
C

Christopher

In what sense is it unsafe?  You're writing that function.  You can
impose any requirements on the data the function receives and introduce
all checks necessary...

Perhaps unsafe is the wrong word. Requires more checking and has more
room
for error?
What you get is a pointer to char [by means of its address], right?
Supposedly it points to a sequence of characters.  Each character in
that sequence has an address, yes?  One of the characters actually
starts the "token" you need to find.  The address of that character you
will need to return.

That was my original thought, but to really get a "token" back the
returned pointer must not only point to the address of that character,
but there must be a '\0' inserted at the end of the token.

Maybe I am misunderstanding the requirements. I can return the address
of the first character of the token easily, but then the caller is
going to have to do something useful with it. Probably calculate the
token length using the original parameter and the returned pointer and
create their own null terminated string.
 
V

Victor Bazarov

Perhaps unsafe is the wrong word. Requires more checking and has more
room
for error?

Room for error is the reverse side of checking (i.e. when checking is
lacking), so it can't be "and". As the programmer of the function, it's
your responsibility to provide all the checking and thus make it "safe"
(or "having no room for error").
What you get is a pointer to char [by means of its address], right?
Supposedly it points to a sequence of characters. Each character in
that sequence has an address, yes? One of the characters actually
starts the "token" you need to find. The address of that character you
will need to return.

That was my original thought, but to really get a "token" back the
returned pointer must not only point to the address of that character,
but there must be a '\0' inserted at the end of the token.

Maybe I am misunderstanding the requirements. I can return the address
of the first character of the token easily, but then the caller is
going to have to do something useful with it. Probably calculate the
token length using the original parameter and the returned pointer and
create their own null terminated string.

You're overthinking it. Program as requirements state, and for bonus
points explain what shortfalls you see in the specification. Since the
insertion of the null char is not in the requirements, point out to the
person grading your results that the use of the returning pointer is
limited if the token is not a true C-string... And offer your
alternative solution (based on std::string).

V
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top