Drill from Bjarne's book

Hi all, i am going through Bjarne book and at the moment im doing chapter 4 drills. The program i wrote seems to be working but im wondering, is there anything i could've done in simpler way? Did i do something particularly wrong or right? Did i over complicate things? (at this point in the book we only learned for, if, while, switch and started doing vectors, we didnt even cover true/false so please keep that in mind). Any advice is much appreciated!

In short this is the drill:
-Must consist while loop.
-Read value(double) and unit (string).
-Each time loop, write out value, unit and larges so far/smallest so far.
-Accept only cm,m,in,ft as units (read them in vector).
-Do sum of values converted into meters.
-When loop ends print smallest, largest number of values and sum.
-Keep all entered values(in meters) in vector and write them out on the end, but sort them first.


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
  int main()
{
	//Drill Chapter 4 6.
	double a;
	double min=99999999;
	double max=0;
	vector <string> units = {"cm","m","in","ft"};
	vector <double> munits = {100,1,39.37,3.281};
	vector <double> values_in_meters;
	string u;
	int test=false;
	double unit_in_meters;
	double sum=0; // sum of entered numbers


	while (cin >> a >> u)
	{
		for (int i = 0; i < units.size(); i++)
		{
			if (u == units[i])
			{
				test = true;
				unit_in_meters = a / munits[i];
				sum += unit_in_meters;
				values_in_meters.push_back(unit_in_meters);
			}
		}
		if (test)
		{
			cout << "\n" << a << u << " ";
			if (unit_in_meters > max)
			{
				cout << "The largest so far! ";
				max = unit_in_meters;
			}
			if (unit_in_meters < min)
			{
				cout << "The smallest so far! ";
				min = unit_in_meters;
			}

			cout << "\n";
			test = false;
		}
		else
			cout << "\nWrong unit!";
	}
	cout << "\n\nEntered values in meters: \n";
	sort(values_in_meters);
	for (int i = 0; i < values_in_meters.size(); i++)
		cout << values_in_meters[i] << " m\n";

	cout <<"\n\nTotal number of values: "<<values_in_meters.size()<< ".\nLargest number: " << max << " meters.\nSmallest number: " << min << "meters.\nTotal sum: " << sum<<" meters.\n\n";


Oh! and how do i change min and max to be first entered value
max=a; min=a; ..at the moment ive set the range from 0 to 99999999 but if larger number is entered then min wont give correct value and also if negative value is entered (when it wont be about units) then it will be wrong too. Ive tried doing that by entering first cin>>a before loop but then its not included in any calculation in the loops and ifs.

And last thing, there is part of the drill that i just skipped because i dont have a clue, its to terminate program when '|' is entered. I think if i put it in 'if' statement with break; in while loop and everything else under 'else' then it will just leave while loop but not the program. Is there a way to do it using only the things we learned so far?
On the subject of the code itself:

If it works as the book suggests, you’re probably right where Stroustrup intends.

A few points to consider:

The variable test is defined as an int, but it is used as a bool, so it should be declared as a bool

The name chosen for test should probably change to reflect what it does, it is a test for whether or not the units were found, so a name like “is_units_valid” or “was_unit_found” or whatever you like would be easier to recognize (it’s a habit to develop).

Some may point out that the call to “sort” is “not standard”, but keep in mind that Stroustrup included a common header file, which further includes a number of standard libraries, then proceeds to provide a few “convenience” functions many programmers should consider for themselves. Stroustrup is basically suggesting that “sort(a)” is better than “sort(a.begin(), a.end() )”, and shows how to arrange for that in his header file.

Many posters here may have lots of suggestions, but as you pointed out in your opening, this is an early chapter of an introduction to C++. This very simple style will evolve in the book, so I have no reason to push you further (as many will I’m sure).

“Oh! and how do i change min and max to be first entered value
max=a; min=a;”


You can try a bool, something like “is_max_initialized”, which starts out as false. When you see that bool is false, set it to true and set max=a, min=a as you describe. It will happen only on first use then (it’s a pattern called lazy initialization).

Now, as to termination on “|”.

Notice Stroustrup suggested cin >> a >> u (or implied it), where a is a double. Any non-numeric entry will cause that input to return false, so the while loop terminates as a result. Now, if the “|” is provided for the string, it would take it, so you’d have to test “u” for any such characters you want to use for termination there, and use "break" if you find them.
Last edited on
What drill are you actually working on? And from exactly what book, he has several.

If it is PPP chapter 4 drills then there is no need for a vector until Drill 9, and note Drill 10 suggests sorting the vector. Also if this is drill 6 there is no need for the "units", using "units" starts in drill 7. Really the first 7 or 8 drills are trying to teach how to use basic control structures.

Also note that each one of the drills build off the previous drills so make sure you do each drill in order, making the appropriate changes for each "new" drill.

I really suggest you make sure you keep all the code for previous drills, so you can go back and see where you went wrong and possibly revert to the earlier code to start over.

Hi Niccolo, thank you for your advises.
I implemented this code:

1
2
3
4
5
6
7
8
9
10
11
while (cin >> a >> u)
	{ 
		for (int i = 0; i < units.size(); i++)
		{
			if (have_value_minmax)
			{
				min = a;
				max = a;
				have_value_minmax = false;

			}
.....

so now its checking if min and max received first value, have_value_minmax is set to true;
I one question about that, what kind of effect will that have on program (going through that if statement each time to check)? how much does one if or for actually affects performance? should we be careful about things like that or should we use less as possible just because of simplicity? i hope my question makes some sense.

I also added this:
1
2
3
4
5
6
}
		else
			cout << "\nWrong unit!";
		if (u == "|")
			break;
	}
...end of while loop

I changed variable type to bool. How come its still working being an int type? does that have some other uses?

Thank you for your advice on naming variables, Bjarne does go through this but i guess we dont even take effort on this simple drills, but looking back yes i would end up scratching my head if i just saw variable named test. Will keep that in mind.
Hi jlb,

I am currently on Chapter 4 Drill, page 126, book: Principles and Practice Using C++, using C++11 and C++14
@tinaHR,

Ok, working backwards,

About bool and test

I changed variable type to bool. How come its still working being an int type? does that have some other uses?


It isn't working as an integer, and you never used "test" as an integer. The keywords "false" and "true" are both BOOL types, not integers. There is automatic conversion available in some cases, where "false" is zero, but for bool's any non-zero evaluates to "true".

If you have any confusion about "test" and it's nature as a bool ask, because I'm not sure why you though it "still working being an int type" - because it isn't. In code analysis tools and high warning levels I'd expect some situations where "false" and "true" are used with integers there should be warnings.

Put another way, despite the "colloquial" reading of the various "if()" clauses, what is tested by "if" statements is a bool. For example, if ( a ) where "a" is an integer is NOT testing "a"'s value, it is testing the boolean test of a for zero or not zero. Likewise, if ( a < b ) doesn't really care about a or b - conceptually the compiler does test for "a"'s value compared to "b"'s value, but the RESULT of that comparison is "true" or "false" - becoming a BOOL, not an integer.

About "if" inside a loop

Every "if" statement does impose a performance penalty, but it is very small. In high performance programming we do think about such things, and take care to test before loops. In such work we actively limit the work inside interior loops.

Yet, that's only for interior loops (we often have loops inside loops, so we're hardly ever concerned about the outer loop level).

However, setting that theory aside for a later study, the performance impact of such an "if" inside a loop is in the region of 100 hundred millionth of a second, on modest hardware. Many machines could run that test a billion times per second or more.

Lazy initialization, the pattern used for this "initial" assignment of min/max, has a cost in this way. When performance is less important that convenience, the cost is minimal.

About the test of have_value_minmax

You have that working, and it's ok, but when you say.

if min and max received first value, have_value_minmax is set to true;


you're saying that backwards from what you wrote. Indeed, your written text is the truth, and the code is inverted. You're setting it to false.

In this formation, the name would be more accurate "does_no_have_value_minmax", because when that is true, you have not set minmax, and when it is false you have...you "don't have no value" is how that reads, which sounds odd.

Indeed, it is more natural to initialize "have_value_minmax" to false, which is saying "there is no minmax set yet".

Then, the test itself is inverted:

1
2
3
4
5
6
7
if ( !have_value_minmax ) // the test is inverted now, NOT 'has minmax'
			{
				min = a;
				max = a;
				have_value_minmax = true; // now we do have minmax

			}


This expresses how you've worded this in text, and it just seems more natural to the mind.

Otherwise you have that all correct, because in reality it works either way, to check for "true" and set to "false" (basically the logic of "does this need initialization") or check "false" and set to "true" (saying "did we initialize yet").

For all of us in this study, our early months, maybe a year or two, we just happy to get something working, and we tend to think in terms of just getting code to work.

Later, we begin to think in terms of expression, in terms of writing what we think - as if we think in code. It develops as practices like this are repeated, so the time it takes to transform from "just getting the code working" to the "expression of thought" is related to how much practice one performs.





Last edited on
About bool and test

I meant how come in int test = false; i can assign false or true since the type is int and not bool and am able to use it as bool (i tried to understand what you wrote but am still confused a bit)

I get what you mean about have_value_minmax, i changed it to no_value_minmax, makes more sense.

You are completely right about ''just getting the code working'' i dont even think that much about naming variables carefully and if they'll make sense, i think we are more like ok i named it, lets get it work and forever move on to the next step (why would i ever need to look at my code again kind of way), i think it changes also when you program for the ''real world'' when you need to modify it, go back to it after few months, when you have colleagues working with you etc. at this point to me all that sounds abstract.
Last edited on
Topic archived. No new replies allowed.