How to return an array of own datatype

S

Steve

Hello (and a happy new year)

I'm quite new to C++ and have to programm something for school and can't
get my head around
a couple of things, but at the moment this one is the most important for me:

I have defined a class String and before I go on I should mention that
I'm not allowed to use any pre-defined templates (no STL) and not the
standard C++ String class, kind of mean :)

Nevertheless I want to tokenize a String with a predefined delimiter,
which will be used later to
cut words out of a sentence.

String.cpp

String[] String::tokenize(const String s, char* delimiter)
{
String stringArray[];
// tokenize the String and put each word into the String array
...

return stringArray;
}


String.h

String[] tokenize(const String s, char* delimiters);


My first problem is that I get a bunch of errors for the header line
(the first is C3409, I'm using VC++ .NET),
I assume this is not the way how one should define an array return type?
I know I have a second problem too, because I have to define the size
of the array I want to return, but honestly I want to avoid that, I
would love to do that dynamicly
as in a Vector.
 
D

David Harmon

On Sun, 02 Jan 2005 11:12:07 +0100 in comp.lang.c++, Steve
String[] tokenize(const String s, char* delimiters);

An array return type is not allowed.

You can return a struct that contains an array. Or you can let the
caller provide a pointer to an array argument that you fill with
your results. You can return a pointer to an array that you got
somewhere, but that means you have to pay more attention to where
the array is allocated.
 
S

Steve

David said:
On Sun, 02 Jan 2005 11:12:07 +0100 in comp.lang.c++, Steve
String[] tokenize(const String s, char* delimiters);


An array return type is not allowed. Ohhh, ok didn't know that!

You can return a struct that contains an array. Or you can let the
caller provide a pointer to an array argument that you fill with
your results. You can return a pointer to an array that you got
somewhere, but that means you have to pay more attention to where
the array is allocated.

Thanks, I will give the struct idea a try.

cheers
Steve
 
M

Mole Wang

Steve said:
David said:
On Sun, 02 Jan 2005 11:12:07 +0100 in comp.lang.c++, Steve
String[] tokenize(const String s, char* delimiters);


An array return type is not allowed. Ohhh, ok didn't know that!

You can return a struct that contains an array. Or you can let the
caller provide a pointer to an array argument that you fill with
your results. You can return a pointer to an array that you got
somewhere, but that means you have to pay more attention to where
the array is allocated.

Thanks, I will give the struct idea a try.
Most time, return a struct is not a good idea. This cause a copy operation of
the members in the struct.
 
C

cyper

String.cpp

std::vector<String> String[] String::tokenize(const String s, char* delimiter)
{
std::vector<String> stringArray;
// tokenize the String and put each word into the String array
...

return stringArray;
}


OK?
But a little slow.
 
C

cyper

Most time, return a struct is not a good idea. This cause a copy operation of
the members in the struct.
Or return a std::SmartPtr allocated by the function ?

Who should own it?
Who should allocate it?
Who should free it?

Pointers bring too trouble to it.
 
J

Jonathan Mcdougall

cyper said:
Or return a std::SmartPtr allocated by the function ?

Who should own it?
Who should allocate it?
Who should free it?

Depending on the design, receiving a reference to an object for modification
can be more "efficient" than returning it. The thing is, modifying
parameters received by reference is usually dangerous, since it is not
always clear that the function will modify it. I prefer passing by address
when my functions modify their arguments.

void f(A &a);
void g(A *a);

int main()
{
A a;

f(a); // watch out, f() modifies a
g(&a); // that's clearer (imho)
}

Except for specific cases, I prefer returning by value since it is the
clearest way and users can safely ignore the modifications.


Jonathan
 
M

Mike Wahler

cyper said:
String.cpp

std::vector<String> String[] String::tokenize(const String s, char* delimiter)
{
std::vector<String> stringArray;
// tokenize the String and put each word into the String array
...

return stringArray;
}


OK?
But a little slow.

Did you try to compile that?

-Mike
 
K

Karthik Kumar

Steve said:
Hello (and a happy new year)

I'm quite new to C++ and have to programm something for school and can't
get my head around
a couple of things, but at the moment this one is the most important for
me:

I have defined a class String and before I go on I should mention that
I'm not allowed to use any pre-defined templates (no STL) and not the
standard C++ String class, kind of mean :)

Nevertheless I want to tokenize a String with a predefined delimiter,
which will be used later to
cut words out of a sentence.

String.cpp

String[] String::tokenize(const String s, char* delimiter)


From a design perspective , the String argument to the function,
seems a little bit unconventional and confusing, since it is not
clear why this ought to be a member function since you are
passing a String and a delimiter as argument to the function.
(well, then you can as well have this method as static, which
may not be the best design though ).

Some suggestions:

1. You can have a method as follows.

vector<String> String::tokenize(const char * delimiter)
//Tokenize the String object's contents' here.


2. A better way would be to have a StringTokenizer class.


vector<String> StringTokenizer::tokenize(const char * delimiter);
 
D

Dietmar Kuehl

Steve said:
String[] String::tokenize(const String s, char* delimiter)
{
String stringArray[];
// tokenize the String and put each word into the String array
...

return stringArray;
}

The typical C++ approach to this is to have the function take an output
iterator which is written to in the function, i.e. something like this:

| template <typename OutIt>
| OutIt String::tokenize(char const* delimiters, OutIt to)
| {
| // ...
| *to++ = token;
| // ...
| return to;
| }

You could then use your 'tokenize()' function something like this:

| std::vector<String> vec;
| String str(/*...*/);
| str.tokenize(",", std::back_inserter(vec));

.... or use whatever appropriate container type you wish instead of
'std::vector' as long as it supports a 'push_back()' operation. This
also
allows output e.g. to standard output using an appropriate iteartor:

| str.tokenize(',', std::eek:stream_iterator<String>(std::cout, "\n"));

The trouble is somewhat that your teacher apparently does not
understand
how C++ works and deprived you from reasonable use of the standard
library
thereby either forcing you to reimplement fairly large portions thereof
or
using inferior programming techniques. If he wanted you to provide an
implementation of some particular algorithms without using the
corresponding
algorithms from the standard library he should have specified it that
way
rather.
String[] tokenize(const String s, char* delimiters);

This is illegal syntax. If it were possible to return an array from a
function, the syntax would rather be something like this:

| String (tokenize(String const&s, char const* delimiters))[10];

A declaration like this should give an error message similar to the one
issued e.g. by SUN's compiler:

| Error: Functions cannot return arrays or functions.

However, please note two other important changes I applied to the
function
signature:
- The string is taken as reference argument: there is probably no need
to
copy the String, especially if you want it to be 'const' anyway.
- To allow passing of string literals to the functions, the second
parameter uses a pointer to 'char const' (i.e. an array of constant
'char's; 'char const' and 'const char' is equivalent but I consider
it
to be easier to read to place the 'const' as far to the right as
possible).
My first problem is that I get a bunch of errors for the header line
(the first is C3409, I'm using VC++ .NET),
I assume this is not the way how one should define an array return
type?

Right. See above.
I know I have a second problem too, because I have to define the size
of the array I want to return, but honestly I want to avoid that, I
would love to do that dynamicly
as in a Vector.

To do so, you need to handle dynamic memory allocation - or,
preferably,
use one of the standard containers. Proper implementation of a
container
is actually non-trivial and involves loads of intrinsic little nits
which
are, IMO, far beyond a typical school assignment level. For example,
reasonable implementation of a 'std::vector' replacement involves
allocation
of uninitialized memory and placement construction/destruction of
elements.
No real rocket science but hardly what students need to be exposed to
learn
dealing with data structures either. Of course, some issues can be side
stepped by default constructing a bigger array and only considering a
subset
of the actual elements to be present in the vector...
 

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,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top