I get an error when I compile the following code:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
using namespace std;
string&
lc(string& s)
{
transform(s.begin(), s.end(), s.begin(), tolower);
return s;
}
int
main()
{
string name = "DAVID";
cout << name << " " << lc(name) << endl;
return 0;
}
; g++ lc.cc
lc.cc: In function `std::string& lc(std::string&)':
lc.cc:11: error: no matching function for call to `transform(
__gnu_cxx::__normal_iterator<char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >,
__gnu_cxx::__normal_iterator<char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >,
__gnu_cxx::__normal_iterator<char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >, <unknown type>)'
If I do not include iostream, or if I use a different function
(e.g., int id(int i){return i;}), I do not get any errors. Am I doing
something wrong?
/david
--
Andre, a simple peasant, had only one thing on his mind as he crept
along the East wall: 'Andre, creep... Andre, creep... Andre, creep.'
-- unknown 13 5977
In article <3F***************@nomail.com>,
David Rubin <bo***********@nomail.com> wrote: I get an error when I compile the following code:
#include <algorithm> #include <cctype> #include <iostream> #include <string>
using namespace std;
string& lc(string& s) { transform(s.begin(), s.end(), s.begin(), tolower); return s; }
int main() { string name = "DAVID";
cout << name << " " << lc(name) << endl; return 0; }
; g++ lc.cc lc.cc: In function `std::string& lc(std::string&)': lc.cc:11: error: no matching function for call to `transform( __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unknown type>)'
If I do not include iostream, or if I use a different function (e.g., int id(int i){return i;}), I do not get any errors. Am I doing something wrong?
Yes, but you're in good company. This one gets almost everyone at least
once.
There are two kickers (if not more) in this one:
1. tolower is (also) a template function prototyped in <locale>:
template <class charT> charT tolower(charT c, const locale& loc);
2. Any standard C++ header is allowed to include any other standard C++
header as an implementation detail (reference 17.4.4.1/1).
So when you say:
transform(s.begin(), s.end(), s.begin(), tolower);
and if the templated tolower is in scope, then the compiler can't figure
out what template parameters to try out for tolower<charT>, even if the
non-templated tolower is also in scope. And apparently gcc's <iostream>
brings tolower<charT> into scope as an implementation detail. Thus the
error.
This is a sneaky one in that it may well compile and do what you want
with another compiler. For example it works just fine on Metrowerks,
unless <locale> is explicitly included, and then you get a similar error.
You can correct it, portably, with the following incantation:
transform(s.begin(), s.end(), s.begin(), (int (*)(int))tolower);
I.e. cast tolower to the specific function pointer type that you're
aiming for.
-Howard
"David Rubin" <bo***********@nomail.com> wrote in message
news:3F***************@nomail.com...
I get an error when I compile the following code:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
using namespace std;
string&
lc(string& s)
{
transform(s.begin(), s.end(), s.begin(), tolower);
return s;
}
int
main()
{
string name = "DAVID";
cout << name << " " << lc(name) << endl;
return 0;
}
; g++ lc.cc
lc.cc: In function `std::string& lc(std::string&)':
lc.cc:11: error: no matching function for call to `transform(
__gnu_cxx::__normal_iterator<char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >,
__gnu_cxx::__normal_iterator<char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >,
__gnu_cxx::__normal_iterator<char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >, <unknown type>)'
If I do not include iostream, or if I use a different function
(e.g., int id(int i){return i;}), I do not get any errors. Am I doing
something wrong?
/david
--
Andre, a simple peasant, had only one thing on his mind as he crept
along the East wall: 'Andre, creep... Andre, creep... Andre, creep.'
-- unknown
__________________________________________________ ___________
the way I fixed it is by doing
::tolower
Howard Hinnant <hi*****@metrowerks.com> wrote: You can correct it, portably, with the following incantation:
transform(s.begin(), s.end(), s.begin(), (int (*)(int))tolower);
I.e. cast tolower to the specific function pointer type that you're aiming for.
See, even standard library implementers get it wrong :-) This one is,
however, even more subtle: 'std::tolower(int)' can only be called with
values which can be represented by an 'unsigned char' and EOF. However,
on systems where 'char' is a signed entity lots of possible 'char' values,
promoted to 'int', cannot be represented as 'unsigned char'. Although the
above code would be portably compilable, it won't run portably. For a
truely portable solution, you would need an auxiliary function:
char mytolower(char c) {
return std::tolower(static_cast<unsigned char>(c));
}
This will convert the negative 'char' to some positive value first which
stays the same value when converted to 'int'. Promoting a negative 'char'
directly to 'int' and then converting this value to an unsigned type
would yield a value which is [normally (*)] bigger than any value which
can be hold by an 'unsigned char'.
(*): if the number of bits used for 'int' and 'unsigned char' is identical,
it would work...
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>
On Wed, 08 Oct 2003 22:43:22 GMT, Howard Hinnant
<hi*****@metrowerks.com> wrote: Yes, but you're in good company. This one gets almost everyone at least once.
There are two kickers (if not more) in this one:
1. tolower is (also) a template function prototyped in <locale>:
template <class charT> charT tolower(charT c, const locale& loc);
2. Any standard C++ header is allowed to include any other standard C++ header as an implementation detail (reference 17.4.4.1/1).
So when you say:
transform(s.begin(), s.end(), s.begin(), tolower);
and if the templated tolower is in scope, then the compiler can't figure out what template parameters to try out for tolower<charT>, even if the non-templated tolower is also in scope.
It's not that clear in the standard that the non-template tolower
shouldn't be chosen. For the templated tolower, argument deduction
would fail, so only the non-template version would be left. In theory
this could be chosen unambiguously.
And apparently gcc's <iostream>brings tolower<charT> into scope as an implementation detail. Thus the error.
This is a sneaky one in that it may well compile and do what you want with another compiler. For example it works just fine on Metrowerks, unless <locale> is explicitly included, and then you get a similar error.
Comeau compiles it fine with both <locale> and <cctype> included.
13.4/2 suggests that it might be ok, but it certainly isn't clear
either way. http://std.dkuug.dk/jtc1/sc22/wg21/d...ctive.html#115
also has vague relevence.
You can correct it, portably, with the following incantation:
transform(s.begin(), s.end(), s.begin(), (int (*)(int))tolower);
I.e. cast tolower to the specific function pointer type that you're aiming for.
However, this still has the problem with the domain to tolower being
EOF + the range of unsigned char.
Tom
David Rubin <bo***********@nomail.com> wrote in message news:<3F***************@nomail.com>... I get an error when I compile the following code:
#include <algorithm> #include <cctype> #include <iostream> #include <string>
using namespace std;
string& lc(string& s) { transform(s.begin(), s.end(), s.begin(), tolower); return s; }
int main() { string name = "DAVID";
cout << name << " " << lc(name) << endl; return 0; }
/david
david, I don't know that much about c++, but you can do what you want
by flipping the bit in the 32's place. If you know that your string
contains letters, then you can use these 3 functions:
#include <iostream>
#include <string>
using namespace std;
string lcase(string stringin){
string stringout;
for(int i = 0; i < stringin.size(); ++i)
stringout += (stringin[i] | 32);
return stringout;
}
string ucase(string stringin){
string stringout;
for(int i = 0; i < stringin.size(); ++i)
stringout += (stringin[i] & (223));
return stringout;
}
string flipcase(string stringin){
string stringout;
for(int i = 0; i < stringin.size(); ++i)
stringout += (stringin[i] ^ 32);
return stringout;
}
int main(){
cout << "Enter text";
string test;
getline(cin, test);
cout << "Original " << test << endl
<< "All Caps " << ucase(test)<< endl
<< "Lower Case " << lcase(test) << endl
<< "Flip Case " << flipcase(test) << endl;
}
Of course, you will prob. want to clean up the function masks so that
they only effect characters. (eg only effect chars (65 - 90) and (97 -
122)).
"Steven C." <no****@xxx.com> wrote in message news:<KG****************@twister.socal.rr.com>... "David Rubin" <bo***********@nomail.com> wrote in message news:3F***************@nomail.com... I get an error when I compile the following code:
#include <algorithm> #include <cctype> #include <iostream> #include <string>
using namespace std;
string& lc(string& s) { transform(s.begin(), s.end(), s.begin(), tolower); return s; }
int main() { string name = "DAVID";
cout << name << " " << lc(name) << endl; return 0; }
I'm sure your aren't interested, but...I improved the functions I just
wrote so that they now ignore all non alphebetic characters. You can
easily change the function to pass a string reference if you want the
change to affect the original string. Anyway...these functions should
work with any string object.
#include <iostream>
#include <string>
using namespace std;
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);
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));
else stringout += in[i]; //character wasn't a letter...dont
change
return stringout;
}
string flipcase(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);
else stringout += in[i]; //character wasn't a letter...dont
change
return stringout;
}
int main(){
cout << "Enter text\n";
string test;
getline(cin, test);
cout << "Original " << test << endl
<< "All Caps " << ucase(test)<< endl
<< "Lower Case " << lcase(test) << endl
<< "Flip Case " << flipcase(test) << endl;
}
in case you are wondering...
if(!(in[i] & 128) & ((in[i] & 95) > 64) & ((in[i] & 31) <= 26))
------------- ------------------ -------------------
0XXX XXXX X10X XXXX 000X XXXX <= 26
000X XXXX > 0
"J. Campbell" wrote: using namespace std;
string& lc(string& s) { transform(s.begin(), s.end(), s.begin(), tolower); return s; }
[snip] david, I don't know that much about c++, but you can do what you want by flipping the bit in the 32's place. If you know that your string contains letters, then you can use these 3 functions:
[snip - code]
Thanks for the code. However, you are assuming an ASCII character set
and a particular locale. The ::tolower solution seems to work well. I
suppose you can extend this to implement Flipcase as a functor (or
simply as a function) using
s[i] = (::isupper(s[i]) ? ::tolower(s[i]) : ::toupper(s[i]));
BTW, for those in the know who are still reading this thread, is* and
to* are known to take an int argument to account for EOF. However, is it
safe to assume that an explicit cast is unnecessary when applying these
functions to a string? Presumably, a string will not contain EOF.
/david
--
Andre, a simple peasant, had only one thing on his mind as he crept
along the East wall: 'Andre, creep... Andre, creep... Andre, creep.'
-- unknown
David Rubin wrote: s[i] = (::isupper(s[i]) ? ::tolower(s[i]) : ::toupper(s[i]));
BTW, for those in the know who are still reading this thread, is* and to* are known to take an int argument to account for EOF. However, is it safe to assume that an explicit cast is unnecessary when applying these functions to a string? Presumably, a string will not contain EOF.
Although the 'is*()' and 'to*()' account for EOF, they do not account
for negative values of 'char' on platforms where 'char' is a signed
entity (at least, they are not required to; I would expect that library
implementers actually do account for this case). Thus, you have to cast
a 'char' to 'unsigned char' before passing them into these functions.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>
Dietmar Kuehl <di***********@yahoo.com> wrote in message news:<bm************@ID-86292.news.uni-berlin.de>... Although the 'is*()' and 'to*()' account for EOF, they do not account for negative values of 'char' on platforms where 'char' is a signed entity (at least, they are not required to; I would expect that library implementers actually do account for this case). Thus, you have to cast a 'char' to 'unsigned char' before passing them into these functions.
#include <algorithm>
#include <string>
#include <cctype>
template <int (*F) (int)>
int safe (unsigned char c) { return F(c); }
int main () {
std::string s;
std::transform(s.begin(), s.end(), s.begin(), safe<std::toupper>);
}
As a bonus, this also deals with the overloaded stuff in <locale> --
unless you actually wanted to call those. :)
- Shane sb******@cs.uic.edu (Shane Beasley) wrote: template <int (*F) (int)> int safe (unsigned char c) { return F(c); }
[...] std::transform(s.begin(), s.end(), s.begin(), safe<std::toupper>);
That's a nice one! :-)
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>
On 10 Oct 2003 04:29:29 -0700, sb******@cs.uic.edu (Shane Beasley)
wrote: Dietmar Kuehl <di***********@yahoo.com> wrote in message news:<bm************@ID-86292.news.uni-berlin.de>...
Although the 'is*()' and 'to*()' account for EOF, they do not account for negative values of 'char' on platforms where 'char' is a signed entity (at least, they are not required to; I would expect that library implementers actually do account for this case). Thus, you have to cast a 'char' to 'unsigned char' before passing them into these functions.
#include <algorithm> #include <string> #include <cctype>
template <int (*F) (int)> int safe (unsigned char c) { return F(c); }
Nice idea, but how about :
#include <string>
#include <functional>
template <int (*F) (int)>
struct safe_to: std::unary_function<char, char>
{
char operator()(char c) const {
return std::char_traits<char>::to_char_type(
F(std::char_traits<char>::to_int_type(c))
);
}
};
With luck, everything will be inlined since safe_to is a functor, and
F is a compile time constant.
Tom
tom_usenet wrote: #include <string> #include <functional>
template <int (*F) (int)> struct safe_to: std::unary_function<char, char> { char operator()(char c) const { return std::char_traits<char>::to_char_type( F(std::char_traits<char>::to_int_type(c))
I'm not sure what to_int_type does, but you don't want to promote a
negative char value to a negative int value. You want to promote a
negative char value to a non-negative (e.g., unsigned char) value, and
*then* to an int value (implicit in the call to std::tolower).
); } };
/david
--
Andre, a simple peasant, had only one thing on his mind as he crept
along the East wall: 'Andre, creep... Andre, creep... Andre, creep.'
-- unknown
On Mon, 13 Oct 2003 14:14:53 -0400, David Rubin
<bo***********@nomail.com> wrote: tom_usenet wrote:
#include <string> #include <functional>
template <int (*F) (int)> struct safe_to: std::unary_function<char, char> { char operator()(char c) const { return std::char_traits<char>::to_char_type( F(std::char_traits<char>::to_int_type(c))
I'm not sure what to_int_type does, but you don't want to promote a negative char value to a negative int value. You want to promote a negative char value to a non-negative (e.g., unsigned char) value, and *then* to an int value (implicit in the call to std::tolower).
to_int_type and to_char_type are for correctly converting between char
and int in the streams sense (e.g. map char to unsigned char values).
It saves on ugly casts (although looks pretty ugly itself). It also
readily converts between wchar_t and wint_t -
char_traits<wchar_t>::to_char_type(mywint);
Tom This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: TheDD |
last post by:
Hello,
i don't manage to use the tolower() function:
#include <algorithm>
#include <iostream>
#include <locale>
#include <string>
using std::cout;
|
by: humble04 |
last post by:
Hi,
I am compiling a collection of C++ code. Most of them are using the new
format #include <iostream>. I think all of them because I failed at
finding out which header file uses the old format ...
|
by: asbisht |
last post by:
Greetings to everyone.
#include<iostream>
main( void )
{
unsigned char value = 'A';
std::cout << tolower(value);
return 0;
}
|
by: Eric Lilja |
last post by:
Hello, consider this program:
#include <iostream>
#include <algorithm>
#include <string>
#include <cctype>
int
main()
{
std::string s = "HEJ";
|
by: beck2 |
last post by:
Hello everyone its Angela again. Can anyone help me please?
i want to convert uppercase characters to lower case using the <stdlib.h>
and the function tolower. for example i want to display "HELLO"...
|
by: Faray |
last post by:
Hello, this is my first post, so hopefully I am posting this in the right place.
Hopefully someone will be able to help me out with my problem here it is:
I need to make a program that ask a...
|
by: tgnelson85 |
last post by:
Hello,
I've managed to get my c++ code calling my c code, and i can call a function that prints something to the screen etc. However, i am trying to call the following C function:
char*...
|
by: nurulshidanoni |
last post by:
Dear all,
my algorith is like this
while(mor students)
read studentID
countexam=0
while (more examination)
read examcode
examID =get ExamID (examCode)
|
by: Soumen |
last post by:
I wanted convert a mixed case string to a lower case one. And I tried
following code:
std::transform(mixedCaseString.begin(), mixedCaseString::end(),
mixedCaseString.begin(),...
|
by: ryjfgjl |
last post by:
ExcelToDatabase: batch import excel into database automatically...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: Vimpel783 |
last post by:
Hello!
Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
|
by: jfyes |
last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
|
by: PapaRatzi |
last post by:
Hello,
I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: Shællîpôpï 09 |
last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
|
by: af34tf |
last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
| |