0

I'm working on Eclipse, on Fedora. I want to make a number more understandable using a dot to separate the thousands. This number is an integer Value that can be 0<Value<99.999

So... if Value = 1000 it shows 1000 and what I want is to show 1.000 (note the dot). The code I need to change is the next one:

char str[12];
sprintf(str, "%d", (int)(Value));
m_Text.SetText(str); 

And what I thought is to do something like:

if (Value > 999) 
{
 int RightPart = (int)Value % 1000;
 int LeftPart = Val/1000 ;
}

And then append in a string LeftPart + "." + RightPart so if Value = 1563 it will be 1+.+563 which is 1.563

My problem is that it's very ugly to do this and I was wondering if there were a better way of doing it. I've searched on google and found imbueand localebut they are only for cout. I've see too some posts like this and this but this doesn't help me with my problem.

Thank you.

NOTE: I want to remark that I DON'T WANT to change the output format. I want to change the int I receive so I can have the dots in the str var with which I will work later.

NOTE 2: Basically the code has to: receive an integer (Value), and send it like a string to setText(). setText() will basically print it on the screen where and when it has to, and I want it to print 1.563 and not 1563 which is more difficult to read.

Community
  • 1
  • 1
Megasa3
  • 766
  • 10
  • 25
  • 4
    You can use the C++ locale facilities to output numeric values with custom thousands-separators and decimal digits separators. See http://en.cppreference.com/w/cpp/locale/numpunct for details. You can use stringstreams to format a string. – Andrew Jul 27 '15 at 15:03
  • 1
    Use stringstream http://stackoverflow.com/a/7276879/786186 – Alessandro Pezzato Jul 27 '15 at 15:04
  • @AlessandroPezzato if I put `int Val = 1563; std::stringstream ss; ss.imbue(std::locale("")); ss << std::fixed << Val; sprintf(str, "%d", (int)(Val)); std::cout << " ss = " << ss << " str = "<< str << std::endl;` then the output is `ss = 0xbfffe398 VAL = 5634 ` so I suppose that something has been wrong – Megasa3 Jul 27 '15 at 15:19
  • @AlessandroPezzato I get the same now: `ss = 5634 str = 5634` – Megasa3 Jul 27 '15 at 15:23
  • Because the question linked by @AlessandroPezzato has wrong answer accepted. Correct answer is by Node there. – Öö Tiib Jul 27 '15 at 15:37
  • @Megasa3 try `ss.imbue(std::locale("en_US.UTF-8"));` – Öö Tiib Jul 27 '15 at 15:42
  • @ÖöTiib O.o you are right! Thank you! I put it and now it prints 1.000.000 if I write `const int x = 1000000; std::cout << x << std::endl;` BUT If now I print str (which is the string I'm interested in, it prints 1563 still) – Megasa3 Jul 27 '15 at 15:53
  • I just don't understand your last remark in the question. You first explain in a very detailed way how you want your number to be printed... only to then tell us that it's not about output but input?! – Christian Hackl Jul 27 '15 at 16:27
  • @ChristianHackl but i don't want it to be printed, I want it to be sent to setText in a special way that is with dots to separate thousands. I added a second note :) Sorry for the misunderstanding – Megasa3 Jul 27 '15 at 20:05

3 Answers3

6

Use stringstream and same imbue technique for it.

For example:

struct dotted : std::numpunct<char> {
    char do_thousands_sep()   const { return '.'; }  // separate with dots
    std::string do_grouping() const { return "\3"; } // groups of 3 digits
    static void imbue(std::ostream &os) {
        os.imbue(std::locale(os.getloc(), new dotted));
    }
};

and then:

    std::stringstream ss;
    dotted::imbue(ss);
    ss << Value;
    std::cout << ss.str();

Demo

jxh
  • 69,070
  • 8
  • 110
  • 193
gandgandi
  • 330
  • 1
  • 8
  • With your cout I get the 1.563 Value I want BUT if I write `sprintf(str, "%d", (int)(Val)); std::cout << " str = "<< str << std::endl;`then it prints 1563. So I'm on the same way. As I said I don't want the visual output to change, I want the int received to change so I can hace the dots in the str. – Megasa3 Jul 27 '15 at 16:08
1
#include <iomanip>
#include <locale>
#include <iostream>
#include <sstream>

using namespace std;

template<class T>
string format(T value)
{
    stringstream ss;
    ss.imbue(locale(""));
    ss << fixed << value;
    return ss.str();
}


int main(int argc, char argv[])
{
    cout.imbue(locale(""));
    cout << 1000000 << endl;

    return 0;
}

Prints:

1.000.000

You should probably look at which locale is used when "" is passed and change it with a more appropriate one.

Or vice versa:

int str_to_nr(string str)
{
    int val;

    stringstream ss(str);
    ss.imbue(locale(""));
    ss >> val;

    return val;
}


int main(int argc, char argv[])
{
    cout << str_to_nr("1.000") << endl;

    return 0;
}

Prints:

1000

Jaka Konda
  • 1,385
  • 3
  • 13
  • 35
  • Again, I don't want to change the output format, I want to change the int read format. I have added a note to my question to let it clear. – Megasa3 Jul 27 '15 at 16:10
  • I'm still not sure if I completely understand what you'd like to achieve, but I updated my answer. – Jaka Konda Jul 27 '15 at 16:20
  • I have added a second note to clarify it more, sorry for the misunderstanding. I'll see later your answer cause now I can't test it – Megasa3 Jul 27 '15 at 20:03
0

@gandgandi's answer basically gives you a technique to print out the value with dots on demand using C++ streams.

sprintf (which is generally not safe to use, BTW) is a C library function. C does not provide a mechanism to alter the locale behavior in the same way C++ provides. In C, you will have to define the locale behavior with mechanisms/tools provided by your operating system and assign it a name. Then, you can use the C function setlocale to alter the locale in the program to the one you have created to get it to print how you want. However, this will only work on machines that have the locale you have created installed. It won't work on any other machine.

With only a little bit of work and almost no creative effort, you can just use the C++ solution already provided combined with a call to sprintf.

char str[12];
stringstream ss;
dotted::imbue(ss);
ss << Value;
sprintf(str, "%s", ss.str());
m_Text.SetText(str);

But, there is really no reason to use sprintf at all:

stringstream ss;
dotted::imbue(ss);
ss << Value;
m_Text.SetText(ss.str());
Community
  • 1
  • 1
jxh
  • 69,070
  • 8
  • 110
  • 193