Wednesday 23 December 2020

Chapter 19 // Drill 14 - Principles & Practice Using C++

In these exercises I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 19 // Drill 14

Bonus: Define input and output operators (>> and  <<) for vector<T>s. For both input and output use a { val, val, val } format. That will allow read_val() to also handle the S<vector<int>> variable.


This drill. I was like "sure no probs". Had it working perfectly for ints and then I remembered that this function can take in vectors of any type. Throw strings, floats, chars etc., at it and it breaks spectacularly. I then had to reset my brain to get into the mindset of generic programming...You need to think of everything and anything that could happen.



Apart from not being able to handle vectors of custom types (what a nightmare), it also doesn't handle strings with spaces in them. But I'm pretty happy with this. He chose this input/output specifically because it's really annoying. Bjarne is the true sneaky fox. If you needed very specific string output though I don't think you would use generic types.

Chapter 19 // Drill 14 - Principles & Practice Using C++

For this it checks if there are any undesirable characters and if not, it then reads the entire entry into a string. It removes commas from the string then converts it to a stringstream to be read into the templated type. This way, we don't have to bother with string to random type conversions; stringstream will take care of it for us. It also has the advantage of reading the entire variable in. So { 1.77, 5 }  will be read as:
- cin >> string, ignore { and ' ' 
- cin >> string (reads 1.77, )
- removes the comma
- stringstream >> type ( 1.77 is converted to type )
- push value into vector
- cin >> string, ignore space
- cin >> string ( reads 5 )
- no comma to remove
- stringstream >> type ( 5 is converted to type )
- push value into vector
- cin >> string, ignore space
- cin >> string, } read, break out of loop and return

Tuesday 22 December 2020

Chapter 19 // Drill 1, 2, 3, 4, 5, 6, 7, 8 ,9, 10, 11, 12, 13 - Principles & Practice Using C++

In these exercises I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.


Chapter 19 // Drill 1

Define template<typename T> struct S { T val; };.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2019/Drills/Drill%201

.

Chapter 19 // Drill 2

Add a constructor, so that you can initialise with a T.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2019/Drills/Drill%202

.

Chapter 19 // Drill 3

Define variables of types S<int>, S<char>, S<double>, S<string>, and S<vector<int>>; initialise them with values of your choice.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2019/Drills/Drill%203

.

Chapter 19 // Drill 4

Read those values and print them.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2019/Drills/Drill%204

 I assume he meant read them in using cin?

Chapter 19 // Drill 5

Add a function template get() that returns a reference to val.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2019/Drills/Drill%205

.

Chapter 19 // Drill 6

Put the definition of get() outside the class.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2019/Drills/Drill%206

.

Chapter 19 // Drill 7

Make val private. 

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2019/Drills/Drill%207

.

Chapter 19 // Drill 8

Do 4 again using get().

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2019/Drills/Drill%207

I guess he didn't mean to use cin earlier...literally just print them? Why use read? See code for drill 7 as this does the same thing.

Chapter 19 // Drill 9

Add a set() function template so that you can change val.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2019/Drills/Drill%209

.

Chapter 19 // Drill 10

Replace set() with an S<T>::operator=(const T&). Hint: Much simpler than Section 19.2.5.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2019/Drills/Drill%2010

.

Chapter 19 // Drill 11

Provide const and non-const versions of get().


.

Chapter 19 // Drill 12

Define a function template<typename T> read_val(T& v) that reads from cin into v.


Ok, so he definitely didn't mean to read in values in drill 4. I provided the operator overload version in 4 but I implemented the function here as well.

Chapter 19 // Drill 13

Use read_val() to read into each of the variables from 3 except the S<vector<int>> variable.

Github: .

See drill 12 as I did that there...I also already read into the vector...

Sunday 20 December 2020

Chapter 18 // Exercise 12 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and a modified version of the std_lib_facilities header found here.

I thought about not typing this novel out but for the sake of clarity I did.

Chapter 18 // Exercise 11

Implement a version of the game "Hunt the Wumpus". "Hunt the Wumpus" (or just "Wump") is a simple (non-graphical) computer game originally invented by Gregory Yob. 

The basic premise is that a rather smelly monster lives in a dark cave consisting of connected rooms. Your job is to slay the wumpus using a bow and arrows. In addition to the wumpus, the cave has two hazards; bottomless pits and giant bats. If you enter a room with a bottomless pit; it's the end of the game for you.  If you enter a room with a bat, the bat picks you up and drops you into another room. If you enter a room with the wumpus or he enters yours, he eats you. 

When you enter a room you will be told if a hazard is nearby:
"I smell the wumpus" : It's in an adjoining room.
"I feel a breeze" : One of the adjoining rooms is a bottomless pit.
"I hear a bat" : A giant bat is in an adjoining room.

For your convenience, rooms are numbered. Every room is connected by tunnels to three other rooms. When entering a room, you are told something like "You are in room 12; there are tunnels to rooms 1, 13, and 4; move or shoot?" Possible answers are m13 ("Move to room 13") and s13-4-3 ("Shoot an arrow through rooms 13, 4, and 3"). The range of an arrow is three rooms. At the start of the game, you have five arrows. The snag about shooting is that it wakes up the wumpus and he moves to a room adjoining the one he was in - that could be your room.

Probably the trickiest part of the exercise is to make the cave by selecting which rooms are connected with which other rooms,. You'll probably want to use a random number generator (e.g., randint() from std_lib_facilities.h) to make different runs of the program use different caves and to move around the bats and the wumpus. Hint: Be sure to have a way to produce a debug output of the state of the cave.

Github: https://github.com/l-paz91/principles-practice/tree/master/Chapter%2018/Exercise%2012

So I didn't do this exactly; I changed a few things and added some others. This version of Hunt The Wumpus features a procedurally generated cave that generates rooms with 1-3 tunnels and random bats/pits. It then sticks the wumpus somewhere once generated. I like this setup as it creates varied caves and hazards:
Chapter 18 // Exercise 12 - Principles & Practice Using C++

Chapter 18 // Exercise 12 - Principles & Practice Using C++

As you can see though this generation style is kind of cruel if the only route generated around the map contains pits. So instead of the game ending I added a new feature of "planks". The player will get 3 planks and can choose to put a plank over a pit to cross it. When players successfully slay a bat, it has a 25% chance of dropping an arrow or a plank.

I had a look at the original Wumpus game and the main puzzle is creating the dodecahedron like cave structure as all rooms must lead to 3 more rooms. I could change the code to only draw tunnels, however I like the fact that you may have to double back and really pay attention to where you're going as not everything is connected.

One of the reasons this took me so long was because I approached it all wrong. I literally tried to implement everything in one go and because I had no source control that meant backtracking as I went over my code. I tried installing git for use with VS but I just couldn't get it to work the way I wanted it to. At work we use Perforce and it's free if you have a team of 5 or less so I downloaded P4V and Helix Core. I've never been so happy to lock files, submit and check things out in separate changelists. Programming was fun before, but now it feels extra fun. After that I was able to iterate much faster, as well as revert back to older versions if needed. Source control; it just works.

I then sat down and properly planned out what I had to do, created a checklist and after that my motivation came back and I really started to enjoy the exercise. Especially because I was now seeing progress with every submit. 

Here's how it looks without the debug map:

Chapter 18 // Exercise 12 - Principles & Practice Using C++

And with the map:

Chapter 18 // Exercise 12 - Principles & Practice Using C++

In the video, you can see the Wumpus moves to a random adjoining room if you fire an arrow. You also have a 1/10 chance of receiving an arrow or a plank when entering a room. This run was particularly lucky.

The code is not great. I try to aim to finish a chapter a month so I'm seriously behind. There is a lot of repetition but it's done. I did it. I finally finished a full game...for once.

There are a few things I'd like to add; like a proper game over screen and sounds but it will have to wait until I've finished the book.

Monday 16 November 2020

Chapter 18 // Exercise 11 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 18 // Exercise 11

Look up (e.g., on the web) skip list and implement that kind of list. This is not an easy exercise.

Github: https://github.com/l-paz91/principles-practice/tree/master/Chapter%2018/Exercise%2011

I sighed...I sighed when I googled "skip list". Why Bjarne? This exercise took me a good 2 weeks as I was determined to solve it using only pointers and arrays. You can use a vector to make it a bit simpler but I noticed that the vector implementation I did bumped the memory usage of the program way up; I was a little shocked at the overhead vector brings.

To solve this I used a paper written by William Pugh (the inventor of Skip lists) found here:

https://www.epaperpress.com/sortsearch/download/skiplist.pdf

It contains pseudo code for each function but it's written in Pascal. I had fun trying to decode that....not. Pascal for the most part is relatively similar to C++; the main issue was working out when I had to de-reference or new something up. At one point I was convinced his code didn't work but of course it was just me that wasn't working.

One of the most annoying parts of this task though was trying to debug it. As all my arrays had to be dynamically allocated at runtime, that meant I could only access them via pointers. Pointers only point at the first value of the array so the watch window isn't that helpful. That is unless you know the tricks of the watch window!


A skip list is pretty much made up of Nodes, a node contains a value and an array of pointers to other nodes ahead of it. mHead is the start of the Skip list and we can see here that it's array mNext is only showing us mNext[0]. How do you find out what mNext[1] is at this point?

Well, just right click on the value in Local values, add a watch to it (the right click menu didn't show up in the recording), then add the subscript operators on the end and access whichever part of the array you want!


That's great for specific parts of the array. But what if you want to glance quickly at the entire array? Well if the array has been dynamically allocated, in the watch window, click on a new line and type in:
nameOfPointer, numberOfElements
hit enter and Visual Studio will give you a normal looking array list!
Chapter 18 // Exercise 11 - Principles & Practice Using C++
(All those values are supposed to be null by the way).

Now, this only works with ints (I'm not doing templated types just yet although I can see Bjarne making that an exercise in later chapters). And I'm sure there is an error somewhere but for the most part it "works on my machine" lol. I've already spent a bit too much time on this one exercise.

Tuesday 10 November 2020

Chapter 18 // Exercise 10 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 18 // Exercise 10

Look at the "array solution" to the palindrome problem in section 18.7.2. Fix it to deal with long strings by (a) reporting if an input string was too long and (b) allowing an arbitrarily long string. Comment on the complexity of the two versions.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2018/Exercise%2010

In this one, he didn't say we couldn't use the std library, so I used cin.getline() instead of just the normal cin >>. This allows whitespace to be read as getline() only skips new lines (unless you give it a different delimiting character). Getline() will then continue reading up until the max and append a terminating 0, regardless of whether there were any characters to read.

The next problem was checking if the reading stopped because the buffer ran out of characters or there were too many characters. We can use cin.fail() to check if the stream failed to read. The failbit will be set if it reaches the end of the buffer and still hasn't encountered the delimiting character. A message can then be printed and cin needs to be reset for the next iteration.

I'm not sure if we were supposed to do it a different way as this wasn't entirely complex so I can't comment on the complexity of the two versions. 


Monday 9 November 2020

Chapter 18 // Exercise 9 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 18 // Exercise 9

Consider the memory layout in section 17.4. Write a program that tells the order in which static storage, the stack, and the free store are laid out in memory. In which direction does the stack grow: upward toward higher addresses or downward toward lower addresses? In an array on the free store, are elements with higher indices allocated at higher or lower addresses?

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2018/Exercise%209

So going off Bjarne's description of static, stack and heap I managed to print some global variables and a bunch of locals/new'd values but I'm unsure what to do with the stack? His description says "...It sets aside some memory to be used when you call functions, and they need space for their arguments and local variables". You can print the address of where the function is but I don't think you can print the size of the function? I had a look around and that generally is something that can't be done.

I also couldn't compare the addresses for different functions unless they're identical but the ones included in the program were in places near each other but didn't trend one specific way.

const char*'s and newed up char arrays always grew downwards but newed up double arrays grew upwards.

I'm not convinced I've done this exercise correctly.


Sunday 8 November 2020

Chapter 18 // Exercise 8 - Principles & Practice Using C++

 In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 18 // Exercise 8

Rewrite all the functions in section 18.7 to use the approach of making a backward copy of the string and then comparing; for example, take "home", generate "emoh", and compare those two strings to see that they are different, so home isn't a palindrome.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2018/Exercise%208

.

Saturday 7 November 2020

Chapter 18 // Exercise 7 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 18 // Exercise 7

Write versions of the cat_dot()s from the previous exercises to take C-style strings as arguments and return a free-store-allocated C-style string as the result. Do not use standard library functions or types in the implementation. Test these functions with several strings. Be sure to free (using delete) all the memory you allocated from the free store (using new). Compare the effort involved in this exercise with the effort involved for exercises 5 and 6.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2018/Exercise%207

Creating this cat_dot was fairly straightforward if a little cumbersome. 

Friday 6 November 2020

Chapter 18 // Exercise 5, 6 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 18 // Exercise 5, 6

5. Write a function, string cat_dot(const string& s1, const string& s2), that concatenates two strings with a dot in between. For example, cat_dot("Niels", "Bohr") will return a string containing Neils.Bohr.

6. Modify cat_dot() from the previous exercise to take a string to be used as the seperator (rather than the dot) as its third argument.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2018/Exercise%205%2C%206

He did these two chapter 4 style exercises to make the next one tedious as hell. I don't want to implement this with pointers and arrays and no standard library lol.

Thursday 5 November 2020

Chapter 18 // Exercise 4 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 18 // Exercise 4

Consider what happens if you give strdup(), findx(), and strcmp() an argument that is not a C-style string. Try it! First figure out how to get a char* that doesn't point to a zero-terminated array of characters and then use it (never do this in real - non-experimental - code; it can create havoc). 

Try it with free-store allocated and stack-allocated "fake C-style strings." If the results looks reasonable, turn off debug mode. Redesign and re-implement those three functions so that they take another argument giving the maximum number of elements allowed in argument strings. Then test that with correct C-style strings and "bad" strings.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2018/Exercise%204

My 'fake' c-style string of 'windows' reported a length of 20 and as such printed garbage after printing windows. It also didn't find 'd' in windows; it returned 'ws'. FindX returned a c-style string so strcmp turned out to work but I think that was just a fluke. That was all just in debug mode. When I switched to release it all worked properly. Visual Studio; built by wizards.

Interestingly when I examined the disassembly of the release build, the initial fake string (which was reporting a size of 8) was still being given 20 spaces:

Chapter 18 // Exercise 4 - Principles & Practice Using C++

646E6977h is "dniw" or "wind"...I'm not sure where the "ows" has gone but it's being moved into the esp register with an offset of 20. Even stranger is that after the initialisation, VS reports that Windows has 7 elements but the last 3 are garbage.

It then clears the eax register to 0 and continues assigning the rest of characters of the fake string and at esp+24 adds 'w' and 'o'. Then at esp+26 adds 's'.

The disassembly from the debug build is much more straightforward but uses more cycles:

Chapter 18 // Exercise 4 - Principles & Practice Using C++

From what I can gather here, it's storing 'w' into chars and then the rest at an offset in the ebp register. 

One day, I hope I'm as smart as the people who build compilers because this is fascinating. But anyway, the exercise still needs completing.

Instead of relying on my custom function arrayLength() to supply the length, I added an argument to strcmp, strdup and findx to take in the length of the array.


Wednesday 4 November 2020

Chapter 18 // Exercise 3 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 18 // Exercise 3

Write a function, int strcmp(const char* s1, const char* s2), that compares C-style strings. Let it return a negative number if s1 is lexicographically before s2, zero if s1 equals s2, and a positive number if s1 is lexicographically after s2. Do not use any standard library functions. Do not use subscripting; use the dereference operator * instead.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2018/Exercise%203

I thought I had this in the bag by just comparing the C-style strings with < and > like you can with strings but I temporarily forgot that this only compares the first character instead. This is a problem if you have words like 'chili' and 'chilly'. So I calculated the shortest length (don't want to be accessing random memory if one of the variables is shorter than the other) and checked to see if each character was either less than the other character or equal to it. If one of them was true, continue to check, if both are false than the entire string is alphabetically after the other. I also used a bool to keep track if the first character was before as the next one may be after and that would return 1 for instances like "bra" and "zebra" as b is before z but r is after e.


Tuesday 3 November 2020

Chapter 18 // Exercise 2 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 18 // Exercise 2

Write a function, char* findx(const char* s, const char* x), that finds the first occurrence of the C-style string x in s. Do not use any standard library functions. Do not use subscripting; use the dereference operator * instead.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2017/Exercise%205

I actually already did this in Chapter 17 Exercise 5, so I'm just going to link that here.

Monday 2 November 2020

Chapter 18 // Exercise 1 - Principles & Practice Using C++

 In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 18 // Exercise 1

Write a function, char* strdup(const char*), that copies a C-style string into memory it allocates on the free store. Do not use any standard library functions. Do not use subscripting; use the dereference operator * instead.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2018/Exercise%201

A bit tedious and I used const_cast. This was exactly the same as exercise 4 in Chapter 17 only then we could use the subscript operator.

Sunday 1 November 2020

Chapter 18 // Vector Drills - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 18 // Vector Drills

1 - Define a global vector<int> gv; initialise it with ten ints, 1, 2, 4, 8, 16, etc.
2 - Define a function f() taking a vector<int> argument.
3 - In f():
    a. Define a local vector<int> lv with the same number of elements as the argument vector.
    b. Copy the values from gv into lv.
    c. Print out the elements of lv.
    d. Define a local vector<int> lv2; initialise it to be a copy of the argument vector.
    e. Print out the elements of lv2.
4. In main():
    a. Call f() with gv as its argument.
    b. Define a vector<int> vv, and initialise it with the first ten factorial values (1, 2*1, 3*2*1, 4*3*2*1,             etc.).
    c. Call f() with vv as its argument.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2018/VectorDrills

Oh I love vector. You can just get on with your life.

Saturday 31 October 2020

Chapter 18 // Array Drills - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 18 // Array Drills

1 - Define a global int array ga of ten ints initialised to 1, 2, 4, 8, 16, etc.
2 - Define a function f() taking an int array argument and an int argument indicating the number of elements in the array.
3 - In f():
    a. Define a local int array la of ten ints.
    b. Copy the values from ga into la.
    c.  Print out the elements of la.
    d. Define a pointer p to int  and initialise it with an array allocated on the free store with the same                 number of elements as the argument array.
    e. Copy the values from the argument array into the free-store array.
    f. Print out the elements of the free-store array.
    g. Deallocate the free-store array.
4. In main():
    a. Call f() with ga  as its argument.
    b. Define an array aa with ten elements, and initialise it with the first ten factorial values (1, 2*1,                     3*2*1, 4*3*2*1, etc).
    c. Call f() with aa as its argument;

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2018/ArrayDrills

I will admit the memcpy got me first time as I read it too quickly and was like "ah yes, destination, source, number in array".....it's the number of bytes in the array, so arraySize*sizeof(int).

Wednesday 28 October 2020

Chapter 17 // Exercise 14 - Principles & Practice Using C++

  In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 17 // Exercise 14

Could the "list of gods" example from Section 17.10.1 have been written using a singly-linked list; that is,could we have left the prev member out of Link? Why might we want to do that? For what kind of examples would it make sense to use a singly-linked list? Re-implement that example using only a singly-linked list.

Github: https://github.com/l-paz91/principles-practice/tree/master/Chapter%2017/Exercise%2014

Eurgh why. Without prev it would be very hard to find the start of the list. The pointer can be changed to point at something else when an element is inserted/removed. We would need to store a pointer to the first value.

Insertion would be trickier as well as you would have to start from a, advance n times to the insertion point so you know the previous then assign the new successors. Just use a vector.

I tried googling best use cases for a Singly linked list and I couldn't really find any.

And with that, another chapter bites the dust. This was a good chapter though. I have so many notes on pointers and memory allocation. I'm also halfway through the book! Just 590 pages out of 1216.

Tuesday 27 October 2020

Chapter 17 // Exercise 13 - Principles & Practice Using C++

 In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 17 // Exercise 13

Modify the Link class from section 17.10.1 to hold a value of a struct God. struct God should have members of type string: name, mythology, vehicle, and weapon. For example, God{"Zeus", "Greek", "", "lightning"} and God{"Odin", "Norse", "Eight-legged flying horse called Sleipner", "Spear and Gungnir"}. Write a print_all() function that lists gods with their attributes one per line. Add a member function add_ordered() that places its new element in its correct lexicographical position. Using the Links with the values of type God, make a list of gods from three mythologies; then move the elements (gods) from that list to three lexicographically ordered lists - one for each mythology.

Github: https://github.com/l-paz91/principles-practice/tree/master/Chapter%2017/Exercise%2013

What in the ever-living christ? I really hated this exercise when I started it. In fact, I procrastinated so much in doing this exercise that I made a slenderman game in Unreal Engine and did the infamous Blender Donut tutorial:

Chapter 17 // Exercise 13  - Principles & Practice Using C++

Anyway, I finally did it and by the end of it, I have to admit, I understood linked lists WAY better than I did before. Don't skip the exercises everyone; they actually work.

Sure, this is not the greatest code ever written but I did it!

Monday 5 October 2020

Chapter 17 // Exercise 11, 12 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 17 // Exercise 11, 12

11. Complete the "list of gods" example from section 17.10.1 and run it.
12. Why did we define two versions of find().

Github: https://github.com/l-paz91/principles-practice/tree/master/Chapter%2017/Exercise%2011

Wow, linked lists are confusing. I never want to read prev->succ = prev if !prev then succ = prev->succ etc....

For exercise 12 I had to go read the small section in Chapter 18. Basically, it's to stop someone from change what Link* is pointing at. In the functions I try to always assign the pointer to a new temp pointer to avoid messing with the original. I feel like this is the same case here.

Friday 2 October 2020

Chapter 17 // Exercise 10 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 17 // Exercise 10

Look at your solution of exercise 7. Is there any way that input could get the array to overflow; that is, is there any way you could enter more characters than you allocated space for (a serious error)? Does anything reasonable happen if you try to enter more characters than you allocated?

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2017/Exercise%207%2C%208

Fortunately, the version of cin.get() that I used only gets up to the specified amount of characters. So I pass it the char pointer then specify 256 (as that is the size of the array) and give it a deliminating character. So it will either stop reading at '!'  or once it reads in 256 characters.

Thursday 1 October 2020

Chapter 17 // Exercise 9 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 17 // Exercise 9

Which way does the stack grow: up (toward higher addresses) or down ( towards lower addresses)? Which way does the free store initially grow (that is, before you use delete)? Write a program to determine the answers.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2017/Exercise%209

If you're newing via a for loop it seems to pick addresses near to each other? Interestingly, it appears to grow downwards for numbers and upwards for chars. I don't think it's set in stone though as I've seen the free store ints going upwards.

Wednesday 30 September 2020

Chapter 17 // Exercise 7, 8 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 17 // Exercise 7, 8

7. Write a program that reads characters from cin into an array that you allocate on the free store. Read individual characters until an exclamation mark (!) is entered. Do not use a std::string. Do not worry about memory exhaustion.
8. Do exercise 7 again, but this time read into a std::string rather than to memory you put on the free store (string knows how to use the free store for you).

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2017/Exercise%207,%208

There's no need to re-invent the wheel here as cin will do all the hardwork for you, all you need to do is supply it with a maximum stream buffer size. Back in chapter 7, we extensively used cin.get() during the creation of the calculator. cin.get() has quite a few different overloads which you can find here:

I used the c-string version istream& get(char* s,  streamsize n, char delim). This allows you to give cin a custom delimiting character (in our case !) and will read characters in and store them at the given address up to streamsize. Simples.

Technically it's cheating but he did say use cin.

As for 8, getline() also has a version that allows you to specify a delimiting character:

Tuesday 29 September 2020

Chapter 17 // Exercise 6 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 17 // Exercise 6

This chapter does not say what happens when you run out of memory using new. That's called 'memory exhaustion'. Find out what happens. You have two obvious alternatives: look for documentation, or write a program with an infinite loop that allocates but never deallocates. Try both. Approximately how much memory did you manage to allocate before failing.

Fortunately, Windows happens to be a good operating system and good OS's stop your program from eating up all the ram. It got to 2GB (which is my pagefile allowance) before it crashed on a bad memory allocation.

Chapter 17 // Exercise 5 - Principles & Practice Using C++

 In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 17 // Exercise 5

Write a function, char* findx(const char* s, const char* x), that finds the first occurrence of the C-style string x in s.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2017/Exercise%205

I'm not entirely sure what he meant by this so I interpreted it as "finds the first occurrence of the C++-style string in the C-Style string".

Also, he did not specify not to use the standard library on this one. There is already the function strstr() to do this that takes in two const char*. 


The actual definition of this function though is deep in the bowels of VS runtime string headers but it basically takes in two pointers to the start of the char arrays and then returns a pointer to the start of the occurrence. This means that if you print the pointer, it will print everything starting from that occurrence.

I mimicked this behaviour and also cast that const away (just like the standard library does).


Saturday 26 September 2020

Chapter 17 // Exercise 4 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 17 // Exercise 4

Write a function, char* strdup(const char* c), that copies a C-style string into memory it allocates on the free store. Do not use any standard library functions.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2017/Exercise%204

With const pointers I find it really stupid that you can't change the object that the pointer is pointing at, but you can change what the pointer is pointing at. In this exercise, c can be changed to point at some random garbage address but god forbid you want to assign the pointer to a non-const pointer. Unreal has a problem with this because pretty much everything gets passed round as const pointers but this allows for people to change what it's pointing at and no one will be none the wiser because it says const in the argument parameters. A lot of programmers assume (and rightly so) that this means their arguments won't be modified in the function body.

We have a senior engineer who prefers us all to use const references as you cannot change the object OR change what it's pointing at and less mistakes can be made.

Also, strdup() is a deprecated std library function so I renamed it so it would compile.

Friday 25 September 2020

Chapter 17 // Exercise 1, 2, 3 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 17 // Exercise 1, 2, 3

1. What is the output format of pointer values on your implementation? Hint: don't read the documentation.
2. How many bytes are there in an int? In a double? In a bool? Do not use of sizeof except to verify your answer.
3. Write a function, void to_lower(char* s), that replaces all uppercase characters in the C-style string s with their lowercase equivalents. For example, Hello, World! becomes hello, world!. Do not use any standard library functions. A C-style string is a zero-terminated array of characters. So if you find a char with the value 0 you are at the end.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2017/Exercise%203

1. Addresses are printed in capitals as "010FFA44", so in hex without the 0x prefix.
2. At least on my pc an int is 32 bits (4 bytes), a double is 64 bits (8 bytes) and a bool is 8 bits (1 byte). I'm not sure if he wanted us to verify this?

3. I used some of my assembly knowledge to do this. ASCII is very clever and well thought out. When it comes to letters, lowercase characters always have their 5th bit set to 1 and uppercase characters have it set to 0; so you can easily switch between upper and lower by just inverting bit 5.

That's what I did here:
Chapter 17 // Exercise 1, 2, 3  - Principles & Practice Using C++

On line 22, we access the contents of s, then OR bit number 5 with 1. As uppercase are 0 in bit 5, when you OR 0 with 1, you get 1, so it flips the upper character to lower.

This does not affect already lower case letters or punctuation (as 1 OR 1 is 1). Some more examples:
Chapter 17 // Exercise 1, 2, 3  - Principles & Practice Using C++
You can also use char ^= (1 << 5) to toggle the bit instead of setting it once.

A warning; s will now be pointing at the end of the array. You can also do while(s[i] != 0; ++i) to avoid this (where i is the length of the array) or assign the pointer to another pointer for the function.

Thursday 24 September 2020

Chapter 17 // Part 2 Drills - Principles & Practice Using C++

 In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 17 // Part 2 - Drills 

1. Allocate an int, intialise it to 7, and assign its address to a variable p1.
2. Print out the value of p1 and of the int it points to.
3. Allocate an array of seven ints ; initialise it to 1, 2, 4, 8, etc.; and assign its address to a variable p2.
4. Print out the value of p2 and of the array it points to.
5. Declare an int* called p3 and initialise it with p2.
6. Assign p1 to p2
7. Assign p3 to p2.
8. Print out the values of p1 and p2 and of what they point to.
9. Deallocate all the memory you allocated from the free store.
10. Allocate an array of ten ints; intialise it to 1, 2, 4, 8, etc.; and assign its address to a variable p1.
11. Allocate an array of ten ints, and assign its address to a variable p2.
12. Copy the values from the array pointed to by p1 into the array pointed to by p2.
13. Repeat 10-12 using a vector rather than an array.

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2017/AllDrillsPart2

.

Tuesday 22 September 2020

Chapter 17 // Part 1 All Drills - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and the std_lib_facilities header provided by Stroustrup.

Chapter 17 // Part 1 - Drills 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

1. Allocate an array of ten ints on the free store using new.
2. Print the values of the ten ints to cout.
3. Deallocate the array (using delete[]).
4. Write a function print_array10(ostream& os, int* a) that prints out the values of a (assumed to have ten elements) to os.
5. Allocate an array of ten ints on the free store; initialise it with the values 100, 101, 102, etc.; and print out its values.
6. Allocate an array of 11 ints on the free store; initialise it with the values 100, 101, 102, etc.; and print out its values.
7. Write a function print_array(osteam& os, int* a, int n) that prints out the values of a (assumed to have n elements) to os.
8. Allocate an array of 20 ints on the free store; initialise it with the values 100, 101, 102, etc.; and print out it's values.
9. Did you remember to delete the arrays? (If not, do it).
10. Do 5, 6, and 8 using a vector instead of an array and a  print_vector() instead of print_array().

Github: https://github.com/l-paz91/principles-practice/blob/master/Chapter%2017/AllDrillsPart1

During this exercise I learnt that vectors will not always store elements in memory next to each other.

Sunday 20 September 2020

Chapter 16 // Exercise 10 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and modified versions of the graphics files used throughout the chapters. You can find those versions through the link below.

Chapter 16 // Exercise 10

Provide a program where you can choose among a set of functions (e.g., sin() and log(), provide parameters for those functions, and then graph them.

Github: https://github.com/l-paz91/principles-practice/tree/master/Chapter%2016/Exercise%2010

It turns out In_box::get_int() will not correctly return negative numbers. This was because of the check to see if a number had been placed in the box. It checks the first character and if it's not a number it returns -99999 so I changed it to allow the first character to be '-'. Other than that, thanks to the Stored Function we made in the last chapter, this was quite straightforward. 

Chapter 16 Exercise 10 Principles & Practice Using C++

And the graphics chapters are now over :( Although I am excited to finally start working on algorithms and memory management. I use these concepts a lot at work but I feel like I haven't picked up the basics properly and I had to start running before I could even walk. I've had a look through the rest of the exercises and there are more that use FLTK so it hasn't completely disappeared. 


Friday 18 September 2020

Chapter 16 // Exercise 9 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and modified versions of the graphics files used throughout the chapters. You can find those versions through the link below.

Chapter 16 // Exercise 9

Modify the calculator from Chapter 7 to get its input from an input box and return its results in an output box.

Github: https://github.com/l-paz91/principles-practice/tree/master/Chapter%2016/Exercise%209

Oh I wish this chapter would stop haunting me. Looking at the code though reminds me of how eager I was to put in error messages. Now I just don't care.

I also wanted to avoid messing with get() and unget() as much as possible so I googled how to put a string into cin and found this very handy section of code:

This uses istringstreams and effectively "fakes" typing in the keyboard. The calculator code thinks we've typed into cin and will happily go about getting and putting back characters in cin.

I did remove a few functions and moved definitions into a cpp file (with declarations in the header) but for the most part it has stayed intact from the code uploaded here:

You can both type statements into the calculator (just don't type '=' press the button) and press the buttons:

Chapter 16 // Exercise 9 - Principles & Practice Using C++




Wednesday 16 September 2020

Chapter 16 // Exercise 8 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and modified versions of the graphics files used throughout the chapters. You can find those versions through the link below.

Chapter 16 // Exercise 8

Provide a currency converter. Read the conversion rates from a file on startup. Enter an amount in an input window and provide a way of selecting currencies to convert to and from (e.g., a pair of menus).

Github: https://github.com/l-paz91/principles-practice/tree/master/Chapter%2016/Exercise%208


I'm not sure how but I did it. It took me a good hour of staring at the documentation and this very helpful post from 2007:
http://www.murga-projects.com/forum/showthread.php?tid=122

My excitement though is not because I created a currency converter but, I enabled the Window class to use a jpg image as a background for the window. 

Chapter 16 Exercise 8 - Principles & Practice Using C++

In all of the previous exercises, you may have noticed that images always draw on top of widgets, no matter what order you draw in. There is a hack however, and that is to create an Fl_Box, give the box an image and then attach the box to your window. Sounds good. The problem though is that we are using Bjarne's helper classes which do not have any functionality to support this so I had to add it.

I basically made a new Widget called FakeBkg that holds an Fl_Image. attach() needs to be overridden as it's pure virtual. In here I assigned a new Fl_Box to the Fl_Widget stored in Widget, gave the widget the image stored in FakeBkg and then assigned the window with my window...I think I might do a separate post on this one.

Anyway, I added a new function to In_box to handle getting floats out of a text box and used a fixed size text file which kind of feels like cheating. I know exactly what line the conversion rates are on and how many characters in so my switch statement is extremely hard coded but efficient. Instead of reading in the text file at the beginning and storing all the different formats (which may or may not get used), it gets the rate from the file when needed.

Monday 14 September 2020

Chapter 16 // Exercise 7 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and modified versions of the graphics files used throughout the chapters. You can find those versions through the link below.

Chapter 16 // Exercise 7

Using the techniques developed in the previous, make an image of an airplane "fly around" in a window. Have a "Start" and a "Stop" button.

Github: https://github.com/l-paz91/principles-practice/tree/master/Chapter%2016/Exercise%207


As I learnt in the last exercise; FLTK does not directly support rotating images (it is something that you need to implement yourself and well... I can't be bothered). So, this is a very "basic" implementation of just moving a png image round the window.

FLTK does support image mirroring however it's when using its Direct Draw functions which we're not using. So, I have two images and the images are switched out when at certain angles for added "realism". Disgustingly hacky but there you go. Stopping and starting the plane is quite simple. I just moved adding the timeout to start and then removing it on stop.

Chapter 16 // Exercise 7 - Principles & Practice Using C++


I used an ellipse for the "track" as it has the useful functions getPointDirection() and getPointOnEllipse(). Ellipse could easily be switched out for a super ellipse though and given random values for the plane to follow random tracks. 

I take all the captures using the windows game bar, it seems to add blips for some reason. The program runs smoothly though.


Sunday 13 September 2020

Chapter 16 // Exercise 6 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and modified versions of the graphics files used throughout the chapters. You can find those versions through the link below.

Chapter 16 // Exercise 6

Make an "analog clock," that is, a clock with hands that move. You get the time of day from the operating system through a library call. A major part of this exercise is to find the functions that give you the time of day and a way of waiting for a short period of time(e.g., a second for a clock tick) and learn to use them based on the documentation you found. Hint: clock(), sleep().

Github: https://github.com/l-paz91/principles-practice/tree/master/Chapter%2016/Exercise%206


The most annoying thing about this exercise was learning that FLTK doesn't support rotating images. There is a way to implement it yourself but it involves getting all the pixel data and shifting it yourself to the new location and I can't be bothered. So I ended up just using some arrows which don't look great but they do the job.

Next I implemented the clock moving. It has three hands; one for hours, minutes and seconds. They use the C struct tm* which handily contains the current date in nice formats. AnimatedClock is its own shape and pretty much handles itself. ClockWindow has a member variable of type AnimatedClock and then ticks every second. In the gif, my PC clock was at 13:38 when I started the recording:



Originally I was trying to use Sleep(), which is a function specific to Windows that pauses the program for a given amout of milliseconds. This did not work how I wanted it to. FLTK has it's own built in timer system called Fl::Wait, we've already used it a few times before. I had a look at the documentation to see if there was a version of wait that takes in a "time value" and there is:
https://www.fltk.org/doc-1.4/classFl.html#af49654e35a0b636aa751dce5ff88a7f5

Here it mentions idle callbacks (i.e our button presses) and elapsed timeouts. I had another look round the documentation for what this meant and  found this:
https://www.fltk.org/doc-1.3/classFl.html#a23e63eb7cec3a27fa360e66c6e2b2e52

The two functions we are interested in are Fl::add_timeout and Fl::repeat_timeout. Using these are somewhat similar to registering tick functions in UE4 (the concept is essentially the same).

Fl::add_timeout requires 3 arguments; a time in seconds, a callback function and a reference to the object. So first, we register the new timeout in the constructor of our window:
(void*)this is very important otherwise on the next tick, fltk will not know what object you are referring to and you will most likely get a runtime error saying you are trying to access a nullptr.

We now create the call back function:
As standard we cast the given address to our window type and call the function we want calling when our timer elapses. The next line calls Fl::repeat_timeout, this is because Fl::add_timout is a oneshot and as such it will only be called once so we tell fltk to repeat the timeout every given time. This is useful because you might want it initially to go off for 1 second but then check every 10. We give it the callback function and use addr to specify our object. addr contains the address of this (our window) which we passed in in the constructor.