Consider rubble and radioactive waste. They have exactly that form, so I don't consider that a feature.My code outputs "-$0" for something like -0.41 without cents. Though that was not really intended at first, I'm starting to consider this a feature rather than a bug. Being below zero is qualitatively different to above zero.
I have now rewritten the code -- again. The previous code I posted worked perfectly in my opinion, only "bad" thing about it was the stackoverflow-snippet, and me not understanding it, and perhaps the C++/C mix.
This version (below) borrows some of your (lwho) C++ ideas, and does not use the stackoverflow code at all (unless having a variable "pos" that starts from decimal point is considered copying the stackoverflow solution?). It is more readable (at least to me) and "only" 30 lines. It doesn't use streams and uses more C++ then my previous code.
Anyway, to answer my question in my previous post, stackoverflow code is released under cc-wiki / creative commons if I understand it correctly.
I'm starting to wonder, if "$" with localized numbers makes so much sense
I think it's ugly, as we all know, in the future the currency will be "credits" or "crowns", not "dollar", but I guess for now this is the best we got.
Unless you have any more comments, I'm preparing this for a PR.
Code: Select all
#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
std::string format_money(long int money, bool showCents=true){
std::string decimalPoint = ",";
std::string groupSeperator = " ";
int groupDigits = 3;
double Money = 0.01*double(money); // convert from cents to $
const char *format = (Money < 0) ? "-$%.2f" : "$%.2f";
char buf[64];
snprintf(buf, sizeof(buf), format, std::abs(Money));
std::string result(buf);
size_t pos; // pos to decimal point
for(pos = 0; pos < result.length() && result[pos] != '.'; ++pos){}
result.replace(pos, 1, decimalPoint); // replace decimal point
if(!showCents){ // remove cents...
bool allAreZero = true;
for(size_t i = pos+1; i < result.length(); ++i)
if(result[i] != '0') allAreZero = false; //... only if all are zero
if(allAreZero) result.erase(result.begin() + pos, result.end());
}
int stepp = (Money < 0) ? 2 : 1; // compensate for "$" or "-$"
while(pos - stepp > groupDigits){ // insert thousand seperator
pos = pos - groupDigits;
result.insert(pos, groupSeperator);
}
return result;
}
int main(int argc, char **argv) {
// in cents
double values[] = { 0, 1, 10, 100, 12, 123, 1234, 12300, 123456, 1234567, 12345678, 123456789 };
for(double sign : {1.0,-1.0}){
for(long int x : values){
int money = sign*x;
std::cout << "number: \t" << money << std::endl;
std::cout << "money cent:\t" << format_money(money) << std::endl;
std::cout << "money nocent:\t" << format_money(money,false) << "\n" << std::endl;
}
}
return 0;
}