C++:重载cin时拆分复数字符串遇越界错误
operator>> for Complex Class Hey there! Let’s work through this string parsing issue you’re hitting while overloading cin>> for your Complex class. Out-of-bounds errors almost always pop up when we don’t account for all possible input formats or skip checks for string length before accessing characters. Let’s break down the problem and build a robust solution step by step.
Common Complex Number Input Formats to Handle
First, we need to cover all valid ways users might input a complex number—skipping any of these can lead to unexpected index accesses:
- Full form:
3.5+2.7i,-1.2-4i - Real-only:
5,-3.14 - Imaginary-only:
6i,-2.5i - Shortened imaginary:
+i,-i(implies ±1 as the imaginary coefficient)
Why You’re Getting Out-of-Bounds Errors
Here are the most likely culprits:
- You’re hardcoding character indices (like
s[1]) without checking if the string is long enough. - You’re not handling edge cases where parts of the number are omitted (e.g., no real part, no explicit coefficient for
i). - You’re splitting the string without first verifying critical positions (like the location of
ior the+/-separators).
Robust operator>> Implementation
Let’s write a version that avoids these pitfalls, with safety checks at every step:
#include <iostream> #include <string> #include <stdexcept> // Assume your Complex class looks like this: class Complex { public: double realpart; double imaginarypart; Complex() : realpart(0), imaginarypart(0) {} }; std::istream& operator>>(std::istream& in, Complex& c) { std::string s; in >> s; // Read the entire complex number string (until whitespace) if (s.empty()) { in.setstate(std::ios::failbit); // Mark input as invalid if empty return in; } size_t i_pos = s.find('i'); double real = 0.0; double imag = 0.0; if (i_pos != std::string::npos) { // Case 1: Input has an imaginary part std::string imag_part = s.substr(0, i_pos); // Find the separator between real and imaginary parts (last +/- before 'i') size_t sep_pos = s.find_last_of("+-", i_pos - 1); if (sep_pos != std::string::npos && sep_pos != 0) { // Extract and parse real part std::string real_part = s.substr(0, sep_pos); try { real = std::stod(real_part); } catch (const std::invalid_argument&) { in.setstate(std::ios::failbit); return in; } catch (const std::out_of_range&) { in.setstate(std::ios::failbit); return in; } imag_part = s.substr(sep_pos, i_pos - sep_pos); } // Handle edge cases like "+i" or "-i" (implies coefficient 1 or -1) if (imag_part.empty() || imag_part == "+" || imag_part == "-") { imag_part += "1"; } // Parse imaginary part try { imag = std::stod(imag_part); } catch (const std::invalid_argument&) { in.setstate(std::ios::failbit); return in; } catch (const std::out_of_range&) { in.setstate(std::ios::failbit); return in; } } else { // Case 2: Input is a pure real number try { real = std::stod(s); imag = 0.0; } catch (const std::invalid_argument&) { in.setstate(std::ios::failbit); return in; } catch (const std::out_of_range&) { in.setstate(std::ios::failbit); return in; } } // Assign values to the Complex object c.realpart = real; c.imaginarypart = imag; return in; } // Test the implementation int main() { Complex c; std::cout << "Enter a complex number: "; std::cin >> c; std::cout << "Real part: " << c.realpart << ", Imaginary part: " << c.imaginarypart << "\n"; return 0; }
Key Safety Features in This Code
- Check for empty input: We immediately mark invalid input if the string is empty, avoiding index accesses on a zero-length string.
- Find
ifirst: This tells us if we’re dealing with a pure real number or a number with an imaginary component. - Safe separator detection: Using
find_last_ofensures we grab the correct+/-that separates real and imaginary parts (not just the sign of the real part). - Handle imaginary edge cases: We auto-add a
1for inputs like+ito avoid parsing errors. - Exception handling: We catch
stoderrors (invalid format or out-of-range values) and set the stream’s fail bit, which matches standardcinbehavior.
Test Cases to Verify
Try these inputs to make sure everything works without out-of-bounds errors:
3.5+2.7i→ Real: 3.5, Imaginary: 2.7-1.2-4i→ Real: -1.2, Imaginary: -45→ Real:5, Imaginary:0-3.14→ Real:-3.14, Imaginary:06i→ Real:0, Imaginary:6-i→ Real:0, Imaginary:-1
内容的提问来源于stack exchange,提问作者csix

