输入错误:拆分一个条目的一部分

input errors : split part of one entery

我正在做一些标准练习 I/O 我有一个复杂的 class 。我的 class 有重载的插入和提取运算符,输入应为以下形式: x + yi(例如 10 + 9i) 我必须确定输入是否有效。 有问题,如果我以这种形式输入,结果总是失败, 因为我正在将 char 'i' 输入到整数数据类型。 那么我如何做到这一点,而不会出现故障位? 我的功能是这样的:

istream &operator>>(istream &input, Complex &complex)
{
    input >> complex.realPart;
    input.ignore(3);
    input >> complex.imaginaryPart;

    return input;
}

但这显然是不够的!如果在 i 和整数之间有一个 space 它可以解决所有问题。但是没有!我想过使用数组,甚至字符串,但是然后将它们复制到我的 class 的 int 私有数据中,这似乎不是一个好的编程。毕竟我必须寻找什么错误? 多谢 ! ;)

您可以使用 std::getline and std::sscanf 来解析值

#include <cstdio>
#include <iostream>
#include <string>

int main()
{
    std::string input;
    std::getline(std::cin, input);

    int real;
    int imaginary;
    std::sscanf(input.c_str(), "%i + %ii", &real, &imaginary);
    std::cout << real << " " << imaginary;
}

输入

5 + 3i

输出 - Live Demo

5 3

return value of std::sscanf according to cppreference

Number of receiving arguments successfully assigned, or EOF if read failure occurs before the first receiving argument was assigned.

所以你可以检查 return 值 == 2 以确保它是一个有效的输入

您必须检查“+”和尾随 'i':

istream &operator>>(istream &input, Complex &complex)
{
    char plus,letter;
    if (input >> complex.realPart >> plus)  {
        if (plus!='+' ) 
            input.setstate(ios::failbit);
        else if (input >> complex.imaginaryPart>>letter) {
             if (letter!='i')
                 input.setstate(ios::failbit);
        }
    }
    return input;
}

直播demo here

请注意,您还可以通过以下方式使其更简单:

istream &operator>>(istream &input, Complex &complex)
{
    char plus,letter;
    if ( (input >> complex.realPart >> plus >> complex.imaginaryPart>>letter) && (plus!='+' || letter!='i'))
            input.setstate(ios::failbit);
    return input;
}

与之前版本的不同之处在于提供了另一个字母而不是加号:第一个版本立即停止读取输入,知道它无论如何都是错误的,而第二个版本将继续使用流。