从字符串解析复数,考虑语法变化 [英] Parse complex number from string, considering syntax variations

查看:59
本文介绍了从字符串解析复数,考虑语法变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个控制台应用程序,我可以在其中输入复数.一切正常,但我希望输入格式更加灵活.现在它只接受 a+bi,我想这样做,所以如果我只输入 3 或 -2i,它仍然有效.

I'm making a console application where I can input complex numbers. Everything works, but I'd like to be more flexible with the input formatting. Right now it only accepts a+bi, I'd like to make it so if I just enter 3 or -2i, it still works.

Complex console::parseComplex(std::string cmp) { 
    float a, b;
    char i;
    std::stringstream ss(cmp);
    if (ss >> a >> b >> i && i == 'i')
        return { a, b };
    else return { true };

事情是,据我所知,如果我添加以下内容

The thing is that as far as I know if I add the following

    else if (ss >> a >> i && i == '\0')
        return { a, 0 };
    else if (ss >> b >> i && i == 'i')
        return { 0, i };

在我的最后一行之前,它不起作用,因为 >> 通过 ss.字符串中不会有任何空格.我不知道如何在不重铸 ss 的情况下更改它(我认为这不是最好的方法)

Before my last line, it won't work, since >> goes through the ss. There won't be any spaces in the string. I'm not sure how to change it without just recasting the ss (which I assume is not the best way of doing it)

而且我不确定如何过滤掉任何被转换为整数并发送出去的随机字符,检查 '\0' 感觉不对.

And I'm not sure how to filter out any random characters being converted into ints and send away, checking for '\0' feels wrong.

谢谢!

(顺便说一句,返回 {true} 在被检查的类上转到 m_fail,这是我能想到的最简单的错误处理方法,但我是新手,所以如果你有任何关于该主题的文档我想阅读更多)

(BTW the return {true} goes to m_fail on the class which get's checked, it's the simplest way of error handling i could come up with, but I'm new to this so if you have any doc handy on the topic I'd love to read more)

推荐答案

我已经建议编写一个小型解析器(例如基于 SO:如何重新排列字符串方程?).

I already recommended to write a small parser (e.g. based on a syntax diagram like shown in SO: How to rearrange a string equation?).

接下来,我按照OP尝试的方式做了一个更简单的方法(并且没有绘制语法图).

In the following, I made a simpler approach following the way tried by OP (and without sketching a syntax diagram).

即我的辅助类型 Complex 的输入流运算符尝试读取两个数字.

I.e. the input stream operator for my helper type Complex tries to read two numbers.

如果第一个数字后跟一个 i 这实际上是第二个数字并且输入结束.

If first number is followed by an i this is actually the second number and input ends.

如果第二个数字后面没有 i 它实际上不是第二个而是丢失了并且流被重置到之前的位置.

If second number is not followed by an i it's actually not the second but missing and stream is reset to the position before.

示例代码:

#include <cmath>
#include <iomanip>
#include <iostream>
#include <sstream>

struct Complex {
  float re, im;
};

std::istream& operator >> (std::istream &in, Complex &value)
{
  value.im = 0;
  // read 1st value
  if (!(in >> value.re)) return in; // ERROR!
  // check whether next char is 'i'
  char c; if (!(in >> c)) return in; // End of Input
  if (c == 'i') {
    value.im = value.re; value.re = 0.0;
    return in;
  }
  in.unget();
  // remember start of imaginary
  std::streampos pos = in.tellg();
  if (!(in >> value.im)) return in; // ERROR or end of input
  if (!(in >> c) || c != 'i') { // ERROR or premature end of input
    value.im = 0.0;
    in.clear();
    in.seekg(pos);
    return in;
  }
  return in;
}

std::ostream& operator << (std::ostream &out, const Complex &value)
{
  return out << value.re << (std::signbit(value.im) ? "" : "+") << value.im << 'i';
}

int main()
{
  // samples:
  std::string samples[] = {
    "1.23+45i",
    " 1.23 +45i",
    " 1.23E3 +45e-1i",
    "Completely wrong!",
    // multiple numbers in one line
    "1.23+45i 1.23 +45i 1.23E3 +45e-1i",
    "1.23 2.34-1i -2i"
  };
  int line = 1;
  for (const std::string &sample : samples) {
    std::cout << "Parse line " << line++ << " '" << sample << "':\n";
    std::istringstream in(sample);
    std::cout << "Got:";
    Complex value;
    while (in >> std::skipws >> value) std::cout << ' ' << value;
    std::cout << '\n'
      << "Stopped with "
      << (in.eof() ? "End of Input" : !in.good() ? "Error" : "???")
      << '\n';
  }
  return 0;
}

编译和测试:

g++ (GCC) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Parse line 1 '1.23+45i':
Got: 1.23+45i
Stopped with End of Input
Parse line 2 ' 1.23 +45i':
Got: 1.23+45i
Stopped with End of Input
Parse line 3 ' 1.23E3 +45e-1i':
Got: 1230+4.5i
Stopped with End of Input
Parse line 4 'Completely wrong!':
Got:
Stopped with Error
Parse line 5 '1.23+45i 1.23 +45i 1.23E3 +45e-1i':
Got: 1.23+45i 1.23+45i 1230+4.5i
Stopped with End of Input
Parse line 6 '1.23 2.34-1i -2i':
Got: 1.23+0i 2.34-1i 0-2i
Stopped with End of Input

coliru 现场演示

在摆弄时我仍然意识到一些弱点,例如1.23 + 45i 无法读取,因为+45 之间有空格.所以,有了更多的代码,这肯定可以得到改进.另一方面...... OP 没有指定哪里应该接受空格,哪里不接受.

While fiddling I still realized some weaknesses like e.g. 1.23 + 45i cannot be read because of space between + and 45. So, with even more code this could be improved for sure. On the other hand... OP didn't specify where spaces should be accepted and where not.

这篇关于从字符串解析复数,考虑语法变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆