Thread: Letting C++ program show special characters such as æ, þ, ó

  1. #31
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Indeed, console was not made for this purpose.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  2. #32
    Registered User
    Join Date
    Nov 2008
    Posts
    36
    If someone comes up with a solution on this matter, please share with us. Especially you Elysa, since you've done it before. As you know, most recent videogames have support for those characters and surely they had to do some code, most fps shooters I know use C programming language like the unreal games, Counter-strike and those. But how did they do it?

    Well, I know that the Unreal series made new fonts for this purpose, so can't we do just that? Is it possible then to change the command prompts font to that font in the program it is needed in, but in normal cmd's it would be the standard font?

    Thanks!

  3. #33
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Helgso View Post
    If someone comes up with a solution on this matter, please share with us. Especially you Elysa, since you've done it before. As you know, most recent videogames have support for those characters and surely they had to do some code, most fps shooters I know use C programming language like the unreal games, Counter-strike and those. But how did they do it?
    Firstly, they probably use C++ instead of C, since C is not really a good language for games.
    And secondly, they don't write characters to the console. The console is really unfit for things like this.
    Writing to the screen using some rendering API is much easier and powerful than the console. Heck, if I wanted, I could even use unicode text on a label on a window without problems.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #34
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    C or C++ is not the issue here - but we are in the C++ forum, so I guess that's what we should be talking about - but really, both languages support "unicode" and "large sets of characters". The Windows console, however, does not. It has a set of 256 characters that it can display at any given time. You may be able to change which 256 characters those are by changing the "Codepage". For example, codepage 861 is icelandic:
    http://www.tachyonsoft.com/cp00861.htm

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #35
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    The windows console supports Unicode output via WriteConsoleW(). However, the console has to be using a font with Unicode characters (like Lucida Console).

    The easy thing to do on Windows is to use a custom stream buffer that utilizes WriteConsoleW():
    Code:
    #include <iostream>
    #include <iomanip>
    #include <streambuf>
    #include <fstream>
    #include <locale>
    #include <string>
    
    #include <windows.h>
    
    //------------------------------------------------------------------------------
    
    class wconbuf : public std::wstreambuf
    {
    public:
        typedef wchar_t char_type;
        typedef std::char_traits<char_type> traits_type;
        typedef traits_type::int_type int_type;
        typedef traits_type::pos_type pos_type;
        typedef traits_type::off_type off_type;
    
    private:
        char_type *m_buffer;
    
        enum {BUFFER_SIZE = 4096 / sizeof(char_type)};
    
    public:
        wconbuf() : m_buffer(new char_type[BUFFER_SIZE])
        {
            setp(m_buffer, m_buffer + BUFFER_SIZE);
        }//constructor
    
        ~wconbuf()
        {
            pubsync();
            delete[] m_buffer;
        }//destructor
    
    protected:
        virtual int_type overflow(int_type c = traits_type::eof())
        {
            // send our buffer through WriteConsoleW() if we can get a handle
            HANDLE hout = ::GetStdHandle(STD_OUTPUT_HANDLE);
            if (hout && (hout != INVALID_HANDLE_VALUE))
            {
                std::streamsize n = static_cast<std::streamsize>(pptr() - pbase());
                DWORD written;
                ::WriteConsoleW(hout, pbase(), static_cast<DWORD>(n), &written, 0);
            }//if
    
            // reset our buffer
            setp(m_buffer, m_buffer + BUFFER_SIZE);
    
            // write the passed character if necessary (into our buffer)
            if (!traits_type::eq_int_type(c, traits_type::eof()))
            {
                traits_type::assign(*pptr(), traits_type::to_char_type(c));
                pbump(1);
            }//if
    
            return traits_type::not_eof(c);
        }//overflow
    
        virtual int sync()
        {
            // flush our buffer into m_sbuf1 and m_sbuf2
            int_type c = overflow(traits_type::eof());
    
            // checking return for eof.
            if (traits_type::eq_int_type(c, traits_type::eof()))
                return -1;
    
            return 0;
        }//sync
    };//wconbuf
    
    //------------------------------------------------------------------------------
    
    const wchar_t CHECK_SYM = L'\u221A';
    const wchar_t SMALL_LATIN_Ae = L'\u00E6';
    const wchar_t SMALL_LATIN_THORN = L'\u00FE';
    const wchar_t SMALL_LATIN_O_wACUTE = L'\u00F3';
    
    //------------------------------------------------------------------------------
    
    using namespace std;
    
    void display_char(wchar_t c)
    {
        wchar_t old_fill = wcout.fill('0');
        wcout << L"U+" << uppercase << hex << setw(4) << int(c) << dec 
              << L" = " << c << endl;
        wcout.fill(old_fill);
    }//display_char
    
    //------------------------------------------------------------------------------
    
    int main()
    {
        wconbuf wcon;
        wcout.rdbuf(&wcon);
    
        display_char(CHECK_SYM);
        display_char(SMALL_LATIN_Ae);
        display_char(SMALL_LATIN_THORN);
        display_char(SMALL_LATIN_O_wACUTE);
    
        return 0;
    }//main
    If you want to do Unicode file I/O with wfstream, you have to use a custom codecvt facet (that's for another thread).

    gg

  6. #36
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Shouldn't wcout be used instead of cout for wide chars?
    Last edited by King Mir; 12-04-2008 at 08:24 PM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  7. #37
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> Shouldn't wcout be used instead of cout for wide chars?
    Yes.

    >> I believe the deficiency of g++ is the lack of implementation of the wide I/O stream facilities
    Correct. The MinGW port of GNU std C++ does not currently support wide streams. However, STLPort does. The previous example I posted works with MinGW + STLPort.

    >> You may be able to change which 256 characters those are by changing the "Codepage"
    Indeed! I really like those tachyonsoft tables - they let you see what code pages contain a certain glyph and what the character values are in those pages. Take the Latin Small Letter Thorn for example - it has the following character values:
    0x95 for CP861
    0xE7 for CP850 and CP858
    0xFE for CP1252

    So this will print the same character 3 times (using Lucida Console):
    Code:
        SetConsoleOutputCP(861);
        cout << char(0x95) << endl;
    
        SetConsoleOutputCP(850);
        cout << char(0xE7) << endl;
    
        SetConsoleOutputCP(1252);
        cout << char(0xFE) << endl;
    >> I tried letting it print with the number 254 like you told me about, an it returned a box
    My default console output code page is 437 (DOS USA). If you look up the glyph for 0xFE in that code page, you'll see that it's Unicode character U+25A0, "Black Square". Most of the DOS code pages use 0xFE for the "Black Square" glyph.

    gg

  8. #38
    Registered User
    Join Date
    Nov 2008
    Posts
    36
    Quote Originally Posted by Codeplug View Post
    >> Shouldn't wcout be used instead of cout for wide chars?
    Yes.

    >> I believe the deficiency of g++ is the lack of implementation of the wide I/O stream facilities
    Correct. The MinGW port of GNU std C++ does not currently support wide streams. However, STLPort does. The previous example I posted works with MinGW + STLPort.

    >> You may be able to change which 256 characters those are by changing the "Codepage"
    Indeed! I really like those tachyonsoft tables - they let you see what code pages contain a certain glyph and what the character values are in those pages. Take the Latin Small Letter Thorn for example - it has the following character values:
    0x95 for CP861
    0xE7 for CP850 and CP858
    0xFE for CP1252

    So this will print the same character 3 times (using Lucida Console):
    Code:
        SetConsoleOutputCP(861);
        cout << char(0x95) << endl;
    
        SetConsoleOutputCP(850);
        cout << char(0xE7) << endl;
    
        SetConsoleOutputCP(1252);
        cout << char(0xFE) << endl;
    >> I tried letting it print with the number 254 like you told me about, an it returned a box
    My default console output code page is 437 (DOS USA). If you look up the glyph for 0xFE in that code page, you'll see that it's Unicode character U+25A0, "Black Square". Most of the DOS code pages use 0xFE for the "Black Square" glyph.

    gg
    The problem is, when I use your code, ahh let me just show you it on a screenshot so you'll understand me ... : http://www.tv.is/vefir/helgi/images/...lp/strange.JPG

    So, that box appears instead of þ so, yeah. Can I do anything to get this working? :S

  9. #39
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You are not using the Lucida Console font! I just tried it, first with the "default" console font - and I got exactly the same as your result, and then with Lucida Console as the font, and I got three "thorn" characters (or whatever character is called - the one that looks like a b printed on top of a p).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #40
    Registered User
    Join Date
    Nov 2008
    Posts
    36
    So how do I use Lucida console font? Will that get me to print &#254;? Sorry, I'm a noob.

  11. #41
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Right-click on the title bar of your command prompt window, and select properties. Then Select the font tab, and select Lucida Console as your font.

    When you click "OK", you can then select to use this "on all consoles" or "just this time". You want to select "all consoles".

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #42
    Registered User
    Join Date
    Nov 2008
    Posts
    36
    Quote Originally Posted by matsp View Post
    Right-click on the title bar of your command prompt window, and select properties. Then Select the font tab, and select Lucida Console as your font.

    When you click "OK", you can then select to use this "on all consoles" or "just this time". You want to select "all consoles".

    --
    Mats
    But if I want to be making a portable exe that shows þ in windows xp, wouldn't I need a command to put in the program to change the font, only on that exe, that would f.x. trigger "just this time"?

  13. #43
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Helgso View Post
    But if I want to be making a portable exe that shows þ in windows xp, wouldn't I need a command to put in the program to change the font, only on that exe, that would f.x. trigger "just this time"?
    Not quite sure how you do that, to be honest. Perhaps the Wide Character (Unicode) solution posted above is a better choice then - but a fair bit more work.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #44
    Registered User
    Join Date
    Nov 2008
    Posts
    36
    Yeah about that, Codeplug, when I try out your code my compiler Code::Blocks says:

    "|13|error: expected class-name before '{' token|" So it seems to have problems after you state first 'public:' line.

    Any ideas what is wrong here?

  15. #45
    The larch
    Join Date
    May 2006
    Posts
    3,573
    It might depend on the compiler you are using. If it is MinGW then it might not support wide streams. (Code::Blocks is not a compiler but an IDE, and can be set up to use various compilers.)

    A side question, now that we have managed to display and perhaps input special characters, what does it take to make functions like toupper/tolower work with them?
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. BOOKKEEPING PROGRAM, need help!
    By yabud in forum C Programming
    Replies: 3
    Last Post: 11-16-2006, 11:17 PM
  2. fopen();
    By GanglyLamb in forum C Programming
    Replies: 8
    Last Post: 11-03-2002, 12:39 PM
  3. Results for the Encryption Contest -- June 23, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 07-07-2002, 08:04 AM
  4. Replies: 1
    Last Post: 03-12-2002, 06:31 AM
  5. Program to show the number of occurrences of words...
    By Nutshell in forum C Programming
    Replies: 5
    Last Post: 01-26-2002, 06:44 PM