String Capitalization Converting

Dec 31, 2010 at 5:15am
Currently, the only way I know how to convert a string to lowercase and uppercase are by:

1
2
3
#include <algorithm>

transform ( answ.begin(), answ.end(), answ.begin(), ptr_fun(::tolower) );


What are alternatives that are more reliable and simple?

Also: How complicated would it be to make a Library File/Header File (not sure which is required) that I can #include and then use a simple command to activate

example:

1
2
3
4
5
6
7
#include <"mystrconv.h">

(...)

strconvertlower(stringvariablenamehere);

Dec 31, 2010 at 5:39am
That's not complicated at all! Simply define your function in a file mystrconv.c, declare it it mystrconv.h, and when you use it, #include mystrconv.h into main.c, and compile like this:
g++ main.c mystrconv.c -o main

If you use an IDE I dunno how it works for your IDE but for most there is a "pass compiler options" box.
Last edited on Dec 31, 2010 at 5:40am
Dec 31, 2010 at 6:09am
I appreciate that piece of information;

I use Code::Blocks as an IDE, and in regards to creating my files:
I am using cpp, not c, so wouldn't my files be Main.cpp and MyStrConv.cpp?

Example (I think?)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <string>
#include <"mystrconv.h">
using namespace std;

int main()
{
     string string_xyz = "HI HI HI";

     strconvertlower(string_xyz);

     cout << string_xyz << "\n"; //produces "hi hi hi"
     return 0;
}

Last edited on Dec 31, 2010 at 6:09am
Dec 31, 2010 at 10:37am
If you like, they can be .cpp and .hpp. whatever.
Dec 31, 2010 at 2:31pm
Don't use angle brackets on user-side includes.

 
#include "mystrconv.h" 


Personally, I would have coded it more like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef STRLOWER_HPP
#define STRLOWER_HPP

#include <algorithm>
#include <cctype>
#include <functional>
#include <string>

inline std::string& strlwr( std::string& s )
  {
  std::transform( s.begin(), s.end(), s.begin(), std::ptr_fun <int, int> ( std::tolower ) );
  return s;
  }

inline std::string strlower( const std::string& s )
  {
  std::string result( s );
  return strlwr( result );
  }

#endif  

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <string>
using namespace std;

#include "strlower.hpp"

int main()
  {
  cout << strlower( "HELLO WORLD!\n" );
  return 0;
  }

:-)
Dec 31, 2010 at 8:21pm
Edit: Ohkay, I implemented that into a program and it works wonders; except:

In some instances strlower(stringname); doesn't do the job, but if I do

strlower(stringname); strlwr(stringname);

it does.

What is the difference between the two, and why do I need to run them both in some instances?


I put the .h file in this code (with my custom modifications to include an uppercase as well)
http://codepad.org/d0LCSBqe

Please note: after the .h file is the .cpp file, they are on one codepad page.
Last edited on Dec 31, 2010 at 8:43pm
Dec 31, 2010 at 9:39pm
Look at the function signatures, they have different side effects.

strlower makes a copy of the string you give it, changes case, and returns the copy. Well, a copy of the copy....

Anywho, strlwr() does what your original function does, and changes the string you pass it in-place.

Hence:
1
2
3
string s = "Hello world!";
strlwr( s );
cout << s << endl;
works as you would expect. But:
1
2
3
string s = "Hello world!";
strlower( s );
cout << s << endl;
does not, since s was not modified (and the lowercased string returned from the function was thrown away). Fix it thus:
1
2
3
string s = "Hello world!";
s = strlower( s );
cout << s << endl;
Now it works, because you copy the result of the lowercased string into s.

The nice part about the strlower() version is that you can say things like:
 
cout << strlower( "Hello world!" ) << endl;
Whereas you cannot with the strlwr() version.

Looking at it again, I suppose it might have been smarter of me to just name the functions identically, so the compiler can choose the proper overload for you.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef STRLOWER_HPP
#define STRLOWER_HPP

#include <algorithm>
#include <cctype>
#include <functional>
#include <string>

inline std::string& strlower( std::string& s )
  {
  std::transform( s.begin(), s.end(), s.begin(), std::ptr_fun <int, int> ( std::tolower ) );
  return s;
  }

inline std::string strlower( const std::string& s )
  {
  std::string result( s );
  return strlower( result );
  }

#endif   

Hope this helps.
Dec 31, 2010 at 11:14pm
Very much so! People like you who are willing to take a little time to explain things in this depth make programming much more enjoyable!

I now completely understand what I was missing, and personally I think it might be cooler to leave them as two separate functions, it would avoid any possible mix-ups between the two. I just didn't fully understand what I was doing, and if that's the case I'm basically accomplishing nothing in the long run.. heh.
Topic archived. No new replies allowed.