4

for the following function

void display()
{
    for (int i = 0; i < 8; i++)
    {
        for (int j = 0; j < 8; j++)
        {
            if (board[i][j] < 84 && (i+j)%2 == 0)
                SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0x70);
            else if (board[i][j] < 84 && (i+j)%2 == 1)
                SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xc0);
            else if (board[i][j] > 97 && (i+j)%2 == 0)
                SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0x7c);
            else if (board[i][j] > 97 && (i+j)%2 == 1)
                SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xc7);
            cout << " " << toupper(board[i][j]) << " ";
        }
        cout << endl;
    }
}

instead of returning chars for the char board[8][8] it returns integers so my output looks like

 82  78  66  81  75  66  78  82

 80  80  80  80  80  80  80  80 

 32  32  32  32  32  32  32  32 

 32  32  32  32  32  32  32  32 

 32  32  32  32  32  32  32  32 

 32  32  32  32  32  32  32  32 

 80  80  80  80  80  80  80  80 

 82  78  66  81  75  66  78  82 

rather than the expected output of

 R  N  B  Q  K  B  N  R

 P  P  P  P  P  P  P  P




 P  P  P  P  P  P  P  P

 R  N  B  Q  K  B  N  R

I have also tried declaring a char a = board[i][j]; cout << toupper(a); in an attempt to confirm the variable type as a character and received the same output.

this is an assignment for a class so i don't expect much help, i just want to know why my function is returning integers in place of chars so that i know what my mistake is for future reference, Google didn't help much. is it some sort of scope issue with toupper?

wallyk
  • 56,922
  • 16
  • 83
  • 148
jeremy south
  • 161
  • 1
  • 3
  • 1
    Have you tried casting the return value of `toupper`? – Captain Obvlious Sep 21 '14 at 19:57
  • Why no google up first for reference? – Abhi Sep 21 '14 at 19:57
  • If you just want a function that converts ASCII upper to ASCII lower characters, I suggest using (or writing) a function specific to this encoding. Such a function can then be type-safe, i.e. deal with `char`s instead of `int`s, and does not need to deal with locales (-> faster). – dyp Sep 21 '14 at 20:12

4 Answers4

5

The intention for toupper is that it can work in other languages than English, and hence it would have to support input and output which is larger than the 8 bit char, and therefor should return something which can be transformed into a unicode or UTF-character.

Simply just casting it to char is probably a source of buggy code for later on depending on what the purpose of your software is.

Have a look at this question on how to use it for wide characters and unicode.

Convert a unicode String In C++ To Upper Case

Community
  • 1
  • 1
Soren
  • 14,402
  • 4
  • 41
  • 67
  • 3
    C, §7.4 "The header `` declares several functions useful for classifying and mapping characters. In all cases **the argument is an `int`, the value of which shall be representable as an `unsigned char` or shall equal the value of the macro `EOF`**. If the argument has any other value, the behavior is undefined." That the parameter is not a `char` has nothing to do with Unicode. It probably has nothing to do with locales, either. See http://stackoverflow.com/q/17452847 and http://stackoverflow.com/q/5919735 – dyp Sep 21 '14 at 20:14
  • You are quoteing "C" standard, but the question is about "C++", and the functions are reportedly working for std::wchar according to http://stackoverflow.com/questions/17991431/convert-a-unicode-string-in-c-to-upper-case -- I have not tried this myself, and I have not looked up the C++ standard if the "undefined" behavior in C is defined in C++ – Soren Sep 21 '14 at 20:20
  • Those are functions "imported" from the C Standard Library into C++. They are not explicitly defined for C++, but only via reference to the C Standard. `wchar_t` etc are not necessarily related to Unicode either. Since on typical implementations, an `unsigned char` can represent values in [0, 255], it cannot be used for e.g. UTF-8 directly. – dyp Sep 21 '14 at 20:23
  • As far as I can see from glancing over those answer at http://stackoverflow.com/questions/17991431/convert-a-unicode-string-in-c-to-upper-case they all DO NOT work reliably or properly. `wchar_t` in most \*nix systems has 32 bits and therefore *can* be used to store a Unicode code point / UTF-32 code unit. On Windows systems, it has 16 bits and is therefore not enough to contain a code point. Also, proper treatment e.g. of German ß is almost impossible: `BUSSE` can either be `buße` or `busse`, depending on what's meant; the former cannot be done on per-character basis. – dyp Sep 21 '14 at 20:27
  • *"Since on typical implementations, an unsigned char can represent values in [0, 255], it cannot be used for e.g. UTF-8 directly."* I have to qualify that: It can be used to *store* a UTF-8 code unit, but no additional information can be (portably) passed if you use it as a parameter type (like, other code units to form a code point). – dyp Sep 21 '14 at 20:31
2

You need to use cout << char(toupper(board[i][j])); to work around the goofy return type of toupper.

StilesCrisis
  • 15,972
  • 4
  • 39
  • 62
0

Toupper function returns the uppercase equivalent to c, if such value exists, or c (unchanged) otherwise. The value is returned as an int value that can be implicitly casted to char.

http://www.cplusplus.com/reference/cctype/toupper/

Abhi
  • 724
  • 1
  • 6
  • 15
  • `EOF` however is an `int`, which may be passed to `toupper`, but may not be casted to a `char` (if `sizeof(int) > sizeof(char)`). – dyp Sep 21 '14 at 19:59
  • instead of casting char a to board[i][j] i cast it directly into toupper(board[i][j]) and this seems to have skipped the step where the char is converted to an int, i think because I'm casting it to a char at the same time as I'm calling toupper so maybe it goes from char to int to char? – jeremy south Sep 21 '14 at 20:03
  • @dyp: Certainly the value of `EOF` can be converted to `char`. If `char` is unsigned, the result is well defined. If `char` is unsigned, the result is well defined as long as `EOF >= CHAR_MIN` (which it usually is). The result of such a conversion is not particularly useful, though. (Typically `EOF == -1`.) – Keith Thompson Sep 21 '14 at 20:05
  • by the way, thank you for explaining the return type of toupper to me rather than just giving me the code to fix my function, i think i understand toupper better now – jeremy south Sep 21 '14 at 20:08
  • @KeithThompson Yes, I was alluding to `EOF < CHAR_MIN` in the case `char` is signed. Anyway, it seems this conversion is typically not injective? – dyp Sep 21 '14 at 20:09
  • 2
    Def: Implicit: *"Implied rather than expressly stated"*. There's nothing *implicit* about the cast required to perform the desired behavior of the OP. The cast required to send an `int` as `char` to `std::cout` is *explicit* in order to invoke the proper overloaded `operator <<`. The text verbatim from cplusplus.com isn't exactly helpful in this particular case (is anyone surprised by that?), whether copied word-for-word here or on their site. – WhozCraig Sep 21 '14 at 20:11
0

The documentation is clear : http://www.cplusplus.com/reference/cctype/toupper/

int toupper ( int c );

So you just have to cast to char:

cout << " " << (char) toupper(board[i][j]) << " ";
Nicolas Albert
  • 2,586
  • 1
  • 16
  • 16
  • 1
    Side remark: "The documentation" is just **a** documentation. It is not official. – dyp Sep 21 '14 at 20:00
  • Sorry, I didn't search the specification. – Nicolas Albert Sep 21 '14 at 20:01
  • I see, so toupper converts to an integer value, my workaround was char a = toupper(board[i][j]); so i believe that the data type went char to int to char, but i think your solution would work better as it wouldn't require the creation of an unneeded variable – jeremy south Sep 21 '14 at 20:06