0

I'm having trouble figuring out how to approach this problem of real + imaginary numbers.

This is the code I have so far:


#include <iostream>
#include <fstream>
#include <string>


using namespace std;

class Complex {

    public:

        Complex();
        Complex(double realNum);
        Complex(double realNum, double imagNum);

        //Complex(double real = 0.0, double imaginary = 0.0); This avoids the 3 above?

        Complex(const Complex& obj);



    private:

        double real;
        double imaginary;



};


int main () {

    Complex *complexArray;
    complexArray = new Complex[8];

    ifstream myfile("complex.txt");

    string line;
    int i = 0;

    if (myfile.is_open()) {

        while (! myfile.eof()) {

            getline(myfile, line);
            complexArray[i] = line;
            i++

        };

        myfile.close();


    };

    else {

        cout << "Error. Could not find/open file." ;
    }



    return 0;

};


Complex::Complex(const Complex& obj) {

    real = obj.real;
    imaginary = obj.imaginary;

};



Complex::Complex () {

    real = 0;
    imaginary = 0;

};



Complex::Complex (double realNum) {

    real = realNum;
    imaginary = 0;

};



Complex::Complex (double realNum, double imagNum) {

    real = realNum;
    imaginary = imagNum;

};

So I realized I cannot read in the complex numbers and store directly into my array...

I'm thinking maybe I should do this?

  1. read in the numbers and store as a string into an array of strings.
  2. Do a loop to go through the array of strings and for the loop...

    1. check (how do I do this?) to make sure it is a complex number in correct format, to avoid the "fake Line hi!"
    2. real = myStringArray[i].at(0) imaginary = myStringArray[i].at(1 & 2 positions...do this somehow)

Anyway, I'm just confused how to approach this problem.

Thanks!

Evan
  • 47
  • 5
  • 1
    you will need to parse `line` which is a string to separate out the numeric substrings that are real and imaginary. Then convert them to doubles. Then you can assign them with the appropriate constructor. – doug Sep 17 '19 at 03:51
  • Why not use the standard complex number class? – Shawn Sep 17 '19 at 03:57
  • 1
    Solve a simpler problem first: reading *one* `Complex` from a file. – Beta Sep 17 '19 at 04:37
  • Have a look at [Why !.eof() inside a loop condition is always wrong.](https://stackoverflow.com/q/5605125/9254539) – David C. Rankin Sep 17 '19 at 05:03

3 Answers3

0

I recommend using regular expressions. This is my method:

#include <iostream>
#include <fstream>
#include <string>
#include <regex>

int main() {
    std::regex rgx("^(?=[iI.\\d+-])([+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?(?![iI.\\d]))?([+-]?(?:(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?)?)?[iI]$");
    std::smatch match;

    std::ifstream infile("complex.txt");
    std::string line;

    while (std::getline(infile, line)) {
        if (std::regex_search(line, match, rgx)) {
            std::cout << "text: " << match[0] << ", real: " << match[1] << ", imaginary: " << match[2] << std::endl;
        }
    }
}

The regular expression is an edit to https://stackoverflow.com/a/50428157/1994239 which works for the sample text that you have provided.

Ali Tavakol
  • 417
  • 3
  • 11
0

You can use regular expressions to match the lines which contain imaginary numbers only. Following is the complete program solving your problem-

#include <iostream>
#include <fstream>
#include <string>
#include <regex>
using namespace std;

class Complex {
    public:
        Complex();
        Complex(double realNum);
        Complex(double realNum, double imagNum);

        //Complex(double real = 0.0, double imaginary = 0.0); This avoids the 3 above?
        Complex(const Complex& obj);
    private:
       double real;
       double imaginary;
 };

Complex::Complex(const Complex& obj) {
    real = obj.real;
    imaginary = obj.imaginary;
}

Complex::Complex () {
   real = 0;
   imaginary = 0;
}

Complex::Complex (double realNum) {
    real = realNum;
    imaginary = 0;
}

Complex::Complex (double realNum, double imagNum) {
   real = realNum;
   imaginary = imagNum;
}

int main () {
    Complex *complexArray = new Complex[8];
    ifstream myfile("test.txt");
    /* this will match the complex numbers of the form - 123.123 + 14.1244  or 123 - 1343.193 and so on, 
      basically assumes that both the real and the imaginary parts are both doubles*/
    regex reg_obj("^[ ]*([-]?\\d+(\\.\\d+)?)\\s*([+-])\\s*(\\d+(\\.\\d+)?)i");  
    smatch sm;
    string line;
    int i = 0;
    double real, imag;
    if (myfile.is_open()) {
        while (! myfile.eof()) {

            getline(myfile, line);
            if(regex_search(line, sm, reg_obj)){
                real = stod(sm[1]);       // this ([-]?\\d+(\\.\\d+)?) is group 1 and will match the real part of the number
                imag = stod(sm[4]);       // second group (\\d+(\\.\\d+)?)i is group 4 which matches the imaginary part of the complex number without matching + or - which are taken care of separately because there could be space between the +|- symbol and the imaginary part
                if(sm[3]=="-") imag = -imag;
                complexArray[i] = Complex(real, imag);
                i++;
            }
        }

        myfile.close();
     }else {
        cout << "Error. Could not find/open file." ;
     }
     return 0;
};
yabhishek
  • 391
  • 3
  • 14
  • Hi Yabhishek, thanks a lot! Regex is probably what I was looking for. I do have one question though...what do I do for double digit vs single digit numbers? ie: 1+2i and 11+2i? How to handle that? – Evan Sep 17 '19 at 05:37
  • @Evan `\\d+` will match one or more number of digits. So, you don't have to worry about matching single or double digits. – yabhishek Sep 17 '19 at 07:29
0

Use regex to do the validation.

#include <iostream>
#include <fstream>
#include <string>
#include <regex>

using namespace std;

class Complex
{

public:

    Complex();
    Complex(double realNum);
    Complex(double realNum, double imagNum);

    //Complex(double real = 0.0, double imaginary = 0.0); This avoids the 3 above?

    Complex(const Complex& obj);

    friend ostream & operator << (ostream &out, const Complex &c)
    {
        cout<<c.real<<" + "<<c.imaginary<<"i";
        return out;
    }


private:

    double real;
    double imaginary;



};


int main ()
{

    Complex *complexArray;
    complexArray = new Complex[8];

    ifstream myfile("complex.txt");

    string line;
    int i = 0;

    if (myfile.is_open())
    {

        while (! myfile.eof())
        {

            getline(myfile, line);
            const std::string& str = line;
            //use regex to identify if this line represents a complex number or not
            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
            {
                continue;
            }

            Complex c(real, imag);
            cout<<c<<endl;
            complexArray[i]=c;
            i++;

        }

        myfile.close();


    }
    else
    {

        cout << "Error. Could not find/open file." ;
    }



    return 0;

};


Complex::Complex(const Complex& obj)
{

    real = obj.real;
    imaginary = obj.imaginary;

};



Complex::Complex ()
{

    real = 0;
    imaginary = 0;

};



Complex::Complex (double realNum)
{

    real = realNum;
    imaginary = 0;

};



Complex::Complex (double realNum, double imagNum)
{

    real = realNum;
    imaginary = imagNum;

};
Imran Rana
  • 11,447
  • 7
  • 42
  • 51