Confusion over std::get_money and std::put_money in C++
Asked Answered
C

1

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?

Cowley answered 21/4, 2019 at 4:55 Comment(4)
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.Dulsea
I don't know about locale. can you please explain it? How to define it?Cowley
Found a related answer for std::put_money: https://mcmap.net/q/1917633/-c-currency-outputCivilly
Not exactly related to I/O, but you should never use a double to represent prices.Hasbeen
M
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.

Marinelli answered 21/4, 2019 at 5:20 Comment(8)
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 localeCowley
@Cowley Sounds like that locale isn't supported by your system.Marinelli
@Cowley Rather than trying to get this to work, you could just read in a double, multiply by 100 and then round to an integer.Marinelli
Never use floats/doubles for money!Gorlovka
@Gorlovka 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.Marinelli
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?Cowley
@Cowley 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.Dulsea
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.Gorlovka

© 2022 - 2024 — McMap. All rights reserved.