I've got a simple class Currency with overloaded operator<<. I don't know how can i separate the number with spaces every 3 digits, so it looks like: "1 234 567 ISK".
#include <cstdlib>
#include <iostream>
using namespace std;
class Currency
{
int val;
char curr[4];
public:
Currency(int _val, const char * _curr)
{
val = _val;
strcpy(curr, _curr);
}
friend ost开发者_C百科ream & operator<< (ostream & out, const Currency & c);
};
ostream & operator<< (ostream & out, const Currency & c)
{
out << c.val<< " " << c.curr;
return out;
}
int main(int argc, char *argv[])
{
Currency c(2354123, "ISK");
cout << c;
}
What interests me, is somehow the easiest solution for this particular situation.
This can be done with facets
struct myseps : numpunct<char> {
/* use space as separator */
char do_thousands_sep() const { return ' '; }
/* digits are grouped by 3 digits each */
string do_grouping() const { return "\3"; }
};
int main() {
std::cout.imbue(std::locale(std::locale(), new myseps));
std::cout << 10000; // 10 000
}
Alternatively, you may code your own loop
void printGrouped(ostream &out, int n) {
if(n < 0) {
out << "-";
return printGrouped(out, -n);
}
if(n < 1000) {
out << n;
} else {
printGrouped(out, n / 1000);
out << " " << setw(3) << setfill('0') << (n % 1000);
}
}
ostream & operator<< (ostream & out, const Currency & c) {
printGrouped(out, c.val);
out << " " << c.curr;
return out;
}
One possibility might be to use locales for this.
#include <locale>
#include <string>
#include <cstddef>
class SpaceSeparator: public std::numpunct<char>
{
public:
SpaceSeparator(std::size_t refs): std::numpunct<char>(refs) {}
protected:
char do_thousands_sep() const { return ' '; }
std::string do_grouping() const { return "\03"; }
};
//...
ostream & operator<< (ostream & out, const Currency & c)
{
SpaceSeparator facet(1); //1 - don't delete when done
std::locale prev = out.imbue(std::locale(std::locale(), &facet));
out << c.val<< " " << c.curr;
out.imbue(prev); //restore previous locale
return out;
}
struct Currency {
static char const sep = ' ';
static int const group_size = 3;
Currency(int val, std::string unit)
: val(val), unit(unit)
{}
friend std::ostream& operator<<(std::ostream& out, Currency const& v) {
// currently ignores stream width and fill
std::ostringstream ss;
bool const neg = v.val < 0;
int const val = (neg ? -v.val : v.val);
if (neg) out << '-';
ss << val;
std::string const s = ss.str();
std::string::size_type n = s.size() % v.group_size;
if (n) out << s.substr(0, n);
for (; n < s.size(); n += v.group_size) {
out << sep << s.substr(n, v.group_size);
}
out << ' ' << v.unit;
return out;
}
private:
int val;
std::string unit;
};
Could make sep and group_size non-static members, if you want to customize each object with comma, etc. (If so, make them private and initialize in the ctor, probably with default parameter values.) You could also use a traits class controlling output formatting.
Locales also support currency formatting through the moneypunct facet.
#include <iostream>
#include <sstream>
#include <cstdlib>
#define GROUP_SEP ','
#define GROUP_SIZE 3
using namespace std;
string output_formatted_string(long long num);
int main() {
string temp;
cout << "Enter a large number: ";
getline(cin, temp);
long long num = atoll(temp.c_str());
string output = output_formatted_string(num);
cout << output << endl;
return 0;
}
string output_formatted_string(long long num)
{
stringstream temp, out;
temp << num;
string s = temp.str();
int n = s.size() % GROUP_SIZE;
int i = 0;
if(n>0 && s.size() > GROUP_SIZE)
{
out << s.substr(i, n) << GROUP_SEP;
i += n;
}
n = s.size() / GROUP_SIZE - 1;
while(n-- > 0)
{
out << s.substr(i, GROUP_SIZE) << GROUP_SEP;
i += GROUP_SIZE;
}
out << s.substr(i);
return out.str();
}
精彩评论