 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Zombie Guest
|
Posted: Wed Aug 18, 2004 6:20 pm Post subject: <string> to lowercase |
|
|
Hi, what is the correct way of converting contents of a <string> to
lowercase?
There are no methods of <string> class to do this so I fallback on
strlwr().
But the c_str() method returns a const pointer which cannot be used
with strlwr() as it does the conversion inplace. So, I use the
following logic of copying the contents to a dynamically allocated
char* array and then doing the conversion:
-----------------------------
string str = "faLSe";
char* pc_str = NULL;
pc_str = new char[str.length() + 1];
memset(pc_str, 0, sizeof(pc_str));
strcpy(pc_str, str.c_str());
strlwr(pc_str);
// pc_str now contains "false"
-----------------------------
Is there any other, less cumbersome way of doing the same?
Thanks for your time.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Matt Wharton Guest
|
Posted: Wed Aug 18, 2004 6:45 pm Post subject: Re: <string> to lowercase |
|
|
You might look at using the 'for_each' algorithm in conjunction with the
string's iterators and 'tolower'.
-Matt
"Zombie" <natkhatbandar (AT) yahoo (DOT) com> wrote
| Quote: | Hi, what is the correct way of converting contents of a <string> to
lowercase?
There are no methods of <string> class to do this so I fallback on
strlwr().
But the c_str() method returns a const pointer which cannot be used
with strlwr() as it does the conversion inplace. So, I use the
following logic of copying the contents to a dynamically allocated
char* array and then doing the conversion:
-----------------------------
string str = "faLSe";
char* pc_str = NULL;
pc_str = new char[str.length() + 1];
memset(pc_str, 0, sizeof(pc_str));
strcpy(pc_str, str.c_str());
strlwr(pc_str);
// pc_str now contains "false"
-----------------------------
Is there any other, less cumbersome way of doing the same?
Thanks for your time.
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Kai-Uwe Bux Guest
|
Posted: Wed Aug 18, 2004 6:47 pm Post subject: Re: <string> to lowercase |
|
|
Zombie wrote:
| Quote: | Hi, what is the correct way of converting contents of a <string> to
lowercase?
There are no methods of <string> class to do this so I fallback on
strlwr().
But the c_str() method returns a const pointer which cannot be used
with strlwr() as it does the conversion inplace. So, I use the
following logic of copying the contents to a dynamically allocated
char* array and then doing the conversion:
-----------------------------
string str = "faLSe";
char* pc_str = NULL;
pc_str = new char[str.length() + 1];
memset(pc_str, 0, sizeof(pc_str));
strcpy(pc_str, str.c_str());
strlwr(pc_str);
// pc_str now contains "false"
-----------------------------
Is there any other, less cumbersome way of doing the same?
Thanks for your time.
|
The following uses the current locale to convert a string to lowercase:
#include <string>
#include <iostream>
#include <locale>
template < typename Iter >
void range_tolower ( Iter beg, Iter end ) {
for( Iter iter = beg; iter != end; ++iter ) {
*iter = std::tolower( *iter );
}
}
void string_tolower ( std::string & str ) {
range_tolower( str.begin(), str.end() );
}
int main ( void ) {
std::string test ( "Test" );
string_tolower( test );
std::cout << test << std::endl;
}
Best
Kai-Uwe
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ashes Guest
|
Posted: Thu Aug 19, 2004 12:51 am Post subject: Re: <string> to lowercase |
|
|
Hi
You can also use the transform() algorithm:
#include <string>
#include <algorithm>
void ConvertToLowerCase(std::string& str)
{
std::transform(str.begin(),
str.end(),
str.begin(),
tolower);
// You may need to cast the above line to (int(*)(int))
// tolower - this works as is on VC 7.1 but may not work on
// other compilers
}
Regards
Ashley
|
|
| Back to top |
|
 |
Xenos Guest
|
Posted: Thu Aug 19, 2004 11:59 am Post subject: Re: <string> to lowercase |
|
|
"Zombie" <natkhatbandar (AT) yahoo (DOT) com> wrote
| Quote: | Hi, what is the correct way of converting contents of a <string> to
lowercase?
There are no methods of <string> class to do this so I fallback on
strlwr().
But the c_str() method returns a const pointer which cannot be used
with strlwr() as it does the conversion inplace. So, I use the
following logic of copying the contents to a dynamically allocated
char* array and then doing the conversion:
-----------------------------
string str = "faLSe";
char* pc_str = NULL;
pc_str = new char[str.length() + 1];
memset(pc_str, 0, sizeof(pc_str));
strcpy(pc_str, str.c_str());
strlwr(pc_str);
// pc_str now contains "false"
-----------------------------
Is there any other, less cumbersome way of doing the same?
|
off the top of my head:
void to_lowercase(std::string&s)
{
for (std::string::iterator i = s.begin(); i != s.end(); ++i)
*i = tolower(*i);
}
OR
string to_lowercase(const std::string& s)
{
std::string t;
for (std::string::const_iterator i = s.begin(); i != s.end(); ++i)
t += tolower(*i);
return t;
}
or you could use a function object with one of the standard library
templates such as for_each or transform.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Joe C Guest
|
Posted: Thu Aug 19, 2004 12:00 pm Post subject: Re: <string> to lowercase |
|
|
"Zombie" <natkhatbandar (AT) yahoo (DOT) com> wrote
| Quote: | Hi, what is the correct way of converting contents of a <string> to
lowercase?
There are no methods of <string> class to do this so I fallback on
strlwr().
But the c_str() method returns a const pointer which cannot be used
with strlwr() as it does the conversion inplace. So, I use the
following logic of copying the contents to a dynamically allocated
char* array and then doing the conversion:
-----------------------------
string str = "faLSe";
char* pc_str = NULL;
pc_str = new char[str.length() + 1];
memset(pc_str, 0, sizeof(pc_str));
strcpy(pc_str, str.c_str());
strlwr(pc_str);
// pc_str now contains "false"
-----------------------------
Is there any other, less cumbersome way of doing the same?
|
These 2 little functions change the case of strings. Note that these assume
ASCII and as such are not portable. I've been told that these are the worst
functions ever...but they work for me...
if you want it to change the actual string rather than returning a new
string, just pass a reference to a void function and make the change to the
charecter of the original string.
here they are:
#include <iostream>
#include <string>
using namespace std;
string lcase(string in);
string ucase(string in);
int main(){
string str("A mIxEd CaSe StRiNg 123!@@#");
cout << str << endl
<< lcase(str) << endl
<< ucase(str) << endl;
return 0;
}
string lcase(string in){
string stringout;
for(int i = 0; i < in.size(); ++i)
if(!(in[i] & 128) && ((in[i] & 95) > 64) && ((in[i] & 31) <= 26))
stringout += (in[i] | 32); //turn on the lcase bit
else stringout += in[i]; //character wasn't a letter...dont change
return stringout;
}
string ucase(string in){
string stringout;
for(int i = 0; i < in.size(); ++i)
if(!(in[i] & 128) && ((in[i] & 95) > 64) && ((in[i] & 31) <= 26))
stringout += (in[i] & (223)); //turn off the lcase bit
else stringout += in[i]; //character wasn't a letter...dont change
return stringout;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Andre Kostur Guest
|
Posted: Thu Aug 19, 2004 12:03 pm Post subject: Re: <string> to lowercase |
|
|
"Matt Wharton" <noSpam (AT) noSpam (DOT) com> wrote in news:1092853381.442698
@cswreg.cos.agilent.com:
| Quote: | You might look at using the 'for_each' algorithm in conjunction with the
string's iterators and 'tolower'.
|
Wouldn't you want std::transform ?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Brian Stone Guest
|
Posted: Thu Aug 19, 2004 12:16 pm Post subject: Re: <string> to lowercase |
|
|
[email]natkhatbandar (AT) yahoo (DOT) com[/email] (Zombie) wrote in message news:<902e612a.0408180133.3b49dfe5 (AT) posting (DOT) google.com>...
| Quote: | Hi, what is the correct way of converting contents of a <string> to
lowercase?
There are no methods of <string> class to do this so I fallback on
strlwr().
But the c_str() method returns a const pointer which cannot be used
with strlwr() as it does the conversion inplace. So, I use the
following logic of copying the contents to a dynamically allocated
char* array and then doing the conversion:
-----------------------------
string str = "faLSe";
char* pc_str = NULL;
pc_str = new char[str.length() + 1];
memset(pc_str, 0, sizeof(pc_str));
strcpy(pc_str, str.c_str());
strlwr(pc_str);
// pc_str now contains "false"
-----------------------------
Is there any other, less cumbersome way of doing the same?
Thanks for your time.
|
The easiest way I know is to use the transform() function from the
<algorithm> library. Here's an example of how to apply this to a
string to convert the case...
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <cctype>
using namespace std;
int main ( int argc, char **argv )
{
string A = "TeStInG!";
cout << A << endl; // output: TeStInG!
transform ( A.begin(), A.end(), A.begin(), ptr_fun(::tolower) );
cout << A << endl; // output: testing!
transform ( A.begin(), A.end(), A.begin(), ptr_fun(::toupper) );
cout << A << endl; // output: TESTING!
}
-- Brian Stone
South Dakota School of Mines & Technology
UAV Team Lead Programmer
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tommy Andreasen Guest
|
Posted: Fri Aug 20, 2004 12:23 am Post subject: Re: <string> to lowercase |
|
|
Zombie wrote:
| Quote: | Hi, what is the correct way of converting contents of a <string> to
lowercase?
There are no methods of <string> class to do this so I fallback on
strlwr().
But the c_str() method returns a const pointer which cannot be used
with strlwr() as it does the conversion inplace. So, I use the
following logic of copying the contents to a dynamically allocated
char* array and then doing the conversion:
-----------------------------
string str = "faLSe";
char* pc_str = NULL;
pc_str = new char[str.length() + 1];
memset(pc_str, 0, sizeof(pc_str));
strcpy(pc_str, str.c_str());
strlwr(pc_str);
// pc_str now contains "false"
-----------------------------
Is there any other, less cumbersome way of doing the same?
Thanks for your time.
|
I usually to it like this:
std::transform(str.begin(), str.end(), str.begin(),
std::ptr_fun(std::tolower));
Tommy -
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Old Wolf Guest
|
Posted: Fri Aug 20, 2004 12:27 am Post subject: Re: <string> to lowercase |
|
|
Kai-Uwe Bux <jkherciueh (AT) gmx (DOT) net> wrote:
| Quote: | Zombie wrote:
Hi, what is the correct way of converting contents of a <string> to
lowercase?
The following uses the current locale to convert a string to lowercase:
#include <string
#include
#include
template < typename Iter
void range_tolower ( Iter beg, Iter end ) {
for( Iter iter = beg; iter != end; ++iter ) {
*iter = std::tolower( *iter );
}
}
|
Unfortunately, std::tolower requires an argument in the range
0...UCHAR_MAX. So you can go:
*iter = std::tolower( (unsigned char)*iter );
and hope that it gets converted back to char properly afterwards, or:
if (*iter >= 0 && *iter <= UCHAR_MAX)
*iter = std::tolower(*iter);
| Quote: | void string_tolower ( std::string & str ) {
range_tolower( str.begin(), str.end() );
}
int main ( void ) {
std::string test ( "Test" );
string_tolower( test );
std::cout << test << std::endl;
}
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Peter Koch Larsen Guest
|
Posted: Fri Aug 20, 2004 12:51 am Post subject: Re: <string> to lowercase |
|
|
"Zombie" <natkhatbandar (AT) yahoo (DOT) com> skrev i en meddelelse
news:902e612a.0408180133.3b49dfe5 (AT) posting (DOT) google.com...
| Quote: | Hi, what is the correct way of converting contents of a <string> to
lowercase?
|
Well... this is actually a rather complicated question. For an explanation
as to why, take a look at the thread "Case insensitive comparison of
std::strings" in comp.lang.c++.moderated. For a "basic" conversion, for_each
and tolower would be okay (perhaps combined with some locale but i am not
familiar with these).
| Quote: | There are no methods of <string> class to do this so I fallback on
strlwr().
But the c_str() method returns a const pointer which cannot be used
with strlwr() as it does the conversion inplace. So, I use the
following logic of copying the contents to a dynamically allocated
char* array and then doing the conversion:
-----------------------------
string str = "faLSe";
char* pc_str = NULL;
pc_str = new char[str.length() + 1];
memset(pc_str, 0, sizeof(pc_str));
strcpy(pc_str, str.c_str());
strlwr(pc_str);
// pc_str now contains "false"
-----------------------------
Is there any other, less cumbersome way of doing the same?
|
Yes - that approach surely seems to cumbersome.
| Quote: |
Thanks for your time.
|
Kind regards
Peter
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Kai-Uwe Bux Guest
|
Posted: Fri Aug 20, 2004 10:10 am Post subject: Re: <string> to lowercase |
|
|
Old Wolf wrote:
| Quote: | Kai-Uwe Bux <jkherciueh (AT) gmx (DOT) net> wrote:
Zombie wrote:
Hi, what is the correct way of converting contents of a <string> to
lowercase?
The following uses the current locale to convert a string to lowercase:
#include <string
#include
#include
template < typename Iter
void range_tolower ( Iter beg, Iter end ) {
for( Iter iter = beg; iter != end; ++iter ) {
*iter = std::tolower( *iter );
}
}
Unfortunately, std::tolower requires an argument in the range
0...UCHAR_MAX. So you can go:
*iter = std::tolower( (unsigned char)*iter );
and hope that it gets converted back to char properly afterwards, or:
if (*iter >= 0 && *iter <= UCHAR_MAX)
*iter = std::tolower(*iter);
|
I was under the impression that std::tolower, being a template, would be
instantiated for the deduced type
is a std::string::iterator. Now, if it is a template, why should it be
restricted to 0..UCHAR_MAX, effectively forcing the type to be unsigned
char? That does not seem to make any sense -- of course, this does not
imply it isn't so. In any case, I looked up tolower in the standard and did
not see any hint at UCHAR_MAX. Probably, I was looking at the wrong
section. Could you point me to the source?
Best
Kai-Uwe Bux
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Fri Aug 20, 2004 2:40 pm Post subject: Re: <string> to lowercase |
|
|
[email]no.more.spam (AT) stoneentertainment (DOT) com[/email] (Brian Stone) wrote in message
news:<acd67ea1.0408181412.6b38c3ca (AT) posting (DOT) google.com>...
| Quote: | The easiest way I know is to use the transform() function from the
algorithm> library. Here's an example of how to apply this to a
string to convert the case...
#include <iostream
#include
#include
#include
#include
using namespace std;
int main ( int argc, char **argv )
{
string A = "TeStInG!";
cout << A << endl; // output: TeStInG!
transform ( A.begin(), A.end(), A.begin(), ptr_fun(::tolower) );
cout << A << endl; // output: testing!
transform ( A.begin(), A.end(), A.begin(), ptr_fun(::toupper) );
cout << A << endl; // output: TESTING!
}
|
Is it just me, or what? There have been a number of postings suggesting
this, either with or without the call to ptr_fun. Now, it has some
obvious and well known problems when it encounters a character encoding
that is negative, and toupper( 'ß' ) doesn't (and cannot) work at all,
but I can understand anglocentric programmers missing this in a quick
response. On the other hand, I have been unable to find a compiler where
this even compiles, in any of the suggested variants, on any system: it
fails to compile (with or without the ptr_fun) with g++ (3.4.0), Sun CC
(5.1) and VC++ (6.0).
In fact, the only variant which compiled (and that got a warning from
Sun CC) is yours, with ::tolower and ::toupper. And you are playing on a
bug in practically every implementation of
::tolower and ::toupper (rather than only having them available in
std::, as the standard requires).
As far as I know (and ignoring the issues of passing an out of bounds
value to the functions), the correct way to write the call to transform
is something like:
std::transform( str.begin(), str.end(),
str.begin(),
std::ptr_fun( (int (*)( int ))std::tolower ) ) ;
Even better would be something like:
std::transform(
str.begin(), str.end(),
str.begin(),
boost::bind(
std::ptr_fun(
(char (*)( char, std::locale const& ))std::tolower ),
_1,
std::locale() ) ) ;
(Some of the Boost experts should verify this. I still have enough older
compilers to support that I can't actively use Boost, as much as it
would facilitate my code.)
This should at least give defined behavior in every case, even if it
gives the wrong results sometimes.
Of course, the original poster asked for something that wasn't
awkward:-).
--
James Kanze GABI Software http://www.gabi-soft.fr
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Fri Aug 20, 2004 2:42 pm Post subject: Re: <string> to lowercase |
|
|
[email]no.more.spam (AT) stoneentertainment (DOT) com[/email] (Brian Stone) wrote in message
news:<acd67ea1.0408181412.6b38c3ca (AT) posting (DOT) google.com>...
| Quote: | natkhatbandar (AT) yahoo (DOT) com (Zombie) wrote in message
news:<902e612a.0408180133.3b49dfe5 (AT) posting (DOT) google.com>...
Hi, what is the correct way of converting contents of a <string> to
lowercase?
There are no methods of <string> class to do this so I fallback on
strlwr().
But the c_str() method returns a const pointer which cannot be used
with strlwr() as it does the conversion inplace. So, I use the
following logic of copying the contents to a dynamically allocated
char* array and then doing the conversion:
-----------------------------
string str = "faLSe";
char* pc_str = NULL;
pc_str = new char[str.length() + 1];
memset(pc_str, 0, sizeof(pc_str));
strcpy(pc_str, str.c_str());
strlwr(pc_str);
// pc_str now contains "false"
-----------------------------
Is there any other, less cumbersome way of doing the same?
The easiest way I know is to use the transform() function from the
algorithm> library. Here's an example of how to apply this to a
string to convert the case...
#include <iostream
#include
#include
#include
#include
using namespace std;
int main ( int argc, char **argv )
{
string A = "TeStInG!";
cout << A << endl; // output: TeStInG!
transform ( A.begin(), A.end(), A.begin(), ptr_fun(::tolower) );
cout << A << endl; // output: testing!
transform ( A.begin(), A.end(), A.begin(), ptr_fun(::toupper) );
cout << A << endl; // output: TESTING!
}
|
1. This isn't guaranteed to compile, for at least two reasons. The
obvious one is that you've forgotten to include
obvious one is that any C++ header may include any other C++
headers; if <iostream> includes <locale> (actually
quite likely, since often <iostream> just includes everything in the
iostream section of the library, and both basic_ios and
basic_streambuf need <locale>), then the call to ptr_fun will be
abiguous.
Formally, in fact, I think that the standard guarantees that it
won't compile, since there shouldn't be a tolower nor a toupper in
global namespace. (But I could be wrong about this. I don't really
understand the interactions between "using namespace" and the ::
specifier.) In practice, however, I don't know of a single
implementation which is conformant in this regard.
2. If it compiles, and uses the tolower in <cctype>, then you have
undefined behavior, at least if plain char is signed (as it is on
most systems). Passing a negative value to the tolower function in
<cctype> is undefined behavior.
--
James Kanze GABI Software http://www.gabi-soft.fr
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Fri Aug 20, 2004 2:42 pm Post subject: Re: <string> to lowercase |
|
|
[email]oldwolf (AT) inspire (DOT) net.nz[/email] (Old Wolf) wrote in message
news:<843a4f78.0408181512.5858b4d8 (AT) posting (DOT) google.com>...
| Quote: | Kai-Uwe Bux <jkherciueh (AT) gmx (DOT) net> wrote:
Zombie wrote:
Hi, what is the correct way of converting contents of a <string
to lowercase?
The following uses the current locale to convert a string to
lowercase:
#include
#include
#include
template < typename Iter
void range_tolower ( Iter beg, Iter end ) {
for( Iter iter = beg; iter != end; ++iter ) {
*iter = std::tolower( *iter );
}
}
Unfortunately, std::tolower requires an argument in the range
0...UCHAR_MAX.
|
No, it takes a second parameter, a std::locale. E.g.:
*iter = std::tolower( *iter, std::locale() ) ;
At least in a conforming implementation (see below).
| Quote: | So you can go:
*iter = std::tolower( (unsigned char)*iter );
|
This works on a conforming implementation as well, as long as you
include
implementations are still pretty rare, however, and I've found that
leaving the std:: off and including <locale.h> seems to be about the
only thing that works portably.
And of course, since in this case, you are using the C version of
tolower, you have to ensure that the input is an unsigned char. And, as
you say, hope that the results don't get mangled when you reconvert back
to char -- realistically, the amount of code that mangling them would
break (even though the standard allows it) is so large that no
implementation would dare...
Finally, of course, none of the solutions really work, because there is
no one to one mapping of upper case characters to lower case characters.
| Quote: | and hope that it gets converted back to char properly afterwards, or:
if (*iter >= 0 && *iter <= UCHAR_MAX)
*iter = std::tolower(*iter);
|
Actually, the only cases such a mapping can make sense is when you are
using pure ASCII, and have no accented characters. So:
assert( *iter >= 0 && *iter <= 127 ) ;
(assuming ASCII, obviously -- this isn't really portable).
--
James Kanze GABI Software http://www.gabi-soft.fr
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|