maltoshi
maltoshi

Reputation: 87

Using toupper on char returns the ascii number of the char, not the character?

int main()
{

char hmm[1000];

cin.getline(hmm, 1000);
cout << hmm << endl;    //this was to test if I could assign my input to the array properly
for (int sayac = 0; hmm[sayac] != '@'; sayac++) {
    if (!isdigit(hmm[sayac])) {
        if (islower(hmm[sayac])) 
            cout << toupper(hmm[sayac]);
        else if (isupper(hmm[sayac]))
            cout << tolower(hmm[sayac]);
        else
            cout << hmm[sayac];
    }
}

"Write a program that reads keyboard input to the @ symbol and that echoes the input except for digits, converting each uppercase character to lowercase, and vice versa. (Don’t forget the cctype family.) "

I'm doing this exercise from the primer book. But when I run it, it returns the ascii order of the char, not the uppercase/lowercase version of the character. Couldn't figure out the problem. Can someone tell my why please?

(I may have other problems about the exercise, please don't correct them if I have. I want to fix it on my own (except the problem I explained), but I can't check the other ones as I have this problem.

Upvotes: 4

Views: 1820

Answers (2)

Fran&#231;ois Andrieux
Fran&#231;ois Andrieux

Reputation: 29022

It's a question of representation. There is no difference between a character and that character's numeric value. It's all in how you choose to display it. For example, the character 'a' is just a constant with a value equal to the character's numeric value.

The problem you are having is that std::toupper and std::tolower return an int rather than a char. One reason for that is that they handle EOF values, which are not necessarily representable by char. As a consequence, std::cout see you are trying to print an int and not a char. The standard behavior for streaming an int is to print the number. The solution is then to cast your result to char to force the value to be interpreted as a character. You can use something like std::cout << static_cast<char>(std::toupper(hmm[sayac]));.

Try the following :

#include <cctype>
#include <iostream>

int main()
{
    char hmm[1000];

    std::cin.getline(hmm, 1000);
    std::cout << hmm << std::endl;    //this was to test if I could assign my input to the array properly
    for (int sayac = 0; hmm[sayac] != '@'; sayac++) {
        if (!std::isdigit(hmm[sayac])) {
            if (std::islower(hmm[sayac]))
                std::cout << static_cast<char>(std::toupper(hmm[sayac]));
            else if (isupper(hmm[sayac]))
                std::cout << static_cast<char>(std::tolower(hmm[sayac]));
            else
                std::cout << hmm[sayac];
        }
    }
}

You should also consider using an std::string instead of an array of char of arbitrary length. Also, take note that you have undefined behavior if the input string does not contain @.

Upvotes: 2

YSC
YSC

Reputation: 40100

When writing

std::cout << toupper('a');

the following happen:

  1. int toupper(int ch) is called, and returns an integer whose value is 'A' (0x41).
  2. std::basic_ostream::operator<<(std::cout, 0x41) is called, that is the int (2) overload since an int was provided.

Overall, it prints "65".

As a solution, you can cast back your upper case to a char:

std::cout << static_cast<char>(toupper('a'));

Upvotes: 6

Related Questions