首先,为我糟糕的英语道歉。英语不是我的母语,我的写作能力也很差。
我搜索了一些关于这个问题的话题。我有一些类似的话题,但我不能得到我的解决方案。[示例:error: binary '>>']没有找到右操作数类型为'const char[1]的操作符,程序在第一次输入后崩溃,VS2013 c++错误C2679: binary '>>'没有找到接受'Fraction'右操作数类型的操作符。(或没有可接受的转换)]
我刚刚发现问题是我不能在istream中使用像:"+"这样的东西,因为它不是一个变量,所以我不能使用它。但是我想以a + bj的形式输入我的类值,这样我就可以用fstream将其导出为txt文件。现在我不知道该怎么做了。
我代码:#include "stdafx.h"
#include "iostream"
#include "fstream"
using namespace std;
class Complex
{
public:
Complex( double = 0.0, double = 0.0);
Complex(const Complex &);
Complex(const Complex *);
Complex operator+( const Complex & ) const;
Complex operator-( const Complex & ) const;
Complex operator*( const Complex & ) const;
Complex operator/( const Complex & ) const;
Complex operator=( const Complex & );
friend istream &operator>>(istream & in, const Complex & Com){
in >> Com.real >> " + " >> Com.imaginary >> "jn"; //Error occur here
return in;
}
friend ostream &operator<<(ostream & out, const Complex & Com){
out << Com.real << " + " << Com.imaginary << "jn";
return out;
}
void print() const;
private:
double real;
double imaginary;
};
为什么要重新发明轮子?标准库已经提供了<complex>
和流支持。
#include <iostream>
#include <complex>
int main()
{
std::complex<double> c;
std::cin >> c;
std::cout << c;
}
如果您正在寻找更复杂的序列化,请尝试像Boost.Spirit。
没有重载>>
操作符,它接受字符串字面值(字符串字面值是char
的常量数组,例如const char [4]
为3个字符的字符串字面值),因此您不能使用这样的模式匹配。
如果你想要进行模式匹配,你应该将一行读入字符串,然后你可以使用正则表达式来匹配特定的模式。
这个错误是因为" + "不能作为istream
的目标
如果使用cout << ... << " + " << ...
写入数据,则输入需要将"+"读入std::string
,并确保它是正确的。
从std::istream
中格式化的提取不像C的sscanf
那样工作,因为你不能指定文本的文字片段来"匹配"或"跳过"。您只能将数据提取到变量中,并在事后验证它。
所以,std::cin >> " + "
和std::cin >> "jn"
是无效的。
你可以让工作,但是& help;
#include <iostream>
#include <cstring>
#include <stdexcept>
struct eat
{
explicit eat(const char* in)
: str(in)
, len(std::strlen(in))
{}
template <size_t N>
explicit eat(const char (&in)[N])
: str(in)
, len(N)
{}
private:
const char* str;
size_t len;
friend std::istream& operator>>(std::istream&, eat);
};
std::istream& operator>>(std::istream& is, eat e)
{
char c;
for (size_t i = 0; i < e.len; i++) {
if (!is.get(c) || c != e.str[i]) {
is.setstate(std::ios::failbit);
break;
}
}
return is;
}
int main()
{
int x = 0, y = 0;
std::cin >> x >> eat(" + ") >> y >> eat("j");
if (!std::cin)
throw std::runtime_error("Input was invalid!");
std::cout << "Real part: " << x << "; imaginary part: " << y << 'n';
}
// Input: 3 + 4j
// Output: Real part: 3; imaginary part: 4
(现场演示)
我选择要求用户在eat()
中包装字符串字面值,这样您就不会意外地使用此功能。您可以通过只定义一个template <size_t N> std::istream& operator>>(std::istream&, const char (&str)[N])
使它与现有代码一起工作,并让它做相同的工作,但我不建议这样做。
所有现有的答案都是好的;我将添加另一种(最简单的?)方法来做同样的事情。您认为"读"one_answers"写"应该具有大致相同的实现,仅改变数据流的"方向"。不幸的是,这不能在c++中工作。
但是,这将在C中工作,使用printf
和scanf
:
// Hypothetical "print" function; you don't need to use it
void print(FILE* out, const Complex & Com){
fprintf(out, "%f + %fjn", com.real, com.imaginary);
}
如果你用scanf
代替printf
,你会得到这样的东西:
void read(FILE* in, Complex & Com){
fscanf(in, "%lf + %lfjn", &com.real, &com.imaginary);
}
然而,这样做有几个问题:
- 这对你学习c++没有任何帮助
- 检测错误不是件容易的事
- 使用
FILE*
,而不是istream
有可能修复第三个缺陷—使用getline
读取一行输入并使用sscanf
解析它:
friend istream &operator>>(istream & in, const Complex & Com){
std::string str;
std::getline(in, str);
sscanf(str.c_str(), "%lf + %lfjn", &com.real, &com.imaginary);
return in;
}