5 ms·
C/C++ locales are a trashfire. The path to enlightenment is to not use them and discard all libraries which think they can get away with calling setlocale (whic
by formerly_proven 5y ago
C/C++ locales are a trashfire. The path to enlightenment is to not use them and discard all libraries which think they can get away with calling setlocale (which a few do, but is more or less a given when we're talking about GUIs).
> obviously you should not use sprintf, you should use C++ iostreams
Friends don't let friends use iostreams.
- PandaPanda150 5y agoIostreams aside: You're absolutely right with the trashfire. I live in a country where the elders of the language decided that we don't format floating point numbers with a decimal point but use a decimal komma instead. So PI is not 3.14 but 3,14 instead. Just imagine what pain you have to go through if you want to parse a .csv file written by an application that "tried to do everything right and use locale".
- MaxBarraclough 5y ago> So PI is not 3.14 but 3,14 instead. How would you write 3,141.592?
- selfmodruntime 5y ago3.141,592 - Germany formats numbers that way.
- deleted 5y ago[deleted]
- vidarh 5y agoNorway as well
- pilif 5y agoHere in Switzerland it's even worse because it depends on where in Switzerland you're formatting the number (French parts have different rules from German parts) and whether you're formatting a number as a plain number or a monetary value. if it's money, you use the . as the decimal separator everywhere. if it's just a number, in the French parts, it's , in the German parts the . The thousands separator is ' everywhere
- zmmmmm 5y agosurely this must routinely cause horrific mistakes in things like bank transactions?
- gray_-_wolf 5y agoIn my country most people do not really use thousands separator, so here it would be either 3141,592 or 3 141,592.
- throwaway2016a 5y agoAt least in currencies it is very common to use space as a thousands separator.
- ur-whale 5y ago3'141,592
- gumby 5y agoNote that some languages don't follow the "break at thousand, million.." pattern, most notably south asian languages that break at the lakh and crore boundaries.
- hashimotonomora 5y ago3141592 thousandths. Integer is beautiful.
- trulyme 5y agoUgh. Locales should be used for (user faced) input / output, never for saving data internally or for exporting it. Well, there are some exceptions, like actually caring about the original datetime, but they are rare.
- mananaysiempre 5y ago> Just imagine what pain you have to go through if you want to parse a .csv file written by an application that "tried to do everything right and use locale". Microsoft Excel will helpfully use semicolons as field separators in this case, making parsing CSVs that came out of it in an unknown locale situation even more fun!
- dietrichepp 5y ago> Friends don't let friends use iostreams. Agreed. Had this discussion enough times that I put my thoughts in an article. <iostream> is just spectacularly bad. https://www.moria.us/articles/iostream-is-hopelessly-broken/ https://www.moria.us/articles/iostream-is-hopelessly-broken/
- giomasce 5y agoOne thing I like of iostreams is that the standard syntax supports passing the file object in depth. If you have a custom type and want to print it, you just implement operator<<(), get a reference to the std::ostream and do what you want with it. Using printf you either have to first write to a temporary string and then print it (which requires more memory and more time to go through it, if the representation of the object is big) or break the flow anyway with something like: printf("The object is "); print_object(object, stdout); printf("\n"); Does fmt support printing a custom type without breaking the format string and without using a temporary string?
- olvy0 5y agoYes, fmt does support printing a custom type, see: https://fmt.dev/latest/api.html#formatting-user-defined-types https://fmt.dev/latest/api.html#formatting-user-defined-type... It may look like a lot to implement, but it worked flawlessly for me several years ago for a simple case, just by copying and pasting the example code there.
- dietrichepp 5y agofmt does this. For a given object, you specialize the “formatter” class. The formatter class parses the format string and stores the contents of the formatter string. It then writes out the formatted string to an output iterator. fmt has a “buffer” class which is used as an interface between formatters and their two primary use cases, which are formatting to strings and formatting to files. A buffer is an abstract base class which exposes a pointer to a region of memory and has a virtual function to flush the output (sort of). When you call fmt::format or fmt::print, you’re getting std::back_insert_iterator for a buffer. I would describe this as “surgical usage of a virtual function” because it is used exactly in a place where it is not called often (you mostly write to a buffer, and flush it less often) and its use reduces the number of template instantiations in your project. That said, the ergonomics for custom formatters is not great.