1

I was trying to write a program which will convert every word(either upper or lower case) in the upper or lower case(depending on which case is max).So here is my program

#include<iostream>
#include<cstring>
#include<cctype>
#include<cstdio>
using namespace std;
int main()
{
    char s[101];
    int c=0, sm=0, i;

    cin>>s;

    for(i=0;i<strlen(s);i++)
    {
        if(s[i]>='A' && s[i]<='Z')
            c++;
        else
            sm++;
    }

    if(sm>c)
    {
        for(i=0;i<strlen(s);i++)
        {
            //cout<<tolower(s[i])<<endl;
            putchar(tolower(s[i]));
        }
    }
    else
    {
        for(i=0;i<strlen(s);i++)
        {
            //cout<<toupper(s[i])<<endl;
            putchar(toupper(s[i]));
        }
    }
}

But i was surprised to see that if i write these statement

if(sm>c)
    {
        for(i=0;i<strlen(s);i++)
        {
            cout<<tolower(s[i])<<endl;                
        }
    }

or

else
    {
        for(i=0;i<strlen(s);i++)
        {
            //cout<<toupper(s[i])<<endl;
            putchar(toupper(s[i]));
        }
    }

then it seems that output is in ASCII number.Can anyone explain me these reason.I am new to c++, so not much aware of cout

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
mahin hossen
  • 175
  • 9
  • 2
    `toupper()` is a function that accepts an argument of type `int`, and returns an `int`. Streaming an `int` to `cout` (or any stream) outputs the numeric value. If you want the corresponding `char`, convert back to `char` before outputting. – Peter Dec 28 '18 at 15:18
  • 1
    @Peter Use the answer section please. Hover your mouse over the "add a comment" link to discover what comments are for. Thanks – Lightness Races in Orbit Dec 28 '18 at 15:50

6 Answers6

4

The reason behind this is the tolower(). The return type of tolower() is int.

That means its equivalent to printing an integer, rather than a character.

If you want to show it correctly, use this:

cout << static_cast<char>(tolower(s[i])) << "\n";
Kunal Puri
  • 3,419
  • 1
  • 10
  • 22
3

std::tolower() and std::toupper() functions return value is int. And std::cout print the exact value that appears to it.

So cout<< tolower(s[i])<<endl print ASCII value of the characters. But when you write putchar(toupper(s[i])) then putchar() function automatically converts the ASCII value to characters. That's why you get character as output.

In order to use cout<< tolower(s[i]) << endl you need to typecast the ASCII value to character.

So write -

cout<< (char)(toupper[i]) <<endl;
cout<< (char)(tolower[i]) <<endl;
YSC
  • 38,212
  • 9
  • 96
  • 149
Faruk Hossain
  • 1,205
  • 5
  • 12
  • 2
    Thanks.Didn't know **tolower(), toupper() functions return value is int**.But thought it might be,but was surprised to see that putchar worked!!.Now i can understand,why it happend.Thanks for the answer – mahin hossen Dec 28 '18 at 15:28
  • @mahinhossen that is what happens when you don't read the documentation – Remy Lebeau Dec 28 '18 at 18:48
3

Just to add that this is a false comparison.

The C++ equivalent of putchar is ostream::put, like this:

std::cout.put(std::tolower(s[i]));

Because both this and putchar take a char, an implicit conversion is performed. This is necessary because tolower gives you an int (for historical reasons, sort of).

The streaming operator << is far more general, and has overloads for all sorts of types so that it can format your data for you. Since you're giving it an int, and not particularly asking for a char, a number is what you get.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
1

From the cplusplus.com reference for tolower:

The value is returned as an int value that can be implicitly casted to char.

However printing the returned int will not convert it to a char. You can explicitly cast it:

std::cout<< (char) tolower(s[i])<<endl;  

However a static cast is safer:

std::cout << static_cast<char>(tolower(s[i]));
Cubbi
  • 46,567
  • 13
  • 103
  • 169
GBlodgett
  • 12,704
  • 4
  • 31
  • 45
0

cout prints the value, and in C++ a tolower returns a int (ASCII) so what you get is that, if you want to yell the actual character you need to convert manually the output.

cout<<static_cast<char>((s[i]))<<endl;

Online editor to C++ (example)

  • 2
    It's very intelligent, which is why it's doing what the code asked it to! Taking an integer and printing its ASCII equivalent instead would be very stupid and annoying. – Lightness Races in Orbit Dec 28 '18 at 15:47
  • `static_cast` is not required in the example that you gave in answer. Even without that, I expected it to work and It did. Because different overloads of << is provided for different data types. If you are passing a `char` as a parameter to << operator, its ASCII value won't be printed. – Kunal Puri Dec 28 '18 at 15:50
0

In this case:

if(sm>c)
    {
        for(i=0;i<strlen(s);i++)
        {
            cout<<tolower(s[i])<<endl;                
        }
    }

yes you should expect an ASCII value. This is because tolower is a function that returns an integer and cout outputs directly what it is given, it doesnt carry out any manipulation.

However you said that in this case:

else
    {
        for(i=0;i<strlen(s);i++)
        {
            //cout<<toupper(s[i])<<endl;
            putchar(toupper(s[i]));
        }
    }

you also get an ASCII value but I think your mistaken. This should output a character because the putchar() function not only outputs what it is given but beforehand carries out manipulation to ensure it is in char format.