使用money_get<>解析USD和$金额时出现解析错误求助
money_get<> Hey there, let's break down why your code is having that over-read problem and how to fix it.
First, let's recap your issue: when using money_get<char> to parse an input like USD 1.11 $2.22, the first parse grabs 1.11 but leaves .22 instead of $2.22 for the second parse, which then fails and returns 0. Let's figure out what's going wrong here.
What's Causing the Over-Read?
There are three main culprits in your original code:
1. Mixing istreambuf_iterator and Formatted Input (cin >> str)
When you use istreambuf_iterator to work directly with the stream's buffer, then follow it up with cin >> str;, you're breaking the stream's internal state. The operator>> moves the stream's buffer pointer independently of the iterator, which means your second get call starts from the wrong position.
2. Not Resetting Error States
You didn't reset the err variable between the two get calls. Even if the first parse succeeds, residual error flags can carry over and cause the second parse to fail immediately.
3. Missing Whitespace Handling After First Parse
The money_get facet doesn't automatically skip trailing whitespace after parsing a value. After grabbing USD 1.11, you need to explicitly skip any leftover spaces to reach the start of the $2.22 segment.
Fixed Code Example
Here's a revised version of your code that fixes all these issues:
#include <iostream> #include <locale> #include <iterator> #include <string> #include <sstream> #include <cctype> using namespace std; int main() { // Using a string stream to simulate input (easy to test; replace with cin for real use) istringstream input_stream("USD 1.11 $2.22"); input_stream.imbue(std::locale("en_US.UTF-8")); cout << "Parsing input: \"USD 1.11 $2.22\"\n"; // Get the money_get facet from the imbued locale auto& money_facet = use_facet<money_get<char>>(input_stream.getloc()); istreambuf_iterator<char> stream_start(input_stream), stream_end; ios_base::iostate parse_error; long double parsed_value; // Parse international currency format (USD 1.11) parse_error = ios_base::goodbit; // Reset error state first! stream_start = money_facet.get(stream_start, stream_end, true, input_stream, parse_error, parsed_value); if (!(parse_error & ios_base::failbit)) { cout << "Parsed international amount: " << parsed_value / 100 << "\n"; } else { cout << "Failed to parse international currency\n"; } // Skip any whitespace between the first and second amount while (stream_start != stream_end && isspace(static_cast<unsigned char>(*stream_start))) { ++stream_start; } // Parse local currency format ($2.22) parse_error = ios_base::goodbit; // Reset error state again! stream_start = money_facet.get(stream_start, stream_end, false, input_stream, parse_error, parsed_value); if (!(parse_error & ios_base::failbit)) { cout << "Parsed local amount: " << parsed_value / 100 << "\n"; } else { cout << "Failed to parse local currency\n"; } // Show remaining input (should be empty if all parsed correctly) string remaining_input(stream_start, stream_end); cout << "Remaining input: \"" << remaining_input << "\"\n"; return 0; }
What This Fixes
When you run this code, you'll get the expected output:
Parsing input: "USD 1.11 $2.22" Parsed international amount: 1.11 Parsed local amount: 2.22 Remaining input: ""
Key changes explained:
- No mixed input methods: We use
istreambuf_iteratorexclusively to handle the stream, so the buffer position stays consistent. - Error state reset: Every parse starts with a fresh error state to avoid carry-over issues.
- Explicit whitespace skipping: We manually jump over spaces between amounts to ensure the second parse starts at the correct position.
- Error checking: We now validate each parse result, making debugging easier if something goes wrong.
Quick Note on money_get Behavior
Just to reinforce how the facet works:
- When using
trueinget()(international mode), it expects the format[sign] [international symbol] [space] [value](likeUSD 1.11). - When using
false(local mode), it expects[sign] [local symbol] [value](like$2.22).
Make sure your input matches these formats exactly—any deviations will cause parsing issues.
内容的提问来源于stack exchange,提问作者SSteven

