String Iterators

A

Adrian

Hi all,

I want a char * (not const) from a std::string.

I see string.begin() return an iterator which is implementation
defined.
And *iterator returns a reference to the element
So does &*iterator return a pointer to the element?

Now this below compiles but is it legal?

Adrian

#include <iostream>
#include <string>
#include <locale>

int main(int argc, char *argv[])
{
std::string mixed("We ARE a test String");

const std::ctype said:
(std::locale::classic());

std::cout << mixed << std::endl;

// What is a good way to get the pointer from an iterator
// Are you allowed to do this?
ctype.tolower(&*mixed.begin(), &*mixed.end());
std::cout << mixed << std::endl;

// instead of this
ctype.toupper(&mixed[0], &mixed[mixed.length()]);
std::cout << mixed << std::endl;

return 0;
}
 
V

Victor Bazarov

Adrian said:
I want a char * (not const) from a std::string.

I see string.begin() return an iterator which is implementation
defined.
And *iterator returns a reference to the element
So does &*iterator return a pointer to the element?
Yes.

Now this below compiles but is it legal?

Adrian

#include <iostream>
#include <string>
#include <locale>

int main(int argc, char *argv[])
{
std::string mixed("We ARE a test String");

const std::ctype said:
(std::locale::classic());

std::cout << mixed << std::endl;

// What is a good way to get the pointer from an iterator
// Are you allowed to do this?
ctype.tolower(&*mixed.begin(), &*mixed.end());

This assumes that the string keeps its characters in an array. I
don't think this is guaranteed anywhere in the Standard. Why can't
you simply use 'transform'?

std::transform(mixed.begin(), mixed.end(), mixed.begin(), tolower);

? Just curious. You can of course write your own 'tolower' that
would use your specific facet, can't you?
std::cout << mixed << std::endl;

// instead of this
ctype.toupper(&mixed[0], &mixed[mixed.length()]);
std::cout << mixed << std::endl;

return 0;
}

V
 
A

Adrian

Adrian wrote:
This assumes that the string keeps its characters in an array. I
don't think this is guaranteed anywhere in the Standard.
It doesnt but 21.3.2 does say they conform to sequence containers
which unfortunantley arent all arrays either.

Then also doesnt this apply to using &mixed[0] and
&mixed[mixed.length()]
Why can't you simply use 'transform'?
Because I was trying to find out how useful facets are. Would be nice
for a simple tolower/toupper functions in the stl that just worked on
strings :)

Point is moot now though - its an old compiler and doesn support
locale's anyway
std::transform(mixed.begin(), mixed.end(), mixed.begin(), tolower);

? Just curious. You can of course write your own 'tolower' that
would use your specific facet, can't you?
I was looking for something already in the STL so that it would be
more efficent than anything I could write.


Adrian
 
V

Victor Bazarov

Adrian said:
Adrian wrote:
This assumes that the string keeps its characters in an array. I
don't think this is guaranteed anywhere in the Standard.
It doesnt but 21.3.2 does say they conform to sequence containers
which unfortunantley arent all arrays either.

Then also doesnt this apply to using &mixed[0] and
&mixed[mixed.length()]

Doesn't WHAT apply? The overloaded operator[] returns a reference.
You can take the address of it to get the address of the referred
object.
Because I was trying to find out how useful facets are. Would be nice
for a simple tolower/toupper functions in the stl that just worked on
strings :)

Point is moot now though - its an old compiler and doesn support
locale's anyway

I was looking for something already in the STL so that it would be
more efficent than anything I could write.

You're essentially spending your precious time trying to find some
elusive solution (which may or may not exist) for the sake of some
performance problem you may or may not even have. Does that pretty
much sum up what you're trying to do here?

V
 
J

James Kanze

I want a char * (not const) from a std::string.
I see string.begin() return an iterator which is implementation
defined.
And *iterator returns a reference to the element
So does &*iterator return a pointer to the element?
Yes.

Now this below compiles but is it legal?
No.

#include <iostream>
#include <string>
#include <locale>
int main(int argc, char *argv[])
{
std::string mixed("We ARE a test String");
const std::ctype<char > &ctype=std::use_facet<std::ctype<char >

std::cout << mixed << std::endl;
// What is a good way to get the pointer from an iterator
// Are you allowed to do this?
ctype.tolower(&*mixed.begin(), &*mixed.end());

No. There are actually two problems, at present:

-- There is currently no requirement that the data in a string
be contiguous; an implementation along the lines of SGI's
rope class is legal, for example.

In fact, no real implementation does this, and the C++
standards committee has decided (for the moment, at least)
to make contiguity a requirement in the next version of the
standard, just as it is for vector. There will also be a
non-const data() to return a pointer to the buffer, so you
don't have to jump through hoops to get it. In the mean
time: all real implementations are contiguous, so you can
jump through hoops, and be relatively safe.

-- The expression *mixed.end() has undefined behavior, and will
probably core dump (assertion failure) in most modern
implementations of the library. To avoid this:

ctype.tolower( &mixed[ 0 ], &mixed[ 0 ] + mixed.size() ) ;

is the consecrated solution. (Whether you use
&*mixed.begin(), or &mixed[0] doesn't matter, but the latter
is shorter to write.)
std::cout << mixed << std::endl;
// instead of this
ctype.toupper(&mixed[0], &mixed[mixed.length()]);

Why "insteamd of"? Both suffer in practice from the same
problem; mixed[mixed.length()] or *mixed.end() actively
dereference one passed the end; in any quality implementation
today, they will provoke an assertion failure.

The basic technique is widely used with vector, and off hand,
I'd say that the &mixed[0] seems to be the preferred technique
for getting the address of the first element---probably just
because it is less to write.
 
A

Adrian

Then also doesnt this apply to using &mixed[0] and
&mixed[mixed.length()]

Doesn't WHAT apply? The overloaded operator[] returns a reference.
You can take the address of it to get the address of the referred
object.
That the elements would have to be an array.
You're essentially spending your precious time trying to find some
elusive solution (which may or may not exist) for the sake of some
performance problem you may or may not even have. Does that pretty
much sum up what you're trying to do here?
I am sorry I thought this was comp.lang.c++ a discussion group.

If you dont wish to discuss or reply feel free to go to the next
thread

:) Have a nice day!
 
V

Victor Bazarov

Adrian said:
Then also doesnt this apply to using &mixed[0] and
&mixed[mixed.length()]

Doesn't WHAT apply? The overloaded operator[] returns a reference.
You can take the address of it to get the address of the referred
object.
That the elements would have to be an array.

No. Overloaded operator[] is called for the object and that does
not *at all* imply that there is an array of any kind. Example:
'std::map' has operator[] defined for it, yet, in all implemenations
I've encountered, there was no array. There is a tree (R-B tree, to
be exact), but no array.

Overloading operator[] allows you to use the particular syntax with
an object of that class, the same syntax that you use to index within
an array. Do not confuse the two.
I am sorry I thought this was comp.lang.c++ a discussion group.

You thought correctly. And I am discussing. Do you have a problem
with what I said? Would you like to present a rebuttal? By all
means, I'll be happy to discuss.
If you dont wish to discuss or reply feel free to go to the next
thread

Oh, thanks for your permission. I didn't know I needed one from you.
:) Have a nice day!

You bet!

V
 
A

Adrian

No. Overloaded operator[] is called for the object and that does
not *at all* imply that there is an array of any kind. Example:
'std::map' has operator[] defined for it, yet, in all implemenations
I've encountered, there was no array. There is a tree (R-B tree, to
be exact), but no array.

Overloading operator[] allows you to use the particular syntax with
an object of that class, the same syntax that you use to index within
an array. Do not confuse the two.
I did not.

You pointed out that since a string does not have to be implented in
an array then
&*mixed.begin() < &*mixed.end() does not have to be true.

I then assumend that &mixed[0] and &mixed[mixed.length()] would follow
the same logic and
not &mixed[0] < &mixed[mixed.length()] does not have to be true.
You thought correctly. And I am discussing. Do you have a problem
with what I said? Would you like to present a rebuttal? By all
means, I'll be happy to discuss.
Certainly :) Your comment was acerbic. I know you have posted here
for years and I respect your knowledge of c++, sometimes I even laugh
at your short treatment of peoples posts but I just felt my question
didnt justify it such a response. But hey its the usernet - all
opinions are valid.
Oh, thanks for your permission. I didn't know I needed one from you.
lol


Adrian
 
V

Victor Bazarov

Adrian said:
No. Overloaded operator[] is called for the object and that does
not *at all* imply that there is an array of any kind. Example:
'std::map' has operator[] defined for it, yet, in all implemenations
I've encountered, there was no array. There is a tree (R-B tree, to
be exact), but no array.

Overloading operator[] allows you to use the particular syntax with
an object of that class, the same syntax that you use to index within
an array. Do not confuse the two.
I did not.

You pointed out that since a string does not have to be implented in
an array then
&*mixed.begin() < &*mixed.end() does not have to be true.

I then assumend that &mixed[0] and &mixed[mixed.length()] would follow
the same logic and
not &mixed[0] < &mixed[mixed.length()] does not have to be true.

Ah, got it. Yes, it does not have to be true. I think I understand.

V
 
R

red floyd

Adrian said:
Hi all,

I want a char * (not const) from a std::string.

You could try (modulo length checks on the API call, of course:


#include <string>
#include <vector>

void API_call(char *);

void API_Wrapper(const std::string& s)
{
std::vector<char> v(s.begin(), s.end());
API_call(&v[0]);
}
 
P

patelvijayp

Hi all,

I want a char * (not const) from a std::string.

I see string.begin() return an iterator which is implementation
defined.
And *iterator returns a reference to the element
So does &*iterator return a pointer to the element?

Now this below compiles but is it legal?

Adrian

#include <iostream>
#include <string>
#include <locale>

int main(int argc, char *argv[])
{
std::string mixed("We ARE a test String");

const std::ctype said:
(std::locale::classic());

std::cout << mixed << std::endl;

// What is a good way to get the pointer from an iterator
// Are you allowed to do this?
ctype.tolower(&*mixed.begin(), &*mixed.end());
std::cout << mixed << std::endl;

// instead of this
ctype.toupper(&mixed[0], &mixed[mixed.length()]);
std::cout << mixed << std::endl;

return 0;

}

Hello,

http://gcc.gnu.org/onlinedocs/libstdc++/21_strings/howto.html#4
http://gcc.gnu.org/onlinedocs/libstdc++/22_locale/howto.html#7

In case, if you have not seen, Above 2 links are from libstdc++
chapter spacific documentation has discussed that.

Vijay.
 
R

Richard Herring

In message <[email protected]>,

[...]
-- There is currently no requirement that the data in a string
be contiguous; an implementation along the lines of SGI's
rope class is legal, for example.

The standard seems to be inconsistent here. 21.3.4 currently says that
operator[](pos) returns data()(pos), with no sign of an as-if
qualification.
In fact, no real implementation does this, and the C++
standards committee has decided (for the moment, at least)
to make contiguity a requirement in the next version of the
standard, just as it is for vector. There will also be a
non-const data() to return a pointer to the buffer, so you
don't have to jump through hoops to get it.

Since the non-const operator[](pos) supposedly returns a reference to
data()(pos), that's just as well ;-/
 
J

James Kanze

In message <[email protected]>,
-- There is currently no requirement that the data in a string
be contiguous; an implementation along the lines of SGI's
rope class is legal, for example.
The standard seems to be inconsistent here. 21.3.4 currently says that
operator[](pos) returns data()(pos), with no sign of an as-if
qualification.

There are a number of defects in the orginal text for string.
To be more accurate, it was the intent of the original standard
to allow an implementation along the lines of rope. As you say,
some of the text seems to contradict this intent (and other text
contradicts the contradictions).
Since the non-const operator[](pos) supposedly returns a reference to
data()(pos), that's just as well ;-/

Yes:).

In fact: the committee discussed the issues rather thoroughly.
Unlike the requirement for vector to be contiguous, this was not
considered a clarification, but a new restriction on
implementations. It was adopted on the basis of two arguments:

-- it's useful, for the same reason the requirement in vector
is useful, when interfacing to C API's, and

-- no implementation ever actually took advantage of the
liberty to be non-contiguous, so presumably, it wasn't an
important liberty.

On the whole, I think it's a good decision. In an ideal world,
you'd just use std::string for everything, it wouldn't matter,
and the best choice would be to leave a maximum of freedom to
the implementors. In the real world, however, it's a rare C++
program that doesn't have to interface with at least one API
specified in C, and simplifying that is easily worth the removal
of a little bit of implementation freedom, that no one used
anyway.
 

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

Similar Threads

Crossword 2
Cannot find my infinite loop 1
Questions about new range for 2
Crossword 14
Remove Space, Stuck on lab 1
TF-IDF 1
Best way to print all possible permutations of a string 3
Lexical Analysis on C++ 1

Members online

Forum statistics

Threads
473,744
Messages
2,569,481
Members
44,900
Latest member
Nell636132

Latest Threads

Top