Thread: tolower error

  1. #16
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    That's just a hand-coded transform()... Why do that when you already have it? And yeah, std::tolower is probably the right way.
    That's right. It was just another solution. I thought that perhaps the OP would like to see how transform() works.

    I caught you in mid-edit when you said you suspected back_inserter to be the problem... back_inserter DOES return an output iterator -- this is the whole purpose of it.
    Yes, I figured that out eventually . . . sorry, I edited it out because I thought no one would have had time to read it. Evidently someone did.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  2. #17
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Livijn View Post
    17 C:\Users\Fredrik\Desktop\main.cpp no matching function for call to `transform(__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::back_insert_iterator<std::string>, string_lower(const std::string&)::lower)'
    You can't put the lower class inside the function. Move it outside into the global space.

    EDIT: Also, you could try what dwks said, and use std::tolower instead of just tolower. I bet that would work. My system is apparently too "helpful." Good demonstration of why it's important to compile your code under different compilers
    Last edited by brewbuck; 05-30-2007 at 03:44 PM.

  3. #18
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by dwks View Post
    That's right. It was just another solution. I thought that perhaps the OP would like to see how transform() works.
    Looking inside the STL headers can be tremendously informative. All kinds of cool, inspiring stuff in there.

    Yes, I figured that out eventually . . . sorry, I edited it out because I thought no one would have had time to read it. Evidently someone did.
    I saw it only by accident

  4. #19
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Quote Originally Posted by Livijn View Post
    17 C:\Users\Fredrik\Desktop\main.cpp no matching function for call to `transform(__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::back_insert_iterator<std::string>, string_lower(const std::string&)::lower)'
    Code:
    >   transform(str.begin(), str.end(), back_inserter(x), tolower);
    Code:
       transform(str.begin(), str.end(), back_inserter(x), ::tolower);
    I have no clue why. Apparently it finds the overloaded function this way. You can also create a custom to_lower(), and substitute that for tolower in the transform call.
    Code:
    char to_lower(char c)
    {
       return tolower(c);
    }

  5. #20
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  6. #21
    Registered User
    Join Date
    Jan 2007
    Posts
    188
    Errors:
    C:/Dev-Cpp/include/ctype.h: In function `std::string string_lower(const std::string&)':
    C:/Dev-Cpp/include/ctype.h:63: error: too few arguments to function `int tolower(int)'
    main.cpp:17: error: at this point in file

    C:/Dev-Cpp/include/c++/3.4.2/bits/stl_algo.h: In function `_OutputIterator std::transform(_InputIterator, _InputIterator, _OutputIterator, _UnaryOperation) [with _InputIterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _OutputIterator = std::back_insert_iterator<std::string>, _UnaryOperation = int]':
    main.cpp:17: instantiated from here
    C:/Dev-Cpp/include/c++/3.4.2/bits/stl_algo.h:789: error: `__unary_op' cannot be used as a function


    I'm getting annoyed :P

  7. #22
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Can you post your latest code?

  8. #23
    Registered User
    Join Date
    Jan 2007
    Posts
    188
    Code:
    #include <iostream>
    #include <cctype>
    #include <iterator>
    #include <algorithm>
    
    using namespace std;
    
    string string_lower(const string &str)
    {
           class lower
           {
                 public:
                        char operator()(char ch) { return tolower(ch); }
           };
    
       string x;
       transform(str.begin(), str.end(), back_inserter(x), std::tolower());
       return x;
    }
    
    int main(int argc, char *argv[])
    {
        //Alla våra svenska ord i en array
        string swedish[2];
        swedish[0] = "hej";
        swedish[1] = "vem";
        
        //Alla våra engelska ord i en array
        string english[2];
        english[0] = "hi";
        english[1] = "who";
        
        /*Alla ord ska ligga i ordning så att swedish[2] representerar det svenska ordet för english[2]*/
        //Precis XD
        
        string insert; //Namnet på stringen som användaren skriver in i
        int quantity = 3; //Hur många ord det finns + 1. Om det finns 2 frågor ska det vara 3 här. Om det är 4 frågor ska det vara 5 här.
        int done = 0; //Hur många ord som har blivit svarade
        int points = 0; //Hur många poäng man får
        
        //Skriver ut en text
        cout << "Här kommer du få svenska ord som du ska översätta!\nDå börjar vi!\n\n\n";
        
        //Kör en while-sats för att alla ord ska vara med
        while (done < quantity) 
        {
              cout << "Vad heter " << swedish[done] << " på engelska?\n"; //Skriver ut vad heter lala beronde på vilket ord det är
              cin >> insert; //Låter användaren skriva in ett ord
              
              string lower = string_lower(swedish[done]); //Gör alla bokstäver små
              
              if (english[done] == lower) //kollar om det är rätt
              {
                         points = points + 1; //Lägg till 1 poäng
              } 
        done++;
        }
        
        cout << "Du fick " << points << " poäng!";
    }

  9. #24
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Don't put the parentheses on std::tolower.

    I realize the parentheses are confusing. The reason for the difference is that std::tolower is a FUNCTION, which can serve directly as the functor of the transform. On the other hand, the hand-cooked lower class is not a function, but a CLASS. When you INSTANTIATE the class (using the () after the name, which is a constructor call), you get an OBJECT which acts as a functor.

    When you add the () to the end of std::tolower(), you actually CALL the function. This function returns an int, so the transform() call is getting passed an integer as a functor, which is invalid.

  10. #25
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    You should also #include <string> since you are using the string class.

  11. #26
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Quote Originally Posted by brewbuck View Post
    Don't put the parentheses on std::tolower.

    I realize the parentheses are confusing. The reason for the difference is that std::tolower is a FUNCTION, which can serve directly as the functor of the transform. On the other hand, the hand-cooked lower class is not a function, but a CLASS. When you INSTANTIATE the class (using the () after the name, which is a constructor call), you get an OBJECT which acts as a functor.

    When you add the () to the end of std::tolower(), you actually CALL the function. This function returns an int, so the transform() call is getting passed an integer as a functor, which is invalid.
    Some people prefer the syntax
    Code:
    &tolower
    because it makes it clear that you're taking the address of a function. It is, believe it or not, the same as
    Code:
    tolower
    just as
    Code:
    int (*to_something)(int) = tolower;
    to_something('a');
    is the same as
    Code:
    int (*to_something)(int) = tolower;
    (*to_something)('a');
    There are two arguments as to which is better. Personally, I use tolower and (*to_something)(). Don't ask me why.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  12. #27
    Registered User
    Join Date
    Jan 2007
    Posts
    188
    Still gets an error:
    18 C:\Users\Fredrik\Desktop\main.cpp no matching function for call to `transform(__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::back_insert_iterator<std::string>, <unknown type>)'

    Code:
    Code:
    #include <iostream>
    #include <cctype>
    #include <iterator>
    #include <algorithm>
    #include <string>
    
    using namespace std;
    
    string string_lower(const string &str)
    {
           class lower
           {
                 public:
                        char operator()(char ch) { return tolower(ch); }
           };
    
       string x;
       transform(str.begin(), str.end(), back_inserter(x), tolower);
       return x;
    }
    
    int main(int argc, char *argv[])
    {
        //Alla v&#229;ra svenska ord i en array
        string swedish[2];
        swedish[0] = "hej";
        swedish[1] = "vem";
        
        //Alla v&#229;ra engelska ord i en array
        string english[2];
        english[0] = "hi";
        english[1] = "who";
        
        /*Alla ord ska ligga i ordning s&#229; att swedish[2] representerar det svenska ordet f&#246;r english[2]*/
        //Precis XD
        
        string insert; //Namnet p&#229; stringen som anv&#228;ndaren skriver in i
        int quantity = 3; //Hur m&#229;nga ord det finns + 1. Om det finns 2 fr&#229;gor ska det vara 3 h&#228;r. Om det &#228;r 4 fr&#229;gor ska det vara 5 h&#228;r.
        int done = 0; //Hur m&#229;nga ord som har blivit svarade
        int points = 0; //Hur m&#229;nga po&#228;ng man f&#229;r
        
        //Skriver ut en text
        cout << "H&#228;r kommer du f&#229; svenska ord som du ska &#246;vers&#228;tta!\nD&#229; b&#246;rjar vi!\n\n\n";
        
        //K&#246;r en while-sats f&#246;r att alla ord ska vara med
        while (done < quantity) 
        {
              cout << "Vad heter " << swedish[done] << " p&#229; engelska?\n"; //Skriver ut vad heter lala beronde p&#229; vilket ord det &#228;r
              cin >> insert; //L&#229;ter anv&#228;ndaren skriva in ett ord
              
              string lower = string_lower(swedish[done]); //G&#246;r alla bokst&#228;ver sm&#229;
              
              if (english[done] == lower) //kollar om det &#228;r r&#228;tt
              {
                         points = points + 1; //L&#228;gg till 1 po&#228;ng
              } 
        done++;
        }
        
        cout << "Du fick " << points << " po&#228;ng!";
    }

  13. #28
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Hmm, that's weird. On every compiler I have access to (Dinkumware's various ones) your source compiles perfectly.

    Did you re-compile it properly?
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  14. #29
    Registered User
    Join Date
    Jan 2007
    Posts
    188
    I got Dev-C++ and it wont work

  15. #30
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Which version? Probably 4.9.something?

    It looks like your compiler is still having trouble figuring out what tolower is.
    Code:
    18 C:\Users\Fredrik\Desktop\main.cpp no matching function for call to `transform(
        ...::__normal_iterator<..., std::basic_string<...> >,
        ...::__normal_iterator<..., std::basic_string<...> >,
        std::back_insert_iterator<std::string>,
        <unknown type>)'
    So perhaps your tolower() is implemented as a macro or something. I'd suggest looking at <cctype> or going
    Code:
    #undef tolower
    to see if that is the case. If it is, you'll have to add a wrapper around tolower() as suggested.
    Code:
    int func_tolower(int c) { return tolower(c); }
    transform(str.begin(), str.end(), back_inserter(x), func_tolower);
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. An error is driving me nuts!
    By ulillillia in forum C Programming
    Replies: 5
    Last Post: 04-04-2009, 09:15 PM
  3. Making C DLL using MSVC++ 2005
    By chico1st in forum C Programming
    Replies: 26
    Last Post: 05-28-2008, 01:17 PM
  4. Connecting to a mysql server and querying problem
    By Diod in forum C++ Programming
    Replies: 8
    Last Post: 02-13-2006, 10:33 AM
  5. Couple C questions :)
    By Divx in forum C Programming
    Replies: 5
    Last Post: 01-28-2003, 01:10 AM