concatenate variable number of arguments and types to a char *

S

suresh

Hi
How to write a function which would concatenate variable number of arguments of different type and return a char *. For example I need the function

f("his weight is = ", 51.5, "pounds");

to return the string "his weight is = 51.5 pounds".

thanks
suresh
 
A

Alf P. Steinbach

Hi
How to write a function which would concatenate variable number of arguments of
different type and return a char *. For example I need the function

f("his weight is = ", 51.5, "pounds");

to return the string "his weight is = 51.5 pounds".

One simple way is like (off the cuff)

template< class T >
string toString( T const& v )
{
stringstream stream_;
stream_ << v;
return stream.str();
}

struct S
{
string s_;
public:
template< class T >
S& operator<<( T const& v )
{
s_ += toString( v );
return *this;
}

operator char const* () const
{
return s_.c_str();
}
};

It can be elaborated and, not the least, optimized.

Anyway, then, when you want to call a function

void foo( char const* s )

you can say things like

foo( S() << "his weight is = " << 51.5 << "pounds" )

Cheers & hth.,

- Alf
 
F

Felix Bytow

Am 19.08.2011 06:04, schrieb suresh:
Hi
How to write a function which would concatenate variable number of arguments of different type and return a char *. For example I need the function

f("his weight is = ", 51.5, "pounds");

to return the string "his weight is = 51.5 pounds".

thanks
suresh

Hi,
this might do, what you want:

#include <string>
#include <sstream>
#include <iostream>

template <typename Head>
std::string concat(Head const & head)
{
std::stringstream strm;
strm << head;
return strm.str();
}

template <typename Head, typename... Tail>
std::string concat(Head const & head, Tail... tail)
{
return (concat(head) + concat(tail...));
}

int main(void)
{
std::cout << concat("The answer is ", 42, "!") << std::endl;
return 0;
}

Ofcourse this code makes use of variadic templates which are part of
C++11. You will find that not all compilers support that already.

Using the old tools you will not be able to write a function that fits
your needs completely...
 
A

Alf P. Steinbach

Am 19.08.2011 06:04, schrieb suresh:

Hi,
this might do, what you want:

#include<string>
#include<sstream>
#include<iostream>

template<typename Head>
std::string concat(Head const& head)
{
std::stringstream strm;
strm<< head;
return strm.str();
}

template<typename Head, typename... Tail>
std::string concat(Head const& head, Tail... tail)
{
return (concat(head) + concat(tail...));
}

int main(void)
{
std::cout<< concat("The answer is ", 42, "!")<< std::endl;
return 0;
}

Ofcourse this code makes use of variadic templates which are part of
C++11. You will find that not all compilers support that already.

Using the old tools you will not be able to write a function that fits
your needs completely...

The C++98 solution I posted is more efficient, O(n) versus yours O(n^2),
at the cost of slightly different notation.

The C++0x machinery you're using can be used to wrap such a more
efficient solution in order to get conventional usage notation.

However I think the C++98 solution is OK as it is... ;-)


Cheers & hth.,

- Alf

PS: Please replace tab characters with spaces before posting. Many
editors do that with just a few keypresses.
 
P

PaulR

Hi
How to write a function which would concatenate variable number of arguments >of different type and return a char *. For example I need the function

The problem with this design is.. What does the char* point to?
Returning a char* to a string created inside a function is a bit
dangerous as the string will be out of scope when the function
returns.
Unless you are playing with dynamic allocation of char arrays.

You are safer to return a std::string object by value and then you can
easily use this as a char pointer by calling the c_str() member
function.
f("his weight is = ", 51.5, "pounds");

to return the string "his weight is =  51.5 pounds".

As an improvment over what Alf posted(i think):
#include <string>
#include <sstream>
#include<iostream>

class str_add{
public:
template<typename T>
str_add& operator <<(T t){ss<<t; return *this;}
std::string str(){return ss.str();}
private:
std::stringstream ss;
};

int main() {
std::string str = (str_add()<< "lets add..." << 5.6179 << " or
something.").str();
const char* cp1 = str.c_str();
//cp1 is ok, it points to a valid string.
const char* cp2 = (str_add()<< "lets add..." << 5.6179 << " or
something.").str().c_str();
//cp2 is not ok, it pointed to a temporary
}

Note you can make the operator anything you like( i.e + or += )
instead of <<.

If you send it into a function as a char* you can only use it in the
function, whereas if you send it in as a std::string it can be
returned and used both inside and outside the function, and is much
safer.

so you make a function that accepts a std::string argument and pass
it:
(str_add()<< "lets add..." << 5.6179 << " or something.").str()
Obviously with your own words and numbers.
And you can also return that string from the function if you want.
 
J

Juha Nieminen

Leigh Johnston said:
char* can never point to an array; it can, however, point *into* an
array or one past the end of an array. :)

What's the difference?

(I'd say that since you can delete/free a dynamically allocated array
via a pointer that points to its first element, the pointer in question
*is* pointing to the array.)
 
A

Alf P. Steinbach

What's the difference?

(I'd say that since you can delete/free a dynamically allocated array
via a pointer that points to its first element, the pointer in question
*is* pointing to the array.)

Didn't you note the long trolling threads about this?

Finally Someone(TM) took the time to quote from the standard some
examples of using the "point to" terminology.

However, that only stops new people from being suckered into the
trolling debate, for a limited time. And there are always words and
expressions that are commonly used but not in the standard. So, best
leave it.


Cheers,

- Alf
 
P

Paul

char* can never point to an array; it can, however, point *into* an
array or one past the end of an array. :)

HTH.

/Leigh

Things are pointed *at* , not into.
You *insert* into, you point *at*
I refer you back to the bunch of bananas analogy.
And as for the &v[0] example , thats not taking the address of an
array , that's just a desperate attempt to try and justify your
argument which, as you like to say, is an Epic Fail!
:)
 
J

Juha Nieminen

Alf P. Steinbach said:
Didn't you note the long trolling threads about this?

I stopped following them quite at the beginning, so I have no idea
what was "discussed" there...
 
J

Juha Nieminen

Leigh Johnston said:
What's the difference?

(I'd say that since you can delete/free a dynamically allocated array
via a pointer that points to its first element, the pointer in question
*is* pointing to the array.)

Think of it this way: instead of an array of char lets have a vector of
char:

std::vector<char> v(1);
char* p1 = &v[0]; // will compile
char* p2 = v; // will not compile

Clearly p1 is a pointer to a vector element not a pointer to a vector;
p1 points to a vector element; it doesn't point to a vector; critically
pointer decay does not occur as it does with the array case.

I don't really understand. std::vector is not an array, it's a class.
It happens to internally manage an array, but it nevetheless isn't itself
one. For all we know it could be a class that prints the 99 bottles of
beer rhyme.

char* isn't a class (especially not one of type std::vector), nor even
a pointer to one.

Apples and oranges?
 
V

Victor Bazarov

Leigh Johnston said:
char* can never point to an array; it can, however, point *into* an
array or one past the end of an array. :)

What's the difference?

(I'd say that since you can delete/free a dynamically allocated array
via a pointer that points to its first element, the pointer in question
*is* pointing to the array.)

Think of it this way: instead of an array of char lets have a vector of
char:

std::vector<char> v(1);
char* p1 =&v[0]; // will compile
char* p2 = v; // will not compile

Clearly p1 is a pointer to a vector element not a pointer to a vector;
p1 points to a vector element; it doesn't point to a vector; critically
pointer decay does not occur as it does with the array case.

I don't really understand. std::vector is not an array, it's a class.
It happens to internally manage an array, but it nevetheless isn't itself
one. For all we know it could be a class that prints the 99 bottles of
beer rhyme.

char* isn't a class (especially not one of type std::vector), nor even
a pointer to one.

Apples and oranges?

Who cares? It is a pointless, time-wasting, discussion about
terminology, and you've started picking on the form in which the
arguments are delivered. Essentially this is "I say tom-AY-to, you say
tom-AH-to". A pointer to an element from a sequence of T is not a
pointer to an array of T because there is already a special type, a
pointer to an array. For 'p' to be a pointer to an array of N T it
would have to be declared T (*p)[N]. But we all say "pointer to an
array of T" because it's easier than the unusual form of "pointer INTO
an array of T", just like we say "a const reference" when we actually
mean "a refernece to a const object".

Now can we drop this?

V
 
P

Paul

Leigh Johnston said:
On 19/08/2011 15:31, Juha Nieminen wrote:
char* can never point to an array; it can, however, point *into* an
array or one past the end of an array. :)
    What's the difference?
    (I'd say that since you can delete/free a dynamically allocated array
via a pointer that points to its first element, the pointer in question
*is* pointing to the array.)
Think of it this way: instead of an array of char lets have a vector of
char:
std::vector<char>  v(1);
char* p1 =&v[0]; // will compile
char* p2 = v; // will not compile
Clearly p1 is a pointer to a vector element not a pointer to a vector;
p1 points to a vector element; it doesn't point to a vector; critically
pointer decay does not occur as it does with the array case.
   I don't really understand. std::vector is not an array, it's a class.
It happens to internally manage an array, but it nevetheless isn't itself
one. For all we know it could be a class that prints the 99 bottles of
beer rhyme.
   char* isn't a class (especially not one of type std::vector), nor even
a pointer to one.
   Apples and oranges?

Who cares?  It is a pointless, time-wasting, discussion about
terminology, and you've started picking on the form in which the
arguments are delivered.  Essentially this is "I say tom-AY-to, you say
tom-AH-to".  A pointer to an element from a sequence of T is not a
pointer to an array of T because there is already a special type, a
pointer to an array.  For 'p' to be a pointer to an array of N T it
would have to be declared T (*p)[N].  But we all say "pointer to an
array of T" because it's easier than the unusual form of "pointer INTO
an array of T", just like we say "a const reference" when we actually
mean "a refernece to a const object".
You got that wrong.
We say it's a pointer to an array because it is a pointer to an array,
not because its some sloppy terminology.
A pointer INTO an array would be a pointer that points to a sub-array.
A pointer INTO the array could not be considered as a pointer to
either the first element nor one past the end whereas a pointer to an
array can , and generally is in the case of the first element.
 
P

Paul

Leigh Johnston said:
On 19/08/2011 15:31, Juha Nieminen wrote:
char* can never point to an array; it can, however, point *into* an
array or one past the end of an array. :)
    What's the difference?
    (I'd say that since you can delete/free a dynamically allocated array
via a pointer that points to its first element, the pointer in question
*is* pointing to the array.)
Think of it this way: instead of an array of char lets have a vector of
char:
std::vector<char>  v(1);
char* p1 =&v[0]; // will compile
char* p2 = v; // will not compile
Clearly p1 is a pointer to a vector element not a pointer to a vector;
p1 points to a vector element; it doesn't point to a vector; critically
pointer decay does not occur as it does with the array case.
   I don't really understand. std::vector is not an array, it's a class.
It happens to internally manage an array, but it nevetheless isn't itself
one. For all we know it could be a class that prints the 99 bottles of
beer rhyme.
   char* isn't a class (especially not one of type std::vector), nor even
a pointer to one.
   Apples and oranges?

I was using it as an analogy; vector is semantically equivalent to an
array albeit an array whose size can change.  Pointing to a vector
element is analogous to pointing to an array element just as pointing to
a vector is analogous to pointing to an array.
Why would you ever want to point to a vector?
A vector has pass by value semantics, an array is quite the opposite.
If you want a pointer to an array then use a pointer to an array:

        typedef int array_type[42];
        array_type* pointer_to_an_array;
        int a[42];
        pointer_to_an_array = &a;

You fail to distinguish between a pointer to an array and a pointer-
type pointer to array.

What you should have said is ....
If you want a pointer OF TYPE pointer-to-array then use such a pointer
type.

The old pointer-TYPE argument works both ways because a pointer type
void* doesn't point to a void. And for bonus points a pointer of type
pointer-to-Base does not mean it doesn't point to a Derived.

On a scale of 1-100 your fail is about 90%. That is 10% of readers may
support your attempts to redefine programming terminology, the rest
will probably realise tha they never read so much pish in their lives.
:)

Next you will be trying to suggest that newbies don't learn about
arrays and instead should use std::vector or something ridiculous like
that.
Brainstorm.... You learned that way? :)
 
P

Paul

On 8/19/2011 3:18 PM, Juha Nieminen wrote:
On 19/08/2011 15:31, Juha Nieminen wrote:
char* can never point to an array; it can, however, point *into* an
array or one past the end of an array. :)
     What's the difference?
     (I'd say that since you can delete/free a dynamically allocated array
via a pointer that points to its first element, the pointer in question
*is* pointing to the array.)
Think of it this way: instead of an array of char lets have a vectorof
char:
std::vector<char>    v(1);
char* p1 =&v[0]; // will compile
char* p2 = v; // will not compile
Clearly p1 is a pointer to a vector element not a pointer to a vector;
p1 points to a vector element; it doesn't point to a vector; critically
pointer decay does not occur as it does with the array case.
    I don't really understand. std::vector is not an array, it's a class.
It happens to internally manage an array, but it nevetheless isn't itself
one. For all we know it could be a class that prints the 99 bottles of
beer rhyme.
    char* isn't a class (especially not one of type std::vector),nor even
a pointer to one.
    Apples and oranges?
Who cares?  It is a pointless, time-wasting, discussion about
terminology, and you've started picking on the form in which the
arguments are delivered.  Essentially this is "I say tom-AY-to, you say
tom-AH-to".  A pointer to an element from a sequence of T is not a
pointer to an array of T because there is already a special type, a
pointer to an array.  For 'p' to be a pointer to an array of N T it
would have to be declared T (*p)[N].  But we all say "pointer to an
array of T" because it's easier than the unusual form of "pointer INTO
an array of T", just like we say "a const reference" when we actually
mean "a refernece to a const object".
You got that wrong.
We say it's a pointer to an array because it is a pointer to an array,
not because its some sloppy terminology.
A pointer INTO an array would be a pointer that points to a sub-array.
A pointer INTO the array could not be considered as a pointer to
either the first element nor one past the end whereas a pointer to an
array can , and generally is in the case of the first element.

Actually Victor got it right; perfectly.  What you just uttered was
simply noise.

If you want a pointer to an array then use a pointer to an array:

     typedef int array_type[42];
     array_type* pointer_to_an_array;
     int a[42];
     pointer_to_an_array = &a;

HTH.

/Leigh- Hide quoted text -

- Show quoted text -
 
P

Paul

On 8/19/2011 3:18 PM, Juha Nieminen wrote:
On 19/08/2011 15:31, Juha Nieminen wrote:
char* can never point to an array; it can, however, point *into* an
array or one past the end of an array. :)
     What's the difference?
     (I'd say that since you can delete/free a dynamically allocated array
via a pointer that points to its first element, the pointer in question
*is* pointing to the array.)
Think of it this way: instead of an array of char lets have a vectorof
char:
std::vector<char>    v(1);
char* p1 =&v[0]; // will compile
char* p2 = v; // will not compile
Clearly p1 is a pointer to a vector element not a pointer to a vector;
p1 points to a vector element; it doesn't point to a vector; critically
pointer decay does not occur as it does with the array case.
    I don't really understand. std::vector is not an array, it's a class.
It happens to internally manage an array, but it nevetheless isn't itself
one. For all we know it could be a class that prints the 99 bottles of
beer rhyme.
    char* isn't a class (especially not one of type std::vector),nor even
a pointer to one.
    Apples and oranges?
Who cares?  It is a pointless, time-wasting, discussion about
terminology, and you've started picking on the form in which the
arguments are delivered.  Essentially this is "I say tom-AY-to, you say
tom-AH-to".  A pointer to an element from a sequence of T is not a
pointer to an array of T because there is already a special type, a
pointer to an array.  For 'p' to be a pointer to an array of N T it
would have to be declared T (*p)[N].  But we all say "pointer to an
array of T" because it's easier than the unusual form of "pointer INTO
an array of T", just like we say "a const reference" when we actually
mean "a refernece to a const object".
You got that wrong.
We say it's a pointer to an array because it is a pointer to an array,
not because its some sloppy terminology.
A pointer INTO an array would be a pointer that points to a sub-array.
A pointer INTO the array could not be considered as a pointer to
either the first element nor one past the end whereas a pointer to an
array can , and generally is in the case of the first element.

Actually Victor got it right; perfectly.  What you just uttered was
simply noise.
He may have done if it was in Russian.
 
I

Ian Collins

I started using C++ in 1993 (having used C before that) and didn't start
using STL containers until the second half of the 90s. When did you
start using C++ exactly?

When he started learning is irrelevant since he appears to lack the
ability to comprehend.

Do us all a favour: put him in your kill-file and get on with your life.
 
P

Paul

When he started learning is irrelevant since he appears to lack the
ability to comprehend.

Do us all a favour: put him in your kill-file and get on with your life.
Are you skitzo?
 

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