Chapter 4 Drill #7

94 views
Skip to first unread message

Shawn

unread,
Dec 26, 2009, 9:43:13 AM12/26/09
to PPP-public
So, I am really confused with this one.

I am starting out with this:

#include <iostream>

using namespace std;

int main()
{
double smallest = 0, largest = 0;
double entry;

cout << "Please enter a number: ";
cin>>entry;
smallest=largest=entry;
cout << "Please enter another number: ";

while(cin>>entry)
{
if (entry < smallest)
{
smallest = entry;
cout << entry << " smallest so far.\n";
}
else if (entry > largest)
{
largest = entry;
cout << entry << " largest so far.\n";
}
else
cout << entry << " is neither the smallest nor the largest so far.
\n";
cout << "Please enter another number: ";
}

return 0;
}

Assuming we are adding a units to it, and still tracking largest and
smallest, how then do we differentiate the double and string part of
the users input? Do we assume there will be a space between the double
and the unit?

As far as largest and smallest, is there a way to write a function
that takes any "unit" and converts it to one particular unit, in order
to do a comparison of large vs. small? Or is there a better way to do
that?

Adrian G. Mowrey

unread,
Dec 26, 2009, 10:39:32 AM12/26/09
to ppp-p...@googlegroups.com
That's what I'm thinking too. You'll be reading the numerical values into a double and the unit type into a string. In order to do that, the user will have to type a "space" between the two (double and string). The drill says "Read the unit indicator into a string," which is referring to cm, m, in, or ft.

P.S. -- But at the beginning of the drill it also says: Enter values such as 10cm, 2.5in, 5ft, or 3.33m..., which in this case there is no space between the double and the string (unit indicator), so I'm not really sure how that will be done...to separate the double from the unit indicator after you're reading it into a string, etc. I haven't read the chapter yet, but what I'm thinking is that you can make two vectors (double and string)...and read the values into them at the same element level. If you enter let's say 3 [space] m that will be 3m. That means you'll be reading 3 into the double_vector[0]; and m into the string_vector[0]; to associate them..., and then you'll be able to write them together without spaces in between at the output with "cout"...and later on you can do the conversion onto the double_vector[n element that you want];. I don't think it's right what I'm saying, but you can try different things. :) Good luck... 


--

You received this message because you are subscribed to the Google Groups "PPP-public" group.
To post to this group, send email to ppp-p...@googlegroups.com.
To unsubscribe from this group, send email to ppp-public+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/ppp-public?hl=en.





--
Adrian G. Mowrey

Shawn

unread,
Dec 30, 2009, 6:35:15 PM12/30/09
to PPP-public
So, well, I ended up doing this:

//Drill #7
#include <iostream>
#include <string>

using namespace std;

double ConvertToCM(double, string); //Function prototype to convert
all measurements to centimeters

int main()
{
double smallest = 0, largest = 0;
double entry;

string unit;

cout << "Please enter a measurement and unit [eg. 12 in]: ";
cin>>entry>>unit;
smallest = largest = ConvertToCM(entry, unit);

cout << "Please enter another measurement and unit: ";

while(cin>>entry>>unit)
{
double temp = ConvertToCM(entry, unit);
if (temp < smallest)
{
smallest = temp;
cout << entry << " " << unit << " smallest so far.\n";
}
else if (temp > largest)
{
largest = temp;
cout << entry << " " << unit << " largest so far.\n";
}
else
cout << entry << " " << unit << " is neither the smallest nor the


largest so far.\n";
cout << "Please enter another number: ";
}

return 0;
}

double ConvertToCM(double measurement, const string unit)
{
double temp;

if (unit == "cm")
return measurement;
else if (unit == "in")
{
temp = measurement * 2.54; //2.54cm = 1 in.
return temp;
}
else if (unit == "m")
{
temp = measurement / 100; //100cm = 1m
return temp;
}
else if (unit == "ft")
{
temp = (measurement * 12) * 2.54;
return temp;
}
else
return 0.0;
}

Any opinions? Seems to work I think....

Matt

unread,
Jan 1, 2010, 3:31:48 PM1/1/10
to PPP-public
Looks like a good start Shawn, although you're obviously yet to finish
it.
This is the code I've written for this Drill. I based it roughly on
what Shawn already had written.
Any feedback would be much appreciated. I think it works as intended.

/* Chapter 4 - Drill
Read in values with units, convert them
all to metres and output some basic statistics */

#include "std_lib_facilities.h"

double convert_to_m(double value, string unit); // Converts the input
value to metres to standardise things.

int main(){
double x = 0;
string unit = 0;
double sum = 0;
double smallest = 0;
double largest = 0;
vector<double> values;

cout << "Enter a value followed by a unit (cm/m/in/ft): ";
cin >> x >> unit;

if(convert_to_m(x, unit) != -1) // The function returns -1 if the
unit is bad. If it's bad, we don't want to put the value into the
vector
{
values.push_back(x);

smallest = x;
largest = x;

sum = x;
}

while(cin >> x >> unit){
if(!cin) error("Could not read in the value.");

x = convert_to_m(x, unit);

if(x!=-1){ //once again, we only work with the input if the unit
was valid. if not, this is skipped.
sum += x;
values.push_back(x);

if(largest < x){
largest = x;
cout << "That's " << x << " metres and is the largest value so far.
\n";
}

if(smallest > x){
smallest = x;
cout << "That's " << x << " metres and is the smallest value so far.
\n";
}

if(x < largest && x > smallest)
cout << "That's " << x << " metres and neither largest nor smallest
value.\n";

}

}

cout << "Largest value: " << largest << "m\n"
<< "Smallest value: " << smallest << "m\n"
<< "Number of values entered: " << values.size() << '\n'
<< "Sum of values: " << sum << "m\n"
<< "The values in metres were: \n";

sort(values.begin(), values.end());

for(unsigned int i=0; i < values.size(); ++i)
cout << values[i] << '\n';

keep_window_open();
return 0;
}

double convert_to_m(double value, const string unit){ //can't
switch on a string
if(unit=="m")
return value;
if(unit=="cm")
return value/100;
if(unit=="in")
return value*0.0254;
if(unit=="ft")
return value*0.3048;
else {
cout << "The unit " << unit << " is not recognised.\n";
return -1;
}
}

Art Werschulz

unread,
Jan 3, 2010, 9:31:10 AM1/3/10
to ppp-p...@googlegroups.com
Hi.

On Jan 1, 2010, at 3:31 PM, Matt wrote:

> double convert_to_m(double value, string unit); // Converts the input
> value to metres to standardise things.

How about doing this instead?

// precondition: length is a measurement given in the indicated unit
// return value:
// if unit is among the recognized units, returns length converted
to metres
// if unit is not recognized, returns -1
double convert_to_metres(const double length, const string unit);

Note the following here:
(*) A function's documentation should stand out a bit more. I like to
put it just before the function. This makes for a nice lead-in to
using the doxygen documentation system (q.v.).
(*) "length" is more descriptive than "value".
(*) Although abbreviating "metres" [sic:-] by "m" is pretty well-
known, "convert_to_metres" is a bit more explicit.
(*) Preconditions and (postconditions or return value) is a nice way
to document a function.

> int main(){
> double x = 0;

Maybe use a better name. input_length is descriptive, but perhaps a
bit long.

> string unit = 0;
Do
string unit = "";
instead. 0 isn't a string.

> double sum = 0;
> double smallest = 0;
> double largest = 0;
> vector<double> values;
>
> cout << "Enter a value followed by a unit (cm/m/in/ft): ";

Maybe "Enter a length ..." instead.

> cin >> x >> unit;
>
> if(convert_to_m(x, unit) != -1) // The function returns -1 if the
> unit is bad. If it's bad, we don't want to put the value into the
> vector

This comment is too long to put where it is; it will cause a line-
wrap, which will be hard to read.
BTW, you already said that it returns -1 if the unit is bad; you don't
need to do this again.
How about:
if (convert_to_metres(input_length) < 0) // ignore bad units

> {
> values.push_back(x);
>
> smallest = x;
> largest = x;
>
> sum = x;
> }
>
> while(cin >> x >> unit){
> if(!cin) error("Could not read in the value.");

If the while loop guard succeeds, cin should be okay. I think you can
ditch this stmt.

> x = convert_to_m(x, unit);
>
> if(x!=-1){ //once again, we only work with the input if the unit
> was valid. if not, this is skipped.

I'd ditch the comment.

> sum += x;
> values.push_back(x);
>
> if(largest < x){
> largest = x;
> cout << "That's " << x << " metres and is the largest value so far.
> \n";

I assume that this is a debugging statement. You should delete it for
the final version, or (if you want to play it safe) comment it out.
Ditto for the analogous statements that appear later.

> }
>
> if(smallest > x){
> smallest = x;
> cout << "That's " << x << " metres and is the smallest value so
> far.
> \n";
> }
>
> if(x < largest && x > smallest)
> cout << "That's " << x << " metres and neither largest nor smallest
> value.\n";
>
> }
>
> }
>
> cout << "Largest value: " << largest << "m\n"
> << "Smallest value: " << smallest << "m\n"
> << "Number of values entered: " << values.size() << '\n'
> << "Sum of values: " << sum << "m\n"
> << "The values in metres were: \n";

Maybe say "The lengths in metres (in ascending order) were: \n".

> sort(values.begin(), values.end());
>
> for(unsigned int i=0; i < values.size(); ++i)
> cout << values[i] << '\n';
>
> keep_window_open();
> return 0;
> }
>
>
>
> double convert_to_m(double value, const string unit){ //can't
> switch on a string

The initial comment on a function should describe what it does, rather
than explain how you did it. So, I'd delete this comment. Mover,
either both parameters should be const, or neither. I wouldn't put a
comment on both the declaration and the definition of the function,
because this violates the "don't do anything twice" principle. The
reason you shouldn't do anything more than once is twofold:
(1) It violates the laziness principle. (Larry Wall, the inventor of
Perl, said that laziness, impatience, and hubris are the three
attributes of a great programmer.)
(2) If you do something more than once, you run the risk of the
multiple versions getting out of synch with each other.

So I'd use something like
double convert_to_metres(const double value, const string unit)
{


> if(unit=="m")
> return value;

Maybe write these as
if (unit == "m") return length;
and so forth.


> if(unit=="cm")
> return value/100;
> if(unit=="in")
> return value*0.0254;
> if(unit=="ft")
> return value*0.3048;
> else {

The "else" is unnecessary, because the only way that flow of control
can reach this point is by unit being neither of "cm", "in", or
"ft". Alternatively, you could do
if (unit == "cm") return 0.01*value;
else if (unit == "cm") return 0.0254*value;
else if (unit == "ft") return 0.30848*value;
else {
I also changed the division to a multiplication, for the sake of
uniformity; moreover, I let the constant be the multiplicand, rather
than the multiplier, since expressions of the form const*variable are
more common than those of the form variable*const (e.g., in algebra,
one usually writes "4a" rather than "a4").

> cout << "The unit " << unit << " is not recognised.\n";
> return -1;
> }
> }

Art Werschulz (8-{)} "Metaphors be with you." -- bumper sticker
GCS/M (GAT): d? -p+ c++ l u+(-) e--- m* s n+ h f g+ w+ t++ r- y?
Internet: agw STRUDEL comcast.net

Matt

unread,
Jan 5, 2010, 12:57:30 PM1/5/10
to PPP-public
Thanks Art,

That was very helpful.

Regards, Matt

PS. I caught a few mistakes in your feedback but I know what you
meant :)

Reply all
Reply to author
Forward
0 new messages