6

I am confused with the C++ function std::get_money defined in the <iomanip> header file. What is the use of get_money as per programming concept?

I have the following code using std::get_money.

#include <iostream>     // std::cin, std::cout
#include <iomanip>      // std::get_money

int main ()
{
  long double price;
  std::cout << "Please, enter the price: ";
  std::cin >> std::get_money(price);

  if (std::cin.fail()) std::cout << "Error reading price\n";
  else std::cout << "The price entered is: " << price << '\n';

  return 0;
}

When I typed in an input of 100.25 it returned 100. What is the relation between the output and monetary format? I read this reference but cannot understand the relation. The same confusion is present with std::put_money, std::get_time, and std::put_time.

What are some examples of its actual use?

TrebledJ
  • 8,713
  • 7
  • 26
  • 48
Encipher
  • 1,370
  • 1
  • 14
  • 31
  • Strange. It should return 10025. What is your locale? Maybe the cent part in your locale is separated by coma and you must enter 100,25. – 273K Apr 21 '19 at 05:19
  • I don't know about locale. can you please explain it? How to define it? – Encipher Apr 21 '19 at 05:23
  • Found a related answer for `std::put_money`: https://stackoverflow.com/a/15337053/10239789 – TrebledJ Apr 21 '19 at 05:30
  • Not exactly related to I/O, but [you should never use a `double` to represent prices](https://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency). – Daniel H Apr 21 '19 at 06:48

1 Answers1

1

This is a part of the standard library that I didn't know existed! According to cppreference, you have to set the locale to define how time and money should be formatted. Here I'm using the en_US locale.

#include <iomanip>
#include <iostream>

int main() {
  long double price;
  std::cin.imbue(std::locale("en_US.UTF-8"));
  std::cout << "Please enter the price: ";
  std::cin >> std::get_money(price);
  if (std::cin.fail()) {
    std::cout << "Error reading price\n";
  } else {
    std::cout << "The price entered is: " << price << '\n';
  }
}

Still, this seems a bit finicky to me. The number must include a . with at least two digits after it. The $ is optional.

Indiana Kernick
  • 5,041
  • 2
  • 20
  • 50
  • terminate called after throwing an instance of 'std::runtime_error' what(): locale::facet::_S_create_c_locale name not valid get that error after include locale – Encipher Apr 21 '19 at 05:22
  • @Encipher Sounds like that locale isn't supported by your system. – Indiana Kernick Apr 21 '19 at 05:23
  • @Encipher Rather than trying to get this to work, you could just read in a `double`, multiply by `100` and then round to an integer. – Indiana Kernick Apr 21 '19 at 05:28
  • Never use floats/doubles for money! – graham.reeds Apr 21 '19 at 07:30
  • @graham.reeds I agree with you but fail to see the problem with the approach used in this answer. I don't see the problem with rounding a `double` to an integer (after multiplying by 100) and doing all the arithmetic with integers (like I mentioned in my comment). I also don't see the problem with storing an integer value in a `double` (`std::get_money` returns cents). A `double` has 54 bits of integer precision which is more than enough to losslessly store a 32-bit `int`. Storing `100.25` dollars in a `double` is definitely a no-no but we're not doing that here. – Indiana Kernick Apr 21 '19 at 07:40
  • I don't get the answer of my question. The problem is still there.Can any one show me the correct output of the above program? – Encipher Apr 21 '19 at 15:51
  • @Encipher Nobody wants answer you when you are lazy. You don't provide the information required to get an answer. What is your country, what is money format used in your country, have you tried to input comma instead of dot. – 273K Apr 21 '19 at 16:06
  • It might be but maybe not. You do three part payments on a 100.00 invoice and wonder where 0.01 went. Solving all the edge cases in a clean manner that doesn't introduce other issues is very very complex, time consuming and frustrating when using ieee854. Do yourself a favour and use an int64. My comment was more of a warning from someone who has gone down this path before. – graham.reeds Apr 21 '19 at 22:32