Dot product assignment... error checking

Hey everyone,

I'm doing a program for class and am sort of stuck with it.

The goal is to calculate the dot product of two vectors with numbers that the user inputs. It does that, but it must also give an error if the input is either negative or greater than 100. That is my problem. I am supposed to use cin.good() which I haven't ever tried before, so I don't know if I'm using that right or not in my program.

I'll post the whole code as well as the errors I am getting.

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/************************************************************/
// System includes

#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
#include <stdexcept>

/************************************************************/
// Local includes


/************************************************************/
// Using declarations

using namespace std;

/************************************************************/
// Function prototypes/global vars/typedefs

void
vectorInput(vector<double>& v);

void
errorCheck(vector<double>& v1, vector<double>& v2);

void
setOutputDigits(int digits);

double
calculateDotProduct(const vector<double>& v1, const vector<double>& v2);

void
printVectors(const vector<double> p, string s);

/************************************************************/

int      
main () 
{  

 int vectorSize= 0;
 cout << "Enter size of vector" << endl;
 cin >> vectorSize;
 vector<double> v1 (vectorSize, 0);
 vector<double> v2 (vectorSize, 0);

 cout << "Maximum # of values to input is " << vectorSize * 2
      << ". Any additional input is disregarded." << endl;
 cout << "Enter values to calculate dot product of (Ctrl + D to terminate)."
      << endl;
 vectorInput(v1);
 vectorInput(v2);
 setOutputDigits(1);

 printVectors (v1, "Vector 1 => ");
 cout << endl;
 printVectors (v2, "Vector 2 => ");

 errorCheck(v1, v2);
   double dotProduct = calculateDotProduct(v1, v2);
   cout << "The dot product is " << dotProduct << endl;

 return EXIT_SUCCESS;
}

void
printVectors(const vector<double> p, string s)
{
 cout << s;
 for (unsigned int i = 0; i<p.size(); i++){
   cout <<  "[" << i << "] " <<  p[i] << "  ";
 }
 cout << endl;

}

double
calculateDotProduct(const vector<double>& v1, const vector<double>& v2)
{
  double product = 0;
   for (unsigned int i = 0; i <= v1.size()-1; i++)
      product += (v1[i])*(v2[i]);
   return product;
     
}


// set pretty output format and number of digits after decimal
void
setOutputDigits(int digits)
{
  cout.precision(digits);
  cout.setf(ios::fixed | ios::dec | ios::showpoint);
}
 

void
vectorInput(vector<double>& v)
{
  int size = v.size( );
  for (int i = 0; i < size && cin >> v[i]; i++) {
  }
}

void
errorCheck(vector<double>& v1, vector<double>& v2)
{
 while(cin.good())
   {
     if (vectorInput(v1) >= 100 || vectorInput(v1) < 0.0 ||
	 vectorInput(v2) >= 100 || vectorInput(v2) < 0.0 ||
	 !cin.good())
       {
	 cout << "Invalid input\n";
       }
     else
       {
	 break;
       }
   }
}

/************************************************************/
/************************************************************/



Errors:
1
2
3
4
5
dot.cpp: In function ‘void errorCheck(std::vector<double>&, std::vector<double>&)’:
dot.cpp:122:29: error: void value not ignored as it ought to be
dot.cpp:122:59: error: void value not ignored as it ought to be
dot.cpp:123:22: error: void value not ignored as it ought to be
dot.cpp:123:47: error: void value not ignored as it ought to be



Any help on figuring this out is greatly appreciated!
Try removing the else in the errorCheck?

Also 100 isn't a double. 100.0 is.
Last edited on
After changing it to:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
oid
errorCheck(vector<double>& v1, vector<double>& v2)
{
 while(cin.good())
   {
     if (vectorInput(v1) >= 100.0 || vectorInput(v1) < 0.0 ||
	 vectorInput(v2) >= 100.0 || vectorInput(v2) < 0.0 ||
	 !cin.good())
       {
	 cout << "Invalid input\n";
       }
	 break;
   }
}


I get the same errors. =/
vectorInput is a function which returns nothing.

You are trying to compare the nothing it returns with something. The compiler doesn't know how to compare nothing to something, and it is informing you of that fact. Furthermore, each call to vectorInput overwrites the values obtained from previous calls to vectorInput.

It would make more sense to evaluate each input extraction in vectorInput to see if the qualifications for valid input are met.
Last edited on
If I'm understanding you correctly, check for valid input in vectorInput rather than a separate function? Or am I going to use things from main in vectorInput?
check for valid input in vectorInput rather than a separate function?

Yes.

The cin.good() checks whether cin is ok. If cin is not ok, then the previous input from cin has probably failed and all the following inputs will fail too (unless you clear the error state). In your case, you probably want to check after each cin >> value;. Then, if you did get a valid double, you will make the range check. If that succeeds, then you have a double value that is in [0.0..100.0] and you can store it as next element in a vector.

If the value is not in range, you need a new value.
If the read failed, you need a new double value, or abort.
Whether you use a separate function or not is up to you, but the input validation (or the invocation of the function which does input validation) should be done in vectorInput.

By way of example:
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
#include <vector>
#include <iostream>
#include <limits>

bool validInput(double value)
{
    return value <= 100.0 && value >= 0.0;
}

double getValue()
{
    const char* prompt = "> ";

    bool inputIsValid = false;
    double value;

    while ( !inputIsValid )
    {
        std::cout << prompt;
        std::cin >> value;

        inputIsValid = std::cin.good() && validInput(value);

        if (!inputIsValid)
        {
            std::cout << "Invalid input! Try again!\n";
            std::cin.clear();   // clear error state on the input stream and remove erroneous input
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            // Also see: http://www.parashift.com/c++-faq/istream-and-ignore.html
        }
    } 
    return value;
}

int main()
{
    const unsigned nValues = 10;

    std::vector<double> v;
    std::cout << "Enter 10 floating point values, one at a time: ";

    for (unsigned i = 0; i < 10; ++i)
        v.push_back(getValue());

    for (unsigned i = 0; i < v.size(); ++i)
        std::cout << v[i] << '\n';
}
Last edited on
Hey,

Thanks for posting that code, it's very helpful in understanding cin.good().

I am trying to utilize the features of your code that help with my code, and I encountered three problems.

First, Ctrl + D does not terminate input. Is that the cost of using cin.clear or cin.ignore? I want my program to be able to do that, and I am curious if there is a work-around.

Second, the way my output is formatted is that whatever N the user inputs, each vector outputs N amount of 0.0's, then it outputs the numbers that I want after those 0.0's and calculates the dot product as intended. I am not sure how to fix this. =/

Third, if I try to make my vectorSize 1, aka fill in two values to calculate, it accepts four, as if I had put in vectorSize of 2. Not sure about that one.


I'm going to repost the code implementing most of your code, and show an output that I get:

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/************************************************************/
// System includes

#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
#include <stdexcept>
#include <limits>

/************************************************************/
// Using declarations

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::numeric_limits;
using std::ios;
using std::streamsize;

/************************************************************/
// Function prototypes/global vars/typedefs

bool
validInput (double value);

double
getValue ();

void
setOutputDigits (int digits);

double
calculateDotProduct (const vector<double>& v1, const vector<double>& v2);

void
printVectors (const vector<double> p, string s);

/************************************************************/

int      
main () 
{  

  int vectorSize= 0;
  cout << "Enter size of vector => ";
  cin >> vectorSize;
  vector<double> v1 (vectorSize, 0);
  vector<double> v2 (vectorSize, 0);

  cout << "Maximum # of values to input is " << vectorSize * 2
       << ". Any additional input is disregarded." << endl;
  cout << "Enter " << vectorSize*2
       << " floating point values (Ctrl + D to terminate): ";

  for (int i = 0; i < vectorSize; ++i)
  {
    v1.push_back (getValue ());
    v2.push_back (getValue ());
  }

  setOutputDigits (1);
  printVectors (v1, "Vector 1 => ");
  cout << endl;
  printVectors (v2, "Vector 2 => ");
  cout << endl;

  double dotProduct = calculateDotProduct(v1, v2);
  cout << "The dot product is " << dotProduct << endl;

  return EXIT_SUCCESS;
}


void
printVectors (const vector<double> v, string s)
{
  cout << s;
  for (unsigned int i = 0; i < v.size (); i++)
  {
    cout <<  "[" << i << "] " <<  v[i] << "  ";
  }
  cout << endl;
}


double
calculateDotProduct (const vector<double>& v1, const vector<double>& v2)
{
  double product = 0;
  for (unsigned int i = 0; i <= v1.size()-1; i++)
  {
    product += (v1[i])* (v2[i]);
  }
  return product;   
}


// set pretty output format and number of digits after decimal
void
setOutputDigits (int digits)
{
  cout.precision (digits);
  cout.setf (ios::fixed | ios::dec | ios::showpoint);
}


bool validInput (double value)
{
  return value <= 100.0 && value >= 0.0;
}


double getValue ()
{
  const char* prompt = "> ";
  bool inputIsValid = false;
  double value;

  while (!inputIsValid)
  {
    cout << prompt;
    cin >> value;
    inputIsValid = cin.good () && validInput (value);

    if (!inputIsValid)
    {
      cout << "Invalid input! Try again!\n";
      cin.clear ();
      cin.ignore (numeric_limits<streamsize>::max (), '\n');
    }
  } 
  return value;
}

/************************************************************/
/************************************************************/



Error with vectorSize of 2:

1
2
3
4
5
6
7
8
9
10
11
12
Enter size of vector
1
Maximum # of values to input is 2. Any additional input is disregarded.
Enter 2 floating point values (Ctrl + D to terminate): > 1
> 2
> 2
> 3
Vector 1 => [0] 0.0  [1] 1.0  [2] 2.0  

Vector 2 => [0] 0.0  [1] 2.0  [2] 3.0  

The dot product is 8.0


That shows both the fact that I needed 4 values instead of 2, and that v[0] was 0.0, which I don't intend.

Hopefully somebody can point me in the right direction. I feel like it's an error with my printVectors function, but I am confused as to how to fix it.






*EDIT*

Just realized that the 1 more was an off by one error with my for loop. Went to i <= vectorSize instead of i < vectorSize. Oops!

The 0.0 is still an issue, as well as Ctrl + D.
Last edited on
> First, Ctrl + D does not terminate input. Is that the cost of using cin.clear or cin.ignore?
No, that's the cost of using cin.good()
Or better said, that's the cost of no checking cin.eof()
1
2
3
4
5
while(cin>>x and x>0){}
//if we are here, several things may have happen
//x has an "invalid" value, like -42
//the input failed because it does not encountered a number (maybe it tried to read a character)
//the input failed because there is nothing to read (eof) 



> Second, each vector outputs N amount of 0.0's, then it outputs the numbers that I want after those 0.0's
vector<double> v1 (vectorSize, 0); that's how you created your vectors. Of size N, and filled with 0
Then when reading you do v1.push_back (getValue ()); effectively increasing their size.
Last edited on
Would

while( !cin.eof())

be effective?


Also, the second part makes sense. I am going to assume I need to use insert from the vector library rather than push_back. Since I am using cin >> value in getValue, would it be wise to implement it there, or would it be best to call value to main and use that in the for loop?

For example,

1
2
3
4
5
    for (int i = 0; i < vectorSize; ++i)
    {
      v1.insert (value, getValue ());
      v2.insert (value, getValue ());
    }



Or something along those lines.
Also, the second part makes sense. I am going to assume I need to use insert from the vector library rather than push_back.


.. which will result in exactly the same problem. The solution is to either start with an empty vector, or modify existing elements of the vector. It is not to add elements to already existing elements in a different way.

1
2
3
std::vector <int> v ;     // empty vector
std::vector <int> u (n) ; // vector with n elements.
std::vector <int> w(n, x) ;  // vector with n elements all having the value x. 


In the context of the code I posted earlier, if I wanted getValue to fail on encountering eof in the input stream, I need to modify the design to achieve that. There has to be some way to indicate to the calling code that the function failed to retrieve a value. There are three ways we could change getValue to do that. We could return a sentinel value that indicates the function failed. We could throw an exception if we encounter eof. We could change the signature of getValue so that it returns an indicator of success or failure.

I prefer the latter.

Modifying the previous example:
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
#include <vector>
#include <iostream>
#include <limits>

bool validInput(double value)
{
    return value <= 100.0 && value >= 0.0;
}

bool getValue(double& value)
{
    const char* prompt = "> ";

    bool inputIsValid = false;

    while (!inputIsValid)
    {
        std::cout << prompt;
        std::cin >> value;

        inputIsValid = std::cin.good() && validInput(value);

        if (!inputIsValid)
        {
            if (std::cin.eof())     // eof was encountered,
                return false;       // signal failure 

            std::cout << "Invalid input! Try again!\n";
            std::cin.clear();   // clear error state on the input stream and remove erroneous input
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            // Also see: http://www.parashift.com/c++-faq/istream-and-ignore.html
        }
    }

    return true;
}

int main()
{
    const unsigned nValues = 10;

    std::vector<double> v;
    std::cout << "Enter floating point values, one at a time: ";

    double value;
    while (getValue(value))
        v.push_back(value);

    for (unsigned i = 0; i < v.size(); ++i)
        std::cout << v[i] << '\n';
}


Can you explain why you declared nValues but never used it? I tried to compile your code and it failed because of that, if I comment it out it is an endless stream of integers for me to type.


Also, utilizing your suggestions, the first value I type in becomes the value of every single element of v1 and v2 for all N, then the next time I put a number in for value, it adds N more spots, then etc.

I feel like it has to involve:

1
2
3
4
5
6
7
8
  double value;
  while(getValue(value))
  {
    for (int i = 0; i < vectorSize; ++i)
    {
      v1.push_back(value);
      v2.push_back(value);
    }


I also changed v1 and v2 to simply
1
2
vector<double> v1;
  vector<double> v2;
Last edited on
Can you explain why you declared nValues but never used it? I tried to compile your code and it failed because of that, if I comment it out it is an endless stream of integers for me to type.

I modified the previous code example. It was leftover from that.

if I comment it out it is an endless stream of integers for me to type.

Until the stream has eof signaled, yes. That was what you were asking for wasn't it?
Hi again, sorry it took so long to get back to this. I've had other assignments and this became sort of a non-priority for the time being.


Basically, what I'm at now is a code that compiles cleanly, does indeed go until Ctrl + D, but sort of goes crazy when I put in values.

Here's the current state of the code:

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/************************************************************/
// System includes

#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
#include <stdexcept>
#include <limits>

/************************************************************/
// Using declarations

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::numeric_limits;
using std::ios;
using std::streamsize;
using std::fill;

/************************************************************/
// Function prototypes/global vars/typedefs

bool
validInput (double value);

bool
getValue (double& value);

void
setOutputDigits (int digits);

double
calculateDotProduct (const vector<double>& v1, const vector<double>& v2);

void
printVectors (const vector<double> p, string s);

/************************************************************/

int      
main () 
{  

  int vectorSize= 0;
  cout << "Enter size of vector => ";
  cin >> vectorSize;
  vector<double> v1;
  vector<double> v2;

  cout << "Maximum # of values to input is " << vectorSize * 2
       << ". Any additional input is disregarded." << endl;
  cout << "Enter " << vectorSize*2
       << " floating point values (Ctrl + D to terminate): ";

  double value;
  while(getValue(value))
  {
    for (int i = 0; i < vectorSize; ++i)
    {
      v1.push_back(value);
      v2.push_back(value);
    }

    setOutputDigits (1);
    printVectors (v1, "Vector 1 => ");
    cout << endl;
    printVectors (v2, "Vector 2 => ");
    cout << endl;

    double dotProduct = calculateDotProduct(v1, v2);
    cout << "The dot product is " << dotProduct << endl;

  }
  return EXIT_SUCCESS;
}


void
printVectors (const vector<double> v, string s)
{
  cout << s;
  for (unsigned int i = 0; i < v.size (); i++)
  {
    cout <<  "[" << i << "] " <<  v[i] << "  ";
  }
  cout << endl;
}


double
calculateDotProduct (const vector<double>& v1, const vector<double>& v2)
{
  double product = 0;
  for (unsigned int i = 0; i <= v1.size()-1; i++)
  {
    product += (v1[i])* (v2[i]);
  }
  return product;   
}


// set pretty output format and number of digits after decimal
void
setOutputDigits (int digits)
{
  cout.precision (digits);
  cout.setf (ios::fixed | ios::dec | ios::showpoint);
}


bool
validInput (double value)
{
  return value <= 100.0 && value >= 0.0;
}


bool
getValue (double& value)
{
  const char* prompt = "> ";
  bool inputIsValid = false;

  while (!inputIsValid)
  {
    cout << prompt;
    cin >> value;
    inputIsValid = cin.good () && validInput (value);

    if (!inputIsValid)
    {
      if (cin.eof())
	return false;

	cout << "Invalid input! Try again!\n";
	cin.clear ();
	cin.ignore (numeric_limits<streamsize>::max (), '\n');
      
    } 
  }
  return true;
}

/************************************************************/
/************************************************************/



When I put in an integer in in the terminal, it does some weird stuff.... for example:

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
Enter size of vector => 1   
Maximum # of values to input is 2. Any additional input is disregarded.
Enter 2 floating point values (Ctrl + D to terminate): > d
Invalid input! Try again!
> 3
Vector 1 => [0] 3.0  

Vector 2 => [0] 3.0  

The dot product is 9.0
> 4
Vector 1 => [0] 3.0  [1] 4.0  

Vector 2 => [0] 3.0  [1] 4.0  

The dot product is 25.0
> 5
Vector 1 => [0] 3.0  [1] 4.0  [2] 5.0  

Vector 2 => [0] 3.0  [1] 4.0  [2] 5.0  

The dot product is 50.0
> 6
Vector 1 => [0] 3.0  [1] 4.0  [2] 5.0  [3] 6.0  

Vector 2 => [0] 3.0  [1] 4.0  [2] 5.0  [3] 6.0  

The dot product is 86.0
> 


It's seeming like this code is turning into one step forward, two steps back. It does this same sort of thing endlessly until I stop inputting. I truly do not know why it calculates the dot product at every turn and continuously fills it with more values when I specify that I want.

My current thought process is that my for loop in main with the v1.push_back and v2.push_back is the problem. My solution to that, however, does not exist.

Any thoughts? =/
It's seeming like this code is turning into one step forward, two steps back. It does this same sort of thing endlessly until I stop inputting. I truly do not know why it calculates the dot product at every turn and continuously fills it with more values when I specify that I want.

It's doing exactly what you tell it to do.

What does the for loop in the following code accomplish? How is vectorSize related to the actual size of the vectors? Do you calculate the dot product once per iteration of the while loop? Should you?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  while(getValue(value))
  {
    for (int i = 0; i < vectorSize; ++i)
    {
      v1.push_back(value);
      v2.push_back(value);
    }

    setOutputDigits (1);
    printVectors (v1, "Vector 1 => ");
    cout << endl;
    printVectors (v2, "Vector 2 => ");
    cout << endl;

    double dotProduct = calculateDotProduct(v1, v2);
    cout << "The dot product is " << dotProduct << endl;

  }
Topic archived. No new replies allowed.