This is my first time writing C++, so I would appreciate advice in the areas of:
- Code style (naming conventions, indentation, etc)
- Memory usage (am I performing unnecessary object copies?)
- Class design (move constructors, destructors, etc, are they necessary?)
- Correct usage of standard library functions (especially the string parsing part)
complex.h:
#ifndef COMPLEX_H
#define COMPLEX_H
#include <string>
class Complex
{
private:
double real_;
double imag_;
public:
Complex();
Complex(const Complex& obj);
Complex(const std::string& str);
Complex(double real);
Complex(double real, double imag);
double real() const;
double imaginary() const;
double argument() const;
double modulus() const;
Complex conjugate() const;
Complex pow(double power) const;
std::string toString() const;
Complex operator+(const Complex& rhs) const;
Complex operator-(const Complex& rhs) const;
Complex operator*(const Complex& rhs) const;
Complex operator/(const Complex& rhs) const;
bool operator==(const Complex& rhs) const;
bool operator!=(const Complex& rhs) const;
};
#endif
complex.cpp:
#include <cmath>
#include <sstream>
#include <regex>
#include "complex.h"
Complex::Complex(const Complex& obj) : Complex(obj.real_, obj.imag_) { }
Complex::Complex(const std::string& str) {
double real = 0.0, imag = 0.0;
std::regex realRegex("^(-)?\\s*(\\d+(\\.\\d+)?)$");
std::regex imagRegex("^(-)?\\s*(\\d+(\\.\\d+)?)i$");
std::regex bothRegex("^(-)?\\s*(\\d+(\\.\\d+)?)\\s*([-+])\\s*(\\d+(\\.\\d+)?)i$");
std::smatch match;
if (std::regex_match(str.begin(), str.end(), match, realRegex)) {
real = std::atof(match[2].str().c_str());
if (match[1].matched) {
real = -real;
}
} else if (std::regex_match(str.begin(), str.end(), match, imagRegex)) {
imag = std::atof(match[2].str().c_str());
if (match[1].matched) {
imag = -imag;
}
} else if (std::regex_match(str.begin(), str.end(), match, bothRegex)) {
real = std::atof(match[2].str().c_str());
imag = std::atof(match[5].str().c_str());
if (match[1].matched) {
real = -real;
}
if (match[4].str() == "-") {
imag = -imag;
}
} else {
throw std::runtime_error("Invalid number format");
}
real_ = real;
imag_ = imag;
}
Complex::Complex() : Complex(0.0) { }
Complex::Complex(double real) : Complex(real, 0.0) { }
Complex::Complex(double real, double imag) : real_(real), imag_(imag) { }
double Complex::real() const {
return real_;
}
double Complex::imaginary() const {
return imag_;
}
double Complex::argument() const {
return std::atan2(imag_, real_);
}
double Complex::modulus() const {
return std::sqrt(real_ * real_ + imag_ * imag_);
}
Complex Complex::conjugate() const {
Complex result(real_, -imag_);
return result;
}
Complex Complex::pow(double power) const {
double mod = modulus();
double arg = argument();
mod = std::pow(mod, power);
arg *= power;
double real = mod * std::cos(arg);
double imag = mod * std::sin(arg);
Complex result(real, imag);
return result;
}
std::string Complex::toString() const {
std::stringstream fmt;
if (imag_ == 0) {
fmt << real_;
} else if (real_ == 0) {
fmt << imag_ << "i";
} else {
fmt << real_;
if (imag_ < 0) {
fmt << " - " << -imag_;
} else {
fmt << " + " << imag_;
}
fmt << "i";
}
return fmt.str();
}
Complex Complex::operator+(const Complex& rhs) const {
Complex result(real_ + rhs.real_, imag_ + rhs.imag_);
return result;
}
Complex Complex::operator-(const Complex& rhs) const {
Complex result(real_ - rhs.real_, imag_ - rhs.imag_);
return result;
}
Complex Complex::operator*(const Complex& rhs) const {
double newReal = real_ * rhs.real_ - imag_ * rhs.imag_;
double newImag = real_ * rhs.imag_ + imag_ * rhs.real_;
Complex result(newReal, newImag);
return result;
}
Complex Complex::operator/(const Complex& rhs) const {
double denom = rhs.real_ * rhs.real_ + rhs.imag_ * rhs.imag_;
double newReal = (real_ * rhs.real_ + imag_ * rhs.imag_) / denom;
double newImag = (imag_ * rhs.real_ - real_ * rhs.imag_) / denom;
Complex result(newReal, newImag);
return result;
}
bool Complex::operator==(const Complex& rhs) const {
return real_ == rhs.real_ && imag_ == rhs.imag_;
}
bool Complex::operator!=(const Complex& rhs) const {
return !(*this == rhs);
}