0

I'm writing a program in which I have to read complex numbers from the console into a vector, containing Complex objects. I have overwritten the >> operator in order to do this, but my vector gets indexed in the in the interval [1..vector.size()] instead of [0..vector.size()). I want it to go from zero, but I can't figure it out.

Here is a minimal reproducible example:

#include <iostream>
#include <vector>
#include <sstream>

using namespace std;

class Complex
{
    private:
        double real, im;
    public:
        Complex(double v_real = 0, double v_im = 0): real(v_real), im(v_im) {};
        // getters
        double getReal() const
        {
            return this->real;
        }
        double getImaginary() const
        {
            return this->im;
        }
        // setters
        void setReal(double v_real)
        {
            this->real = v_real;
        }
        void setImaginary(double v_im)
        {
            this->im = v_im;
        } 
};


void operator>>(istream& i, Complex& c)
{
    string line;
    getline(i,line);
    istringstream ss (line);

    double temp_real;
    double temp_im;
    char oper;
    ss >> temp_real;
    ss >> oper;
    ss >> temp_im;
    if (oper == '-') temp_im *= -1;
    char junk_i;
    ss >> junk_i;
    c.setReal(temp_real);
    c.setImaginary(temp_im);
}


ostream& operator<<(ostream& o, Complex c)
{
    if (c.getImaginary() > 0)
    {
        o<<c.getReal()<<'+'<<c.getImaginary()<<'i'<<endl;
    }
    else
    {
        o<<c.getReal()<<c.getImaginary()<<'i'<<endl;
    }


    return o;
}


int main(){

    cout << "How many numbers will you create?" << endl;
    int num_of_complex; 
    cin >> num_of_complex;
    vector<Complex> v;
    Complex temp_c;

    for (int i = 0; i < num_of_complex; i++)
    {
        cin >> temp_c;
        v.push_back(temp_c);
    }

    for (int i = 0; i < v.size(); i++)
    {
        cout << v[i] << endl;
    }
}

Here is the input/output:

enter image description here

Ted Klein Bergman
  • 9,146
  • 4
  • 29
  • 50
Myxy290
  • 99
  • 1
  • 7
  • 3
    _"These are only a part of a larger program ..."_ Provide a [mcve] of the problem as required here please! – πάντα ῥεῖ Mar 12 '22 at 10:40
  • 3
    You need to provide a [mre]. Vectors are always indexed from 0, and in the code, you've provided you have put the first element at index 0. – Ted Klein Bergman Mar 12 '22 at 10:41
  • In the `operator>>` overload, what is the `junk_i` variable supposed to be for? – Some programmer dude Mar 12 '22 at 10:41
  • 1
    `void operator>>` -- This should return a reference to the input stream, not void. Example: `std::istream& operator>>(std::istream& i, Complex& c) { ... return i; }` – PaulMcKenzie Mar 12 '22 at 10:50
  • For the i at the end of the complex number, I don't have to store that and I didn't want to leave it unchecked – Myxy290 Mar 12 '22 at 10:51
  • Why do you say your vector is indexed from `1`? What is the exact input you give your program? What is the exact output you get? What is the expected output? – Some programmer dude Mar 12 '22 at 10:53
  • 1
    Regarding the `junk_i` variable, you don't need to extract that from the string stream, you can simply discard the remaining contents of the string stream. Unless you want to add validation that the input actually contains an `i` at the end. And then you need to make sure that there's really nothing more left in the string stream. And not skip white-space (which the `>>` operator does, even for string streams). – Some programmer dude Mar 12 '22 at 10:56
  • @Someprogrammerdude because the index 0 of my vector outputs a random number when referenced, and the first input number is at index 1. This has never happened before – Myxy290 Mar 12 '22 at 10:58
  • @PaulMcKenzie Thank you, I put it there. I forgot that that was needed. However this didn't solve my issue. – Myxy290 Mar 12 '22 at 11:00
  • @TedKleinBergman an example input would be 4(number of complexes),enter and in every new line a complex number like so: 1+1i,enter,2+2i,enter,3+3i,enter,4+4i,enter. However it stops after 3+3i and outputs the vector, junk value at 0 index and the 3 complex numbers after – Myxy290 Mar 12 '22 at 11:04
  • @TedKleinBergman could it be some kind of software issue then? It does not run correctly on my part – Myxy290 Mar 12 '22 at 11:06
  • @TedKleinBergman Yes, I use build and run in CodeBlocks. – Myxy290 Mar 12 '22 at 11:07
  • 1
    @Myxy290 -- *However this didn't solve my issue* -- The comment section is for comments, not answers. – PaulMcKenzie Mar 12 '22 at 11:32

2 Answers2

2

The problem is that you're reading the first number with cin >> num_of_complex;, but this does not move the cursor to a new line! This means that the next call (i.e. the first call to your overridden >>) with getline will read only an empty line and try to convert nothing into a complex number.

You can fix this by ignoring everything in the input buffer until the next newline or to the end of the buffer after reading the first number. This is done with the method:

cin.ignore(numeric_limits<streamsize>::max(), '\n');

Full working example:

#include <iostream>
#include <vector>
#include <stream>
#include <limits>

using namespace std;

class Complex
{
private:
    double real, im;
public:
    Complex(double v_real = 0, double v_im = 0): real(v_real), im(v_im) {};

    // Getters.
    double getReal() const
    {
        return this->real;
    }
    double getImaginary() const
    {
        return this->im;
    }

    // Setters.
    void setReal(double v_real)
    {
        this->real = v_real;
    }
    void setImaginary(double v_im)
    {
        this->im = v_im;
    }
};


istream& operator>>(istream& i, Complex& c)
{
    string line;
    getline(i, line);
    istringstream ss (line);

    double temp_real;
    double temp_im;
    char oper;
    ss >> temp_real;
    ss >> oper;
    ss >> temp_im;
    if (oper == '-') temp_im *= -1;
    char junk_i;
    ss >> junk_i;
    c.setReal(temp_real);
    c.setImaginary(temp_im);

    return i;
}


ostream& operator<<(ostream& o, Complex c)
{
    if (c.getImaginary() > 0)
        o << c.getReal() << '+' << c.getImaginary() << 'i' << endl;
    else
        o << c.getReal() << c.getImaginary() << 'i' << endl;

    return o;
}


int main()
{
    cout << "How many numbers will you create?" << endl;
    int num_of_complex;
    cin >> num_of_complex;

    // Ignore everything in the input buffer until a new line or the end
    // of the buffer.
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    vector<Complex> v;
    Complex temp_c;

    for (int i = 0; i < num_of_complex; i++)
    {
        cin >> temp_c;
        v.push_back(temp_c);
    }

    for (int i = 0; i < v.size(); i++)
    {
        cout << v[i] << endl;
    }
}
Ted Klein Bergman
  • 9,146
  • 4
  • 29
  • 50
  • Thank you! this solved my problem. I also had to `#include ` as well for this to work. Thank you for the help – Myxy290 Mar 12 '22 at 11:28
0

but my vector gets indexed in the [1..vector.size()] interval instead of [0..vector.size()). I want it to go from zero, but I can't figure it out.

Subtract 1 from the 1 based index to get the 0 based index that is used by the standard vector. Example:

std::vector<int> v{5, 6, 7};
std::size_t index = 2; // should access value 6
std::cout << v[index - 1];
eerorika
  • 232,697
  • 12
  • 197
  • 326