Need help with my mock exam

We are given a main and we have to code the classes without additional includes and so on (of course without changing the main).

When i run the programm i get this return (the supposed output is commented in the main.cpp right after the return 0):

1
2
3
4
5
6
7
8x^5+0x^4+0x^3+3x^2+-2x^1+7x^0
1x^2+1x^1+1x^0 -5x^0
-1x^4+0x^3+-1x^2+0x^1+-1x^0
1x^6+0x^5+0x^4+0x^3+0x^2+0x^1+0x^0
Leitindex 0 nicht erlaubt!

Process finished with exit code -1073741819 (0xC0000005)


I know from this error code that it is a memory access violation error. I also found out that it is the exection handling in the constructor that is making problems. I think the constructor should be public and accessible without problems.


main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include<iostream>
#include<vector>
#include<string>
#include<stdexcept>
#include"Polynom.h"
using namespace std;

int main() {
  Polynom p {{7,-2,3,0,0,8}};
  cout << p << '\n';
  cout << Polynom{{1,1,1}} << " " << Polynom{{-5}} << '\n';
  cout << Polynom{{-1,0,-1,0,-1}}<<'\n';
  cout << Polynom{{0,0,0,0,0,0,1}}<<'\n';
  try {
    cout << Polynom{{4,-1,0,0}};
    cout << Polynom{{2}};
  }
  catch (runtime_error& e) {
    cout << "Leitindex 0 nicht erlaubt!\n";
  }
  try {
    cout << Polynom{{}};
  }
  catch (runtime_error& e) {
    cout << "Leere Initialisierungsliste nicht erlaubt!\n";
  }
  cerr << p << '\n';
  cerr << p.grad() << ' ' << Polynom{{1,2,3}}.grad() << '\n';

  //Dekommentieren fuer Zusatz wert
  /*
  cout << Polynom{{4,-1,1}}.wert(2)<<'\n';
  cout << p.wert(-1) << ' ' << p.wert(7) << ' ' << p << '\n';
  */

  //Dekommentieren fuer Zusatz print_fmt
  /*
  p.print_fmt(cout)<<'\n';
  Polynom{{1,1,1}}.print_fmt(cout)<<'\n';
  Polynom{{-5}}.print_fmt(cout)<<'\n';
  Polynom{{-1,0,-1,0,-1}}.print_fmt(cout)<<'\n';
  Polynom{{0,0,0,0,0,0,1}}.print_fmt(cerr)<<'\n';
  */

  return 0;
}

/*
8x^5+0x^4+0x^3+3x^2+-2x^1+7x^0
1x^2+1x^1+1x^0 -5x^0
-1x^4+0x^3+-1x^2+0x^1+-1x^0
1x^6+0x^5+0x^4+0x^3+0x^2+0x^1+0x^0
Leitindex 0 nicht erlaubt!
Leere Initialisierungsliste nicht erlaubt!
8x^5+0x^4+0x^3+3x^2+-2x^1+7x^0
5 2

//Ausgabe für Zusatz wert
6
4 134596 8x^5+0x^4+0x^3+3x^2+-2x^1+7x^0

//Ausgabe für Zusatz print_fmt
8x^5+3x^2-2x+7
x^2+x+1
-5
-x^4-x^2-1
x^6
*/



Polynom.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef CLION_POLYNOM_H
#define CLION_POLYNOM_H

#include<iostream>
#include<vector>
#include<string>
#include<stdexcept>
using namespace std;

class Polynom {
private:
    vector<int> vec;
public:
    Polynom(vector<int>);
    int grad() const;
    ostream& print(ostream&) const;
};

ostream& operator<< (ostream&, const Polynom&);


#endif //CLION_POLYNOM_H 



Polynom.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<iostream>
#include<vector>
#include<string>
#include<stdexcept>
#include"polynom.h"
using namespace std;

Polynom::Polynom(vector<int> vec)
:vec(vec)
{
    if(vec.back() == 0){
        throw runtime_error("5");
    }if(vec.size() == 0){
        throw runtime_error("2");
    }
}

int Polynom::grad() const{
    return vec.size();
}

ostream& Polynom::print(ostream& o) const{
    for (int i = 0; i < vec.size(); i++){
        if(i == vec.size()-1){
            o << (to_string(vec[vec.size()-(i+1)]) + "x^" + to_string(vec.size() - (i+1)));
        } else{
            o << (to_string(vec[vec.size()-(i+1)]) + "x^" + to_string(vec.size() - (i+1)) + "+");
        }

    }
    return o;
}

ostream& operator<< (ostream& o, const Polynom& p){
    p.print(o);
    return o;
}
Last edited on
The source of your problem was that the vector iterator was constantly out of range. I made some changes in your Polynom.cpp and Polynom header files. (They are highlighted in bold-text);

The change made to your return statement in line 19:

 
   return vec.size() -1;


was to get the correct output 5 2. Otherwise the resulting output would be 6 3. (And don't ask me why - that, you have to figure out yourself.)

The reason for changing int to size_t in both files was, that possible loss of data as a result from demoting size_t to int can occur. (At least that is what VS warns about, and I treat warnings the same way as errors. ;-))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<iostream>
#include<vector>
#include<string>
#include<stdexcept>
#include"polynom.h"
using namespace std;

Polynom::Polynom(vector<int> vec)
	:vec(vec)
{
	if (vec.end(), vec.begin(), vec.size() == 0) {
		throw runtime_error("5");
	}if (vec.size() == 0) {
		throw runtime_error("2");
	}
}

size_t Polynom::grad() const {
	
	return vec.size()-1;
}

ostream& Polynom::print(ostream& o) const {
	for (size_t i = 0; i < vec.size(); i++) {
		if (i == vec.size()-1) {
			o << (to_string(vec[vec.size() - (i + 1)]) + "x^" + to_string(vec.size() - (i + 1)));
		}
		else {
			o << (to_string(vec[vec.size() - (i + 1)]) + "x^" + to_string(vec.size() - (i + 1)) + "+");
		}

	}
	return o;
}


ostream& operator<< (ostream& o, const Polynom& p) {
	p.print(o);
	return o;
}


POLYNOM.H

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef CLION_POLYNOM_H
#define CLION_POLYNOM_H

#include<iostream>
#include<vector>
#include<string>
#include<stdexcept>
using namespace std;

class Polynom {
private:
	vector<int> vec;
public:
	Polynom(vector<int>);
	size_t grad() const;
	ostream& print(ostream&) const;
};

ostream& operator << (ostream&, const Polynom&);


#endif //CLION_POLYNOM_H  
Last edited on
I dont get the right output

What i get is

1
2
3
4
5
6
7
8
9
8x^5+0x^4+0x^3+3x^2+-2x^1+7x^0
8x^5+0x^4+0x^3+3x^2+-2x^1+7x^0 //for some reason this is in red
1x^2+1x^1+1x^0 -5x^0
5 2 //for some reason this is in red
-1x^4+0x^3+-1x^2+0x^1+-1x^0
1x^6+0x^5+0x^4+0x^3+0x^2+0x^1+0x^0
0x^3+0x^2+-1x^1+4x^02x^0Leere Initialisierungsliste nicht erlaubt!

Process finished with exit code 0

And for some reason two lines were red (i makred it with comments). Is it because i use CLion? I ll add the CMakeList just in case...


CMakeList.txt


1
2
3
4
5
6
7
cmake_minimum_required(VERSION 3.7)
project(CLion)

set(CMAKE_CXX_STANDARD 11)

set(SOURCE_FILES main.cpp Polynom.cpp Polynom.h)
add_executable(CLion ${SOURCE_FILES} Polynom.cpp Polynom.h)


I use MinGW 5.0, Bundled CMake 3.7.2, Bundled 7.11.1

the condition for (vec.end(), vec.begin(), vec.size() == 0) is that the last number of polynom must not be 0. So it should be something like vec.back(), vec.at(vec.size()-1), vec[vec.size()-1], but none of these worked.
> if (vec.end(), vec.begin(), vec.size() == 0)
that does not do what you think it does. (by the way, ¿do you think that's `and' or `or'?)
but yeah, the original code was trying to access `.back()' of an empty vector.


> throw runtime_error("5");
great, instead of returning a meaningful message you return an error code masked as a string.
whatever, it's not like you check it in your catch.


> And for some reason two lines were red
I don't see anywhere in your code anything that produces colored output.
edit: perhaps cmake is marking the error output (std::cerr)
Last edited on
> if (vec.end(), vec.begin(), vec.size() == 0)
that does not do what you think it does. (by the way, ¿do you think that's `and' or `or'?)
but yeah, the original code was trying to access `.back()' of an empty vector.

Neither, I thought from -> to. Iterator range. Checking from begin to end whether the vector is empty. Thinking it over:

if (vector.empty()) { }

would have probably been the correct/or better solution to the OP's problem. :)
Last edited on
if (vec.end(), vec.begin(), vec.size() == 0) {
This doesn't do what you think. It is equivalent to
1
2
3
vec.end();  // call vec.end() and throw away the result
vec.begin(); // call vec.begin() and throw away the result
if (vec.size() == 0) {  // check vec.size 

The real problem with the constructor is that you were accessing vec.back() before checking vec.size() to verify that there was an item to access. So if the vector is empty, then vec.back() will throw an exception. The constructor should be:
1
2
3
4
5
6
7
8
9
10
Polynom::Polynom(vector<int> vec)  // const vector<int> & would be more efficient
:vec(vec)
{
    if(vec.size() == 0){
        throw runtime_error("2");
    }
    if(vec.back() == 0){
        throw runtime_error("5");
    }
}

Your print method is more complicated than necessary. You don't need to convert everything to a string, just use the << operator:
1
2
3
4
5
6
7
8
9
10
    for (int i = 0; i < vec.size(); i++) {
        if (i == vec.size() - 1) {
            o << vec[vec.size() - (i + 1)] << "x^" <<
                vec.size() - (i + 1);
        } else {
            o << vec[vec.size() - (i + 1)] << "x^" <<
                vec.size() - (i + 1) << "+";
        }

    }

Your code basically says "if it's the last term then print the term, otherwise print the term and a plus sign. You can simplify the logic by printing the first term outside the loop (there is always at least one term). Then inside the loop print "+" and the next term.

Also, you can do less arithmetic if you run the index backwards:
1
2
3
4
5
6
7
    // vec.size() is guaranteed to be non-zero
    int i=vec.size()-1;

    o << vec[i] << "x^" << i;
    while (--i >= 0) {
        o << '+' << vec[i] << "x^" << i;
    }


> throw runtime_error("5");
great, instead of returning a meaningful message you return an error code masked as a string.
whatever, it's not like you check it in your catch.


I missunderstood the "5 2" from my answer output. I just realised that those two numbers come from the method "grad()"


> And for some reason two lines were red
I don't see anywhere in your code anything that produces colored output.
edit: perhaps cmake is marking the error output (std::cerr)


well it also should have printed those lines at all. One was printed twice and the other one was printed too early, which confuses me.


Neither, I thought from -> to. Iterator range. Checking from begin to end whether the vector is empty. Thinking it over:

if (vector.empty()) { }

would have probably been the correct/or better solution to the OP's problem. :)


Can if (vector.empty()) { } only check the last value?I though if (vector.empty()) { } is something like vec.size == 0. The first error should only trigger when the last value is 0, because for example 0x^3+1x^2+2x^1+3 isnt a third-degree polynomial.


Your print method is more complicated than necessary. You don't need to convert everything to a string, just use the << operator:
1
2
3
4
5
6
7
8
9
10
    for (int i = 0; i < vec.size(); i++) {
        if (i == vec.size() - 1) {
            o << vec[vec.size() - (i + 1)] << "x^" <<
                vec.size() - (i + 1);
        } else {
            o << vec[vec.size() - (i + 1)] << "x^" <<
                vec.size() - (i + 1) << "+";
        }

    }


I converted them to string at because i made a mistake before that i used o += instead of o <<, which made me change so much of my original code.

I did all the changes now i get

1
2
3
4
5
6
7
8
9
10
8x^5+0x^4+0x^3+3x^2+-2x^1+7x^0 //for some reason this is in red
8x^5+0x^4+0x^3+3x^2+-2x^1+7x^0
5 2 //for some reason this is in red
1x^2+1x^1+1x^0 -5x^0
-1x^4+0x^3+-1x^2+0x^1+-1x^0
1x^6+0x^5+0x^4+0x^3+0x^2+0x^1+0x^0
Leitindex 0 nicht erlaubt!
Leere Initialisierungsliste nicht erlaubt!

Process finished with exit code 0


I think the red ones are printed with cerr, the only weird thing about this is the order. for some reason the last two lines are printed first and thrid. I ll post the current Polynom.h and Polynom.cpp againt.


Polynom.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef CLION_POLYNOM_H
#define CLION_POLYNOM_H

#include<iostream>
#include<vector>
#include<string>
#include<stdexcept>
using namespace std;

class Polynom {
private:
    vector<int> vec;
public:
    Polynom(vector<int>);
    size_t grad() const;
    ostream& print(ostream&) const;
};

ostream& operator << (ostream&, const Polynom&);


#endif //CLION_POLYNOM_H 



Polynom.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Polynom::Polynom(vector<int> vec)
        :vec(vec)
{
    if (vec.size() == 0) {
        throw runtime_error("2");
    }if(vec.back() == 0){
        throw runtime_error("5");
    }
}

size_t Polynom::grad() const {

    return vec.size()-1;
}

ostream& Polynom::print(ostream& o) const {
    int i=vec.size()-1;

    o << vec[i] << "x^" << i;
    while (--i >= 0) {
        o << '+' << vec[i] << "x^" << i;
    }
    return o;
}


ostream& operator<< (ostream& o, const Polynom& p) {
    p.print(o);
    return o;
}


Thanks for help, very nice tips and optimization. I would be nice if the order can be solved, but it is possible that it cause by CLion.
Last edited on
> Can if (vector.empty()) { } only check the last value?I though
> if (vector.empty()) { } is something like vec.size == 0.
yes, `vector.empty()' and `vector.size()==0' are equivalent.
the problem was that you were accessing `vector.back()' but the container was empty.
now you fixed it because you first check if there are elements to be accessed.

> I would be nice if the order can be solved, but it is possible that it cause
> by CLion.
cerr (stderr) and cout (stdout) are different streams
would need to check the standard to affirm that stdout must be flushed before a write to stderr.
didn't realise that you could end with interleaved output.
> I would be nice if the order can be solved, but it is possible that it cause
> by CLion.
cerr (stderr) and cout (stdout) are different streams
would need to check the standard to affirm that stdout must be flushed before a write to stderr.
didn't realise that you could end with interleaved output.


that is interesting. I didnt though of that. If that is the problem then i should be able to solve it by either adding flush or endl... I changed my constructor and it worked. Thx u very much.


constructor

1
2
3
4
5
6
7
8
9
10
Polynom::Polynom(vector<int> vec)
        :vec(vec)
{
    cout << flush;
    if (vec.size() == 0) {
        throw runtime_error("2");
    }if(vec.back() == 0){
        throw runtime_error("5");
    }
}



Output

1
2
3
4
5
6
7
8
9
10
8x^5+0x^4+0x^3+3x^2+-2x^1+7x^0
1x^2+1x^1+1x^0 -5x^0
-1x^4+0x^3+-1x^2+0x^1+-1x^0
1x^6+0x^5+0x^4+0x^3+0x^2+0x^1+0x^0
Leitindex 0 nicht erlaubt!
Leere Initialisierungsliste nicht erlaubt!
8x^5+0x^4+0x^3+3x^2+-2x^1+7x^0
5 2

Process finished with exit code 0

Topic archived. No new replies allowed.