14

I'm trying to convert a string to lowercase, and am treating it as a char* and iterating through each index. The problem is that the tolower function I read about online is not actually converting a char to lowercase: it's taking char as input and returning an integer.

cout << tolower('T') << endl;

prints 116 to the console when it should be printing T.

Is there a better way for me to convert a string to lowercase? I've looked around online, and most sources say to "use tolower and iterate through the char array", which doesn't seem to be working for me.

So my two questions are:

  1. What am I doing wrong with the tolower function that's making it return 116 instead of 't' when I call tolower('T')

  2. Are there better ways to convert a string to lowercase in C++ other than using tolower on each individual character?

LogicStuff
  • 19,397
  • 6
  • 54
  • 74
user83676
  • 339
  • 1
  • 9
  • 15

6 Answers6

22

That's because there are two different tolower functions. The one that you're using is this one, which returns an int. That's why it's printing 116. That's the ASCII value of 't'. If you want to print a char, you can just cast it back to a char.

Alternatively, you could use this one, which actually returns the type you would expect it to return:

std::cout << std::tolower('T', std::locale()); // prints t

In response to your second question:

Are there better ways to convert a string to lowercase in C++ other than using tolower on each individual character?

Nope.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • 1
    The better war is to use ICU: http://stackoverflow.com/questions/313970/how-to-convert-stdstring-to-lower-case – Alan Stokes Nov 21 '15 at 23:13
  • 1
    Actually, there are other ways to convert a string to lowercase. For example, the difference between an ASCII 'T' and 't' is 0x20. So if one ORs or add 0x20 to an uppercase ASCII letter, the letter will become lowercase. Again, this is true for ASCII alphabets. If you need other code pages, this method won't work. Whether or not this is "best" depends on the environment and the project. – Thomas Matthews Nov 22 '15 at 00:21
3

116 is indeed the correct value, however this is simply an issue of how std::cout handles integers, use char(tolower(c)) to achieve your desired results

std::cout << char(tolower('T')); // print it like this
user4578093
  • 231
  • 1
  • 3
  • 10
2

It's even weirder than that - it takes an int and returns an int. See http://en.cppreference.com/w/cpp/string/byte/tolower.

You need to ensure the value you pass it is representable as an unsigned char - no negative values allowed, even if char is signed.

So you might end up with something like this:

char c = static_cast<char>(tolower(static_cast<unsigned char>('T')));

Ugly isn't it? But in any case converting one character at a time is very limiting. Try converting 'ß' to upper case, for example.

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
1

To lower is int so it returns int. If you check #include <ctype> you will see that definition is int tolower ( int c ); You can use loop to go trough string and to change every single char to lowe case. For example

while (str[i]) // going trough string 
{
  c=str[i]; // ging c value of current char in string 
  putchar (tolower(c)); // changing to lower case      
  i++;  //incrementing 
}
1

the documentation of int to_lower(int ch) mandates that ch must either be representable as an unsigned char or must be equal to EOF (which is usually -1, but don't rely on that).

It's not uncommon for character manipulation functions that have been inherited from the c standard library to work in terms of ints. There are two reasons for this:

  1. In the early days of C, all arguments were promoted to int (function prototypes did not exist).

  2. For consistency these functions need to handle the EOF case, which for obvious reasons cannot be a value representable by a char, since that would mean we'd have to lose one of the legitimate encodings for a character.

http://en.cppreference.com/w/cpp/string/byte/tolower

The answer is to cast the result to a char before printing.

e.g.:

std::cout << static_cast<char>(std::to_lower('A'));
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
0

Generally speaking to convert an uppercase character to a lowercase, you only need to add 32 to the uppercase character as this number is the ASCII code difference between lowercase and uppercase characters, e.g., 'a'-'A'=97-67=32.

char c = 'B';
c += 32; // c is now 'b'
printf("c=%c\n", c);

Another easy way would be to first map the uppercase character to an offset within the range of English alphabets 0-25 i.e. 'a' is index '0' and 'z' is index '25' inclusive and then remap it to a lowercase character.

char c = 'B';
c = c - 'A' + 'a'; // c is now 'b'
printf("c=%c\n", c);
hmofrad
  • 1,784
  • 2
  • 22
  • 28