0

// See the code below and help me why i did not getting the right result. Or suggest any other C++ function to convert a C-string like "$567,789,675.89" into long double

  long double mstold( char s[] )
{
    int len = strlen(s);
    long double cash;
    int n=0;
    char amount[ 100 ];
for( int i=0; i<len; i++)                       // for copying the passed C-String into another C-string
  {
    amount[n] = s[i];
      n++;
    if( s[i] == '$' || s[i] == ',')     // Because the C-String has been passed in format: "$567,789,564.987"
        n--;
  }

   cash = _atold( amount );           // This does not gives the right result
   return cash;
 }
  • 3
    Why would you want to? A floating point variable cannot represent `0.01` or `0.1` (or most multiples of them) exactly so converting monetary amounts to floating point, and then doing operations on the values, introduces errors that are a no-no in financial calculations. The way to avoid such errors is to avoid using floating point to represent monetary values, and use integral types (e.g. number of cents) or a structure with two values (dollars and cents as separate members). Operations with integral values limit the potential for errors in monetary calculations. – Peter Aug 08 '22 at 08:14
  • Almost a duplicate [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Richard Critten Aug 08 '22 at 08:27
  • Being totally nerdy, I find `long double cash;` kind of humorous. Nobody has that amount of cash! Not even [Uncle Scrooge](https://disney.fandom.com/wiki/The_Money_Bin). – BoP Aug 08 '22 at 08:39
  • @RichardCritten Not precisely. It's asking how to do something. That link you provided is relevant to my question of why would one want to. ;-) – Peter Aug 08 '22 at 08:42
  • @Peter Actually I want to convert a C-string( a string that shows money amount with dollar sign and with commas at right positions) that is given by the user in the form "$567,789,654.98" to long double data type by using a function , say mstold(), that takes the string entered by the user and removes commas and dollar sign from the string entered by the user and store it in an array of type char. And then this function uses _atold function to convert this into long double data type . But this does not work. Will you help me to do this?? – Nitish Kumar Mishra Aug 08 '22 at 09:26
  • @NitishKumarMishra I understand what you want to do. My point is that you shouldn't be doing it. Converting a monetary value to floating point is fundamentally a flawed goal. – Peter Aug 08 '22 at 09:32
  • @Peter that's why I didn't flag as a a duplicate and said _"almost"_ I thought the additional background information would be useful to OP. – Richard Critten Aug 08 '22 at 10:39
  • @Peter I understand what are you trying to teach me but as I am a beginner and this is a question for me to solve given by the teacher. – Nitish Kumar Mishra Aug 10 '22 at 01:50
  • Fair enough. But you do realise that your teacher would have given you the exercise as a means to learn by doing? Getting other people to do your homework isn't conducive to your learning. – Peter Aug 10 '22 at 02:21
  • @Peter Actually firstly I tried myself with honesty but.... You understand better. But thanks Sir for helping me. – Nitish Kumar Mishra Aug 10 '22 at 11:05

2 Answers2

0

Use strtold() function, since _atold() is a non standard function. I am posting the code which works in compiler explorer. You were not terminating amount array with '\0'. Perhaps that's the reason _atold not worked.

#include <cstdlib>
#include <iostream>
#include <cstring>


using namespace std;

long double mstold(const char* s)
{
    int len = strlen(s);
    long double cash;
    int n = 0;
    char* amount = new char[len+1];
    for (int i = 0; i<len; i++)                       // for copying the passed C-String into another C-string
    {
        amount[n] = s[i];
        n++;
        if (s[i] == '$' || s[i] == ',')     // Because the C-String has been passed in format: "$567,789,564.987"
            n--;
    }
    amount[n] = '\0';
    cash = strtold(amount, NULL);           // This does not gives the right result
    delete[] amount;
    return cash;
}

int main()
{
    long double cash = mstold("$567,789,675.89");
    std::cout << cash << std::endl;
}
mmj
  • 139
  • 8
0

First note. Please do not use C-Style strings. In C++ we use std::string. Anyway, also C-style strings will do and can be converted automatically.

Then, for newbies it is the best to transform the input monetary-string to a number-string with just one decimal digit and then use function stold for conversion. You may read here about it.

But in the real C++ world, you would do 2 things:

  • use dedicated C++ facilities
  • use localization

Unfortunately this is a rather complex topic and you need a while to understand.

You need to read about the localization library. Here you will learn about 2 major concepts:

  1. locales
  2. facets

In general textual representation of dates, monetary values or number formats are governed by regional or cultural conventions. All this properties are contained in a std::locale object.

But the std::locale does not offer much functionality. The real localization facilities are offered in the form of facets. And a std::locale encapsulates several facets. And one of them is about the monetary formatting.

You really can do many things with that and in the end get fully customized behaviour. But, as said, not that easy to understand.

I will use the std::money_get class in my below example.

Please note. This will convert your number into units, without a fraction. In financial calculations we basically should not use fractions, because double or even long double cannot store all "reaal" values". Please read about this as well.

Anyway. I will show you an example how such a monetary value would be converted in C++. You maybe shocked by the complexity, but flexibility has its price . . .

Please see:

#include <iostream>
#include <iomanip>
#include <limits>
#include <string>
#include <locale>
#include <sstream>

int main() {
    // Input String
    char valueAsCString[] = "$567,789,675.89";

    // Put it in an istringstream for formatted extraction
    std::istringstream iss{ valueAsCString };

    // Assume US currency format (On Posix machines, please use "en-US") and set it for the stream
    std::locale myLocale("en_US");
    iss.imbue(myLocale);
    
    // Assume that everthing is good
    std::ios_base::iostate ioError{ std::ios_base::goodbit };

    // Here we will get the value in UNITS, so without a fraction!!!
    long double value{};

    // Parse the money string and get the result
    std::use_facet<std::money_get<char>>(myLocale).get(std::istreambuf_iterator<char>(iss), {}, false, iss, ioError, value);

    // Check Error state
    iss.setstate(ioError);
    if (iss)
        // Show result
        std::cout << std::setprecision(std::numeric_limits<long double>::digits10 + 1) << std::setw(25) << value / 100 << '\n';
    else
        std::cerr << "\nError during conversion\n";
}
A M
  • 14,694
  • 5
  • 19
  • 44
  • May be your answer will be correct but as I am a beginner so I have not the knowledge of some streams that you have been used. Thanks for helping. – Nitish Kumar Mishra Aug 10 '22 at 11:12