Во-первых, извините за мой плохой английский. Английский не мой основной язык, и мои навыки письма настолько ужасны …
Я искал тему об этой проблеме. У меня похожая тема, но я не могу найти решение для своей. [Пример: ошибка: двоичная>>’: не найден оператор, который принимает правый операнд типа’ const char [1] и программа падает после первого ввода , VS2013 C ++ ошибка C2679: двоичный файл ‘>>’: не найден оператор, который принимает правый операнд типа’ Fraction ‘(или нет приемлемого преобразования) ]
Я просто понимаю, что проблема в том, что я не могу использовать что-то вроде: «+» в istream, потому что это не переменная, поэтому я не могу ее использовать. Но я хочу ввести значение моего класса в виде: a + bj, чтобы я мог экспортировать его в текстовый файл с помощью fstream. Теперь я не знаю, как это сделать.
Мой код:
#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 >> "j\n"; //Error occur here
return in;
}
friend ostream &operator<<(ostream & out, const Complex & Com){
out << Com.real << " + " << Com.imaginary << "j\n";
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
не работает как С sscanf
в том, что вы не можете указать буквальные фрагменты текста, чтобы «соответствовать» или «пропустить». Вы можете только извлечь данные в переменные и подтвердите это после факта.
Так, std::cin >> " + "
а также std::cin >> "j\n"
просто недействительны.
Вы могли бы делать это работает, хотя …
#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])
И пусть он делает ту же работу, но я бы не рекомендовал это.
Все существующие ответы хороши; Я добавлю другой (самый простой?) способ сделать то же самое. Вы представляете, что «чтение» и «запись» должны иметь примерно одинаковую реализацию, изменяя только «направление» потока данных. К сожалению, это не может работать в C ++.
Тем не менее, это будет работать в C, используя printf
а также scanf
:
// Hypothetical "print" function; you don't need to use it
void print(FILE* out, const Complex & Com){
fprintf(out, "%f + %fj\n", com.real, com.imaginary);
}
Если вы замените printf
с scanf
, вы получите что-то вроде этого:
void read(FILE* in, Complex & Com){
fscanf(in, "%lf + %lfj\n", &com.real, &com.imaginary);
}
Однако есть несколько проблем с этим:
FILE*
не istream
Можно исправить третий недостаток — используйте getline
читать строку ввода и sscanf
разобрать это:
friend istream &operator>>(istream & in, const Complex & Com){
std::string str;
std::getline(in, str);
sscanf(str.c_str(), "%lf + %lfj\n", &com.real, &com.imaginary);
return in;
}