In C++11, how to print a character given its Unicode code? - c++

I am sure this is a dumb question, but is there a straightforward way to print a Unicode character in C++ given its hex code? For instance: I know that the code for ❤ is 0x2764. Is there a way I can use its code to print it (either via printf or on a stream)?
For the record, I can print the character by writing:
cout << "\u2764" << endl;
but that requires knowing the value at compile time rather than using a variable.
Thanks

From a comment I see you're on OS X, which uses UTF-8 and has a sufficiently complete implementation of the C++11 library (libc++) for the following to work.
#include <codecvt> // wstring_convert, codecvt_utf8
#include <iostream> // cout
int main() {
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
std::cout << convert.to_bytes(static_cast<char32_t>(0x2764)) << '\n';
}
This depends on the console working properly with UTF-8, which OS X's does.

Be sure to output wchar_t to the stream.
#include <iostream>
std::wcout << static_cast<wchar_t>(0x2764) << std::endl;

Related

c++ How to print in a file a double decimal number with comma(instead of dot)

I need to print a csv file with numbers.
When the file is printed , I have numbers with dots, but I need them with commas.
Here an example.
If I print this number in terminal using locale method, I obtain a number with comma, but in the file I have the same number but with dot. I do not understand why.
How could I do?
#include <iostream>
#include <locale>
#include <string> // std::string, std::to_string
#include <fstream>
using namespace std;
int main()
{
double x = 2.87;
std::setlocale(LC_NUMERIC, "de_DE");
std::cout.imbue(std::locale(""));
std::cout << x << std::endl;
ofstream outputfile ("out.csv");
if (outputfile.is_open())
{
outputfile <<to_string(x)<<"\n\n";
}
return 0;
}
Thanks in advance.
Locales are system-specific. You probably just made a typo; try "de-DE", which will probably work (at least it does on my Windows).
However, if your program is not inherently German-centric, then abusing the German locale just for the side effect of getting a specific decimal point character is bad programming style, I think.
Here is an alternative solution using std::numpunct::do_decimal_point:
#include <string>
#include <fstream>
#include <locale>
struct Comma final : std::numpunct<char>
{
char do_decimal_point() const override { return ','; }
};
int main()
{
std::ofstream os("out.csv");
os.imbue(std::locale(std::locale::classic(), new Comma));
double d = 2.87;
os << d << '\n'; // prints 2,87 into the file
}
This code specifically states that it just wants the standard C++ formatting with only the decimal point character replaced with ','. It makes no reference to specific countries or languages, or system-dependent properties.
Your issue is that std::to_string() uses the C locale libraries. It appears that "de_DE" is not a valid locale on your machine (or Coliru for that matter), leading to the default C locale being used and using .. The solution is to use "de_DE.UTF-8". As an aside, using "" for std::locale will not always produce commas; instead, it will depend on the locale set for your machine.

Right aligning money_put results

I'm trying to get the C++ library to generate properly formatted USD output ($ sign, commas for every 1000s place etc).
I'm close, but I cannot get the right alignment to work:
#include <iostream>
#include <iomanip>
#include <locale>
using namespace std;
int main() {
double fiftyMil = 50000000.0; // 50 million bucks
locale myloc;
const money_put<char>& mpUS = use_facet<money_put<char> >(myloc);
cout.imbue(myloc);
cout << showbase << fixed;
cout << "A";
cout.width(30);
cout.setf(std::ios::right);
mpUS.put(cout, false, cout, ' ', fiftyMil * 100); // convert to cents
cout << "B" << endl;
return 0;
}
I'm getting:
A$50,000,000.00 B
I want to get:
A $50,000,000.00B
Any ideas why this isn't working?
I'm using the latest Solaris compiler (12.4)
Update:
It seems like the issue is with the C++ libraries included with the Solaris compiler. This is the workaround I used:
#include <iostream>
#include <iomanip>
#include <locale>
#include <sstream>
using namespace std;
string getFormattedCcy(double amt) {
ostringstream os;
static locale myloc;
static const money_put<char>& mpUS = use_facet<money_put<char> >(myloc);
os.imbue(myloc);
os << showbase << fixed;
mpUS.put(os, false, os, ' ', amt * 100);
return os.str();
}
int main() {
double fiftyMil = 50000000.0; // 50 million bucks
cout << "A";
cout.setf(std::ios::right);
cout.width(30);
cout << getFormattedCcy(fiftyMil);
cout << "B" << endl;
return 0;
}
You have a couple of problems--one with your code, another that looks like its in your implementation.
The problem in your code is pretty trivial. Since you're using a default-constructed locale, it should be using the "C" locale, which shouldn't write out the $ or thousands separators.
That part is easy to fix. Change: locale myloc; to: locale myloc(""); to get a localized locale (so to speak).
I doubt that'll fix the justification problem you're seeing though. That looks to me like it's a problem with the standard library you're using. When I run your code (with the correction above) I get what I'd expect:
A $50,000,000.00B
That's with Visual C++ though (and despite a compiler that conforms fairly poorly, its standard library is about as good as they come).
Also note that right justification is the default, so the line:
cout.setf(std::ios::right);
...should have no effect (but I suspect you knew that, and added it in the hope of getting it to work when it didn't otherwise).
As far as how to get things to work with the Sun Oracle compiler, the most obvious suggestion would probably be to switch standard libraries to one that works better. That leads to another question: whether to try to get a standard library to work with the compiler you're using, or switch to a different compiler such as CLang or gcc. From what I understand, 12.4 was a pretty serious improvement in terms of C++ conformance, but I don't think either the compiler or (apparently) the standard library is really competitive with gcc or Clang yet. OTOH, you may not have a choice, in which case essentially your only route is to build a different standard library with your existing compiler, and hope for the best. If you can't even do that...you could try setting the locale correctly, and just writing the number with std::cout << fiftyMil;, and hope it at least gives you commas as it should, then add the currency sign separately.
As an aside, if you do get an updated (C++11 or newer) library, you can use put_money to simplify the code quite a bit:
#include <iostream>
#include <iomanip>
#include <locale>
using namespace std;
int main() {
double fiftyMil = 50000000.0; // 50 million bucks
std::locale myloc("");
cout.imbue(myloc);
cout << "A" << showbase << setw(30) << put_money(fiftyMil * 100) << "B";
}

glibmm 2.4 invalid byte sequence in conversion input

Trying to use Glibmm-2.4 to output Chinese returns "Invalid byte sequence in conversion input".
#include <iostream>
#include <glibmm/ustring.h>
#include <glibmm/convert.h>
int main()
{
Glib::ustring myUstring = "中";
try
{
std::cout << myUstring;
}
catch(Glib::ConvertError e)
{
std::cout << e.what();
}
return 0;
}
Any idea what I am doing wrong here?
Using Ubuntu 14.04.2 i386 LTS, g++, glibmm-2.4
An initialization of the locale is needed E.g. std::locale::global(std::locale("")); in order to use ustring and have it do the stream operator's implicit conversion correctly, otherwise characters outside of ASCII aren't converted correctly.
This is documented here

Getline Function Messing with Code

Picking up C++ and having a go at it on OS X 10.9 using XCode 5.0.2 and using Alex Allain as reference.
The following code compiles just fine and outputs correctly
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string user_first_name = "test";
std::cout << user_first_name << "\n";
return 0;
}
When I add a getline function, code appears to compile but with no output.
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string user_first_name = "test";
std::getline( std::cin, user_first_name, '\n' );
std::cout << user_first_name << "\n";
return 0;
}
In fact debug navigator has memory filling up with bars (although actual memory use is fixed at 276 KB). Why am I getting stumped on such a simple thing/concept?
I did a bit of digging around and its quite likely this is related to a text encoding issue. I'm using defaults which is Unicode (UTF-8). Encoding is not something I'm familiar with, never something I had to deal with when learning on Windows. How do I get past this?
I can't comment regarding the use of XCode or OS X, but it was my understanding that std::cin always gives you a narrow (single-byte) character stream. In Windows (at least with Visual Studio), I think it works whether you compile for UTF8 (single-byte for all ASCII characters) or UTF16 (2-bytes for all ASCII characters). The runtime library presumably does the conversion for you as necessary.
I'm not sure what "filling up with bars" means, but maybe it's just that you're looking at uninitialized memory. If you think that it is an encoding issue, perhaps try using wstring/wcin instead of string/cin and see if that helps.

wcout and wcerr: How to get it to work with unicode?

#include <iostream>
#include <clocale>
#include <string>
int main() {
std::setlocale(LC_ALL, "en_US.utf8");
std::wstring str(L"Τὴ γλῶσσα μοῦ ἔδωσαν");
std::wcout << str << std::endl;
std::wcerr << str << std::endl;
}
This produces no output on the terminal.
How can I get it to produce UTF-8 output? I figure that ought to be something supported by C++.
I am aware of the utfcpp library, which I am using, but the question is specifically whether there is a stdlib way to print out UTF8.
I got it by following this.
std::setlocale(LC_ALL, ""); is the magic incantation.
This worked on my trivial test program. However my full program still completely fails at printing out wstrings.
That is fine (well, no, it is still somewhat alarming), I will avoid relying on stdlib, and do it myself with the help of utfcpp library, which is excellent. This way I can use cout and cerr for everything and all will be well.