String Iterators

Discussion in 'C++' started by Adrian, Apr 18, 2007.

  1. Adrian

    Adrian Guest

    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<char > &ctype=std::use_facet<std::ctype<char >
    >(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;
    }
     
    Adrian, Apr 18, 2007
    #1
    1. Advertising

  2. Adrian wrote:
    > 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<char > &ctype=std::use_facet<std::ctype<char >
    >> (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
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Apr 18, 2007
    #2
    1. Advertising

  3. Adrian

    Adrian Guest

    On Apr 18, 2:00 pm, "Victor Bazarov" <> wrote:
    > 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
     
    Adrian, Apr 18, 2007
    #3
  4. Adrian wrote:
    > On Apr 18, 2:00 pm, "Victor Bazarov" <> wrote:
    >> 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.

    >
    >> 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.


    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
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Apr 18, 2007
    #4
  5. Adrian

    James Kanze Guest

    On Apr 18, 9:32 pm, Adrian <> wrote:

    > 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::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());


    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.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Apr 19, 2007
    #5
  6. Adrian

    Adrian Guest

    On Apr 18, 3:35 pm, "Victor Bazarov" <> wrote:
    > > 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!
     
    Adrian, Apr 19, 2007
    #6
  7. Adrian wrote:
    > On Apr 18, 3:35 pm, "Victor Bazarov" <> wrote:
    >>> 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.

    >> 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.


    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
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Apr 19, 2007
    #7
  8. Adrian

    Adrian Guest

    On Apr 19, 7:58 am, "Victor Bazarov" <> wrote:
    > 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'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.


    > 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.

    > > 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.

    lol


    Adrian
     
    Adrian, Apr 19, 2007
    #8
  9. Adrian wrote:
    > On Apr 19, 7:58 am, "Victor Bazarov" <> wrote:
    >> 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
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Apr 19, 2007
    #9
  10. Adrian

    red floyd Guest

    Adrian wrote:
    > 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]);
    }
     
    red floyd, Apr 19, 2007
    #10
  11. Adrian

    patelvijayp Guest

    On Apr 19, 12:32 am, Adrian <> wrote:
    > 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<char > &ctype=std::use_facet<std::ctype<char >
    >
    > >(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.
     
    patelvijayp, Apr 20, 2007
    #11
  12. In message <>,
    James Kanze <> writes

    [...]
    >
    > -- 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 ;-/


    --
    Richard Herring
     
    Richard Herring, Apr 23, 2007
    #12
  13. Richard Herring wrote:
    > [...] 21.3.4 currently says
    > that operator[](pos) returns data()(pos), with no sign of an as-if
    > qualification.


    Nit pick correction: 'returns data()[pos]'.

    > [..]


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Apr 23, 2007
    #13
  14. In message <f0i8k8$24i$>, Victor Bazarov
    <> writes
    >Richard Herring wrote:
    >> [...] 21.3.4 currently says
    >> that operator[](pos) returns data()(pos), with no sign of an as-if
    >> qualification.

    >
    >Nit pick correction: 'returns data()[pos]'.
    >
    >> [..]

    >

    It's Monday. Replace () with [] as appropriate ;-)

    --
    Richard Herring
     
    Richard Herring, Apr 23, 2007
    #14
  15. Richard Herring wrote:

    >>Nit pick correction: 'returns data()[pos]'.
    >>
    >>> [..]

    >>

    > It's Monday. Replace () with [] as appropriate ;-)


    'returns data [] as appropriate ;-) [pos]' ?

    --
    Salu2
     
    =?ISO-8859-15?Q?Juli=E1n?= Albo, Apr 23, 2007
    #15
  16. Adrian

    James Kanze Guest

    On Apr 23, 2:20 pm, Richard Herring <junk@[127.0.0.1]> wrote:
    > In message <>,
    > James Kanze <> writes


    > [...]


    > > -- 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).

    > > 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 ;-/


    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.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Apr 24, 2007
    #16
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Old Wolf
    Replies:
    4
    Views:
    7,587
    gfaraj
    Oct 16, 2006
  2. Marcin Kaliciñski

    Iterators and reverse iterators

    Marcin Kaliciñski, May 8, 2005, in forum: C++
    Replies:
    1
    Views:
    509
    Kai-Uwe Bux
    May 8, 2005
  3. Phil Endecott
    Replies:
    9
    Views:
    484
    Abhishek Padmanabh
    Feb 21, 2008
  4. barcaroller
    Replies:
    7
    Views:
    463
    barcaroller
    Nov 8, 2008
  5. , India
    Replies:
    10
    Views:
    1,098
    James Kanze
    Aug 8, 2009
Loading...

Share This Page