Thread: strlwr() and delimiter removal

  1. #1
    Registered User kryptkat's Avatar
    Join Date
    Dec 2002
    Posts
    638

    strlwr() and delimiter removal

    20 C:\Dev-Cpp\project333 misc\stringtolowercvc.cpp cannot convert `std::string' to `char*' for argument `1' to `char* strlwr(char*)'
    but all i want to do is convert the entire string to lower case.
    Code:
       string s;
      while(getline(in, s )) { // Discards newline char
      out << strlwr(s) ;
    } // end while
    also tried
    Code:
        string s;
        while(getline(in, strlwr(s) ) ) {
        out << s ;
        }
    same error but but but but it work in c. included are iostream string even tried cstring. fstream for file rw.

    after doing several searchs i found transform() i would like to stick with strlwr() that i know for now. read through thinking in cpp vol 1. looking for some type of clue to get it working. even tried strlwr(&s) nope.

    delimiter prob
    25 C:\Dev-Cpp\project333 misc\stringuntokin.cpp `get' undeclared (first use this function)
    29 C:\Dev-Cpp\project333 misc\stringuntokin.cpp no match for 'operator!=' in '(&words)->std::vector<_Tp, _Alloc>::operator[] [with _Tp = std::string, _Alloc = std::allocator<std::string>](((unsigned int)i)) != '.''
    29 C:\Dev-Cpp\project333 misc\stringuntokin.cpp no match for 'operator!=' in '(&words)->std::vector<_Tp, _Alloc>::operator[] [with _Tp = std::string, _Alloc = std::allocator<std::string>](((unsigned int)i)) != ',''
    yes same error twice
    Code:
    int main() {
       vector<string> words;
     ifstream in(...
    ofstream out(...
    string word;
        // string s;
      //while(getline(in, s)) // Discards newline char
        //out << s ;          // outline
      
       while(get(in , word) )
        words.push_back(word); 
      for(int i = 0; i < words.size(); i++) {
        cout << words[i] ; //endl removed 
         while(words[i] != '.' | words[i] != ',' )   out << words[i] ;
         }
    try change getline() to get(). prob is with while delimiter removal.

  2. #2
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Well as of your first function, strlwr() is looking for a const char *, you are supplying a std::string so the quick fix for this is to edit the call to strlwr() like so:
    Code:
    strlwr(s.c_str());
    Not sure about the rest...
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by kryptkat
    after doing several searchs i found transform() i would like to stick with strlwr() that i know for now. read through thinking in cpp vol 1. looking for some type of clue to get it working. even tried strlwr(&s) nope.
    The problem is that strlwr(), which is not in the C++ standard library, changes the string. As such, jeffcobb's suggestion does not work.

    So, you have a few choices: you could allocate space for a null terminated string, copy over the contents of your std::string, and only then apply strlwr(), but then you will be stuck with a null terminated string whose allocated memory needs to be managed manually.

    Alternatively, you could pass &s[0] as the argument, but it is not guaranteed to work at this point of time, though it most likely will (but you should push_back() a null character before using it in this way). You can avoid this uncertainty by using a std::vector<char> and passing &v[0] instead, where v is the vector with enough space to store the null terminated string... but frankly you are better off learning how to use transform().
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Quote Originally Posted by laserlight View Post
    The problem is that strlwr(), which is not in the C++ standard library, changes the string. As such, jeffcobb's suggestion does not work.
    .
    My mistake, just looked it up, thought it did take a const char * but nope I was wrong. Just checked some old code, I did it once like so:
    Code:
    string myStrLwr(string in)
    {
       string strOut = "";
       for(unsigned pos = 0; pos < in.size(); pos++)
       {
          char c = tolower(in.at(pos));
          strOut.push_back(c);
       }
       return strOut;
    
    }
    Sorry for the confusion...

    Jeff

    Note: this *does* work; just recompiled and tested myself ^__^
    Last edited by jeffcobb; 12-28-2009 at 11:39 AM. Reason: added line about test
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Ah, but then you might as well use std::transform, e.g.,
    Code:
    string myStrLwr(string in)
    {
        transform(in.begin(), in.end(), in.begin(), ::tolower);
        return in;
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Quote Originally Posted by laserlight View Post
    Ah, but then you might as well use std::transform, e.g.,
    Code:
    string myStrLwr(string in)
    {
        transform(in.begin(), in.end(), in.begin(), ::tolower);
        return in;
    }
    Yep might as well. YAWTSAC (Yet Another Way To Skin A Cat)...I never said this was the only way, just what I had written some time ago that worked...
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  7. #7
    Registered User kryptkat's Avatar
    Join Date
    Dec 2002
    Posts
    638
    using transform() what about the delimiter removal ? how to use transform to remove delimiters ?
    Code:
       while(words[i] != '.' | words[i] != ',' )   out << words[i] ;
    when i tried to use "char q[] = "test string"; " in a class i got can not covert const string. so put it in main() also tried file read. i know the prob is std::string is not char *s or not pointer to char. is not string. transform requires vector ? or algorithm ? for include. do not understand why transform need begin twice ?

    lazerlight
    when return in is that in in memory or does it write back to file or second file like
    Code:
    string myStrLwr(string in)
    {
        transform(in.begin(), in.end(), in.begin(), ::tolower);
        return in;
    }
        out <<  in // filetwo.txt
    thank you both

    YAWTSAC (Yet Another Way To Skin A Cat)
    <shudders>
    Last edited by kryptkat; 12-28-2009 at 12:44 PM.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by kryptkat
    using transform() what about the delimiter removal ? how to use transform to remove delimiters ?
    You need to elaborate on what exactly is this delimiter removal about.

    Quote Originally Posted by kryptkat
    transform requires vector ? or algorithm ? for include.
    <algorithm> is the correct header.

    Quote Originally Posted by kryptkat
    do not understand why transform need begin twice ?
    In my example, I am applying transform to the elements of the string, and then assigning the result to those same elements.

    Quote Originally Posted by kryptkat
    when return in is that in in memory or does it write back to file or second file like
    jeffcobb's myStrLwr example is a function that takes a std::string argument by value and returns a std::string object. It has nothing to do with files. Personally, I would have taken the argument by non-const reference and modified it as demonstrated in my example. In such a case, the return type can be void.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User kryptkat's Avatar
    Join Date
    Dec 2002
    Posts
    638
    19 C:\Dev-Cpp\project333 misc\stringtolowercase.cpp a function-definition is not allowed here before '{' token
    this is the error i got when i tried
    Code:
    string myStrLwr(string in)
    {
        transform(in.begin(), in.end(), in.begin(), ::tolower);
        return in;
    }
    i was writing to files my bad. i put that in main ().

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by kryptkat
    i put that in main ().
    It is a function definition, and functions cannot be defined within other functions.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by kryptkat View Post
    this is the error i got when i tried
    Code:
    string myStrLwr(string in)
    {
        transform(in.begin(), in.end(), in.begin(), ::tolower);
        return in;
    }
    i was writing to files my bad. i put that in main ().
    I've seen problems like that before, relating to the fact that tolower() is a macro. It's not SUPPOSED to be a macro if you include <cctype> instead of <ctype.h>, but some library implementations are broken, go figure. Try this:

    Code:
    char MyToLower( char ch )
    {
        return tolower( ch );
    }
    
    string myStrLwr(string in)
    {
        transform(in.begin(), in.end(), in.begin(), MyToLower);
        return in;
    }
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  12. #12
    Registered User kryptkat's Avatar
    Join Date
    Dec 2002
    Posts
    638
    i realized it was a function definition after i got the error.

    Code:
    /* stringtolowercase.cpp */
    
    #include <iostream>
    #include <string>
    #include <fstream>
    #include <algorithm>
    #include <cctype>
    
    using namespace std;
    
    char MyToLower( char ch )
    {
        return tolower( ch );
    }
    
    string myStrLwr(string in)
    {
        transform(in.begin(), in.end(), in.begin(), MyToLower);
        return in;
    }
    
    int main() {
        ifstream in("filetext.txt");
        ofstream out("filetextoutlowercase.txt");
    
    //     string s;
    // while(getline(in, s)) // Discards newline char
    //    out << s << "\n"; // ... must add it back
      
    // want to convert entire file to lower case get stuck here 
    
    // 
    
    
    out << fget( MyToLower(in) )  ;
    
    }
    yikes.

  13. #13
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Quote Originally Posted by kryptkat View Post
    // want to convert entire file to lower case get stuck here
    In the simple case it's the same code as lowercasing the string, just with different iterators.

    Code:
    #include <iterator>
    
    int main() {
        ifstream in("filetext.txt");
        ofstream out("filetextoutlowercase.txt");
    
        if(!(in && out))
        {
             // handle error
        }
    
        std::transform(
            std::istreambuf_iterator<char>(in),
            std::istreambuf_iterator<char>(),
            std::ostreambuf_iterator<char>(out),
            MyToLower
        );
        // 'out' now contains a lowercased version of in
    If the file contains wide chars then change the type of the iterators to wchar_t. If the file contains other types of multibyte characters then chances are it'll need extra effort to do the right thing.

  14. #14
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Quote Originally Posted by laserlight View Post
    You need to elaborate on what exactly is this delimiter removal about.


    <algorithm> is the correct header.


    In my example, I am applying transform to the elements of the string, and then assigning the result to those same elements.


    jeffcobb's myStrLwr example is a function that takes a std::string argument by value and returns a std::string object. It has nothing to do with files. Personally, I would have taken the argument by non-const reference and modified it as demonstrated in my example. In such a case, the return type can be void.
    I should have done it by reference but figured the heart of the method was what was of educational value (if any)...as for doing it as a file, I would have mmapped the file and iterated over the contents that way...simple and fast.
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  15. #15
    Registered User kryptkat's Avatar
    Join Date
    Dec 2002
    Posts
    638
    // 'out' now contains a lowercased version of in
    ok it compiles but how do you get it to write to the file ? i tried out << out and nothing in the file. have been using string s and doing out << s which works. so would something like
    Code:
      string s; 
       out << s(out) ;
    work ?

    nope got
    44 C:\Dev-Cpp\project333 misc\stringtolowercvc.cpp no match for call to `(std::string) (std::ofstream&)'
    Last edited by kryptkat; 12-29-2009 at 10:58 AM.

Popular pages Recent additions subscribe to a feed