This seems such a simple problem but I've got no way to put the "£" into my code, all i get is the "ú" symbol?
Printable View
This seems such a simple problem but I've got no way to put the "£" into my code, all i get is the "ú" symbol?
Not as simple as it seems. In a particularly impressive move of conflict between backwards compatibility and sane behaviour, the compatibility won, and so you end up with your compiler's editor using the Windows-1251 (most likely) character set while the console uses the IBM-DOS character set, codepage 443 or 850 or something like that. (443 is US, 850 is Germany, don't know what UK would be.)
In effect, your compiler compiles the code, which is Win-1251, and takes the character codes of the string literally into the executable. There, in your exe, is a character code that would be the pound sign in Win-1251.
However, when printing to the console, the same character code is interpreted as an 'ú' instead.
Solution? Uh... I'll leave that to others. I think there's a setting somewhere in the console properties for that, but that's only a local solution.
gcn_zelda: there's no character 156 in ASCII...
Of course, this depends on which font you have, or perhaps which code page you have for command line programs.
This sounds a damn sight more compliacated then i thought it would be, if its any help I'm using microsofts visual c++ on windows xp pro using the british character set. Is there no way just insert a specific character like you can in HTML?
We guessed as much.Quote:
if its any help I'm using microsofts visual c++ on windows xp pro using the british character set
Not really, no. Not a named character. It is possible to insert a specific character code, but that brings you back to the dependency.Quote:
Is there no way just insert a specific character like you can in HTML?
c++
cout << (char)156;
c
printf("%c",156);
dependency???? :confused:Quote:
Originally Posted by CornedBee
Dependency on the character set that happens to be in use.
I tried that as one of the first things, i just got a whole heap of errors chucked at me, plus we're not really allowed to use regular C code as that is what we've being taught up to now, I'm pretty sure that it has to stay as true to c++ as humanly possible.Quote:
c++
char r = 156;
cout << r;
c
printf("%c",156);
I'm not really bothered if it doesn't work on this system, what matters is if it works when compiled on a linux shell.Quote:
Dependency on the character set that happens to be in use.
The fact that it works for you is irrelevant, since it may not work on others' computers.
Edit : And why did you open up the whole std namespace for one cout? Just use std :: cout.
In that case, find a text editor that saves the files in the ISO-8895-1 encoding (I believe that's Linux's standard set), save them with that, transfer over the the Linux box and it should work.Quote:
I'm not really bothered if it doesn't work on this system, what matters is if it works when compiled on a linux shell.
Point in case is that if you're developing at one machine but want to run on another, you'll have to keep this stuff in mind - and unfortunately, I'm not aware of any proper way to find out about these problems at runtime. Hey, even Java doesn't manage it!
Well it wont help him much if it works for you but not for him will it??
If you want a bad, non-portable, not sure to work and probably error-prone method you will need to find out what value that character has, This little program can help you with that
Then you will manually have to chech all the characters that are printed out and when you find it you will know that on your particular system with your charset and everything £ has the value to the left.Code:#include <iostream>
using namespace std;
int main()
{
unsigned char c = 0;
for(int i=0; i<256; c++, i++)
cout << (int)c << ": " << c << endl;
}
Characters are problematic anyway. Case in point? Try running this program, compiled as C++ in MSVC++:
So, what do you think? Is the German umlaut ö a printable character? The answer: the program crashes...Code:#include <cctype>
#include <iostream>
int main()
{
using namespace std;
cout << isprint('ö') << endl;
}
The valid range of arguments for isprint() goes from 0 through 127. In many compilers, the functions isprint(), isalnum(), etc. are implemented by indexing into an array of 128 chars. That doesn't mean that chars with values greater than 127 won't print, just that you had better not test them with isprint(), isalnum(), etc.Quote:
Originally Posted by CornedBee
Regards,
Dave
I don't know what the standard says, but MS's documentation on their implementation says this:
The confusing part about this is that not every single-character character constant is within that allowed range, because some of them are negative integer values. Yes, it is clearly warned about, but hey, this means that I can't even write a text in my native language without resorting to tricks!Quote:
The is routines produce meaningful results for any integer argument from –1 (EOF) to UCHAR_MAX (0xFF), inclusive. The expected argument type is int.
Caution For the is routines, passing an argument of type char may yield unpredictable results. An SBCS or MBCS single-byte character of type char with a value greater than 0x7F is negative. If a char is passed, the compiler may convert the value to a signed int or a signed long. This value may be sign-extended by the compiler, with unexpected results.
The problem is with the sign-extension and is easy to fix.
- Consider the char value -10.
- This is "11110110" in two's-complement binary.
- Now we implicitly convert this to a signed int by passing it to isprint().
- The value is sign-extended and we now have "11111111 11111111 11111111 11110110" in binary.
- The implementation casts this value to an unsigned int for comparison purposes.
- We now have the decimal value 4294967286. Obviously, this will cause problems if we try to compare it against a 256 or 64KB lookup table.
This is demonstrated with this very simple program.
The solution is to avoid the sign-extension by passing the value as an unsigned char.Code:#include <stdio.h>
void demo(int c)
{
printf("int_value: %d\n", c);
printf("uint_value: %u\n", c);
}
int main(void)
{
char c = -10;
demo(c);
demo((unsigned char) c);
getchar();
return 0;
}
However, it still doesn't return true. This is because the ctype functions use the "C" locale by default. In this locale, only the base characters are supported. We can use the setlocale function or we can use Windows functions which provide much more reliable international character support.Code:isprint((unsigned char) 'ö')
Results:Code:#include <stdio.h>
#include <ctype.h>
#include <windows.h>
#include <locale.h>
int win_isprint(UCHAR c)
{
WORD char_type;
if (GetStringTypeA(LOCALE_USER_DEFAULT, CT_CTYPE1, (LPCSTR) &c, 1, &char_type))
return !(char_type & C1_CNTRL);
else
return 0;
}
int main(void)
{
char c = -10;
setlocale( LC_ALL, ".ACP" ); /* Uses the windows specified code page. */
printf("CLib: %d\n", isprint((unsigned char) '\b'));
printf("CLib: %d\n", isprint((unsigned char) 'a'));
printf("CLib: %d\n", isprint((unsigned char) 'ö'));
printf("Win: %d\n", win_isprint('ö'));
printf("Win: %d\n", win_isprint('\b'));
getchar();
return 0;
}
Code:CLib: 0
CLib: 258
CLib: 258
Win: 1
Win: 0
I know all of this. It's still counterintuitive. Especially as the same code works in C.
I do not see what the big deal is:
cout<<char(156);
works fine for me in devc++ and vc++
The bolded part:Quote:
I what the big deal is:
Quote:
works fine for me.
just curious after reading through this post why couldnt you just go to the character map copy the symbol then paste it in your code like this...
Code:
cout << "£\n";
Because of this (simplified explanation): the compiler has a target character encoding. The literal strings inside the executable (including your "£\n") will be in this encoding. But the computer knows no such thing as a character in memory, it's all numbers - displaying a character just means using the number as an index into a table of drawing instructions. This is what an encoding does: it specifies which number to use for which character. This number will then get stored in the executable.
There might be another encoding used on the target system. The same number stored in the executable could suddenly be a different character.
This is what is so unreliable about the whole thing.
Windows complicates matters: there is more than one encoding on a single platform. While the compiler will most likely use Windows' native Windows-1252 (or variant, depending on where you live) encoding as target, the interpretation of the characters, when written to the console, will happen using the IBM-OEM-xxx encoding, where xxx is your code page number. (443 is American English, 850 is German, ...)
Try it yourself. Take that code snippet, compile it as a console app and run. It won't be a pound sign printed to the console.
The problem is that you can't detect what character set is being used using standard C++. Your best bet, therefore, is to use wide-character strings. Using this code:
wcout << L"£\n";
should work. (Provided that you have a proper implementation of your standard streams. I'm not sure if there is such a thing.)