Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 66c92b7

Browse files
chavidsponce
authored andcommitted
Review operators exercise and split a preceding classes exercise from it.
1 parent 86a5878 commit 66c92b7

File tree

16 files changed

+516
-226
lines changed

16 files changed

+516
-226
lines changed

‎exercises/ExerciseSchedule_EssentialCourse.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ People should replay them and discover the tools by themselves.
3737
Day 2 - OO Exercises
3838
--------------------
3939

40-
### Polymorphism (directory: [`polymorphism`](polymorphism), [CheatSheet](ExercisesCheatSheet.md#polymorphism-directory-polymorphism))
40+
### My first classes (directory: [`classes`](classes), [CheatSheet](ExercisesCheatSheet.md#classes-directory-classes))
4141

4242
### Operator overloading (directory: [`operators`](operators), [CheatSheet](ExercisesCheatSheet.md#operator-overloading-directory-operators))
4343

44+
### Polymorphism (directory: [`polymorphism`](polymorphism), [CheatSheet](ExercisesCheatSheet.md#polymorphism-directory-polymorphism))
45+
4446
### Virtual inheritance (directory: [`virtual_inheritance`](virtual_inheritance), [CheatSheet](ExercisesCheatSheet.md#virtual-inheritance-directory-virtual_inheritance))
4547

4648

‎exercises/ExercisesCheatSheet.md

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,37 @@ The idea of this exercise is to play with all kinds of possible loops and contro
4545
Object-orientation Exercises
4646
----------------------------
4747

48+
### Classes (directory: [`classes`](classes))
49+
50+
This exercise is about doing a basic class, not using any operator overloading. It also paves the way for object-functions, making a first algo-like class.
51+
52+
You may discuss with the students:
53+
- pros and cons of making the constructor explicit or not,
54+
- pros and cons of having multiply() and equal() either as member functions,
55+
friend free functions or external free functions.
56+
- optionally, thed difference between equality and equivalence.
57+
58+
NOTE: I did not find a justified need to add operator=...
59+
60+
### Operator overloading (directory: [`operators`](operators))
61+
62+
Here we take the class from the previous exercise, and we try to make
63+
anything an operator that makes sense.
64+
65+
Tips and tricks:
66+
- When the argument of CHECK() has a comma not between parentheses, for example
67+
curly braces, add an additional global level of parenthesis, or CHECK() will
68+
think it has several arguments.
69+
70+
You may discuss with the students:
71+
- the chaining of operator<<
72+
- in a set of consistent operators (such as == and !=),
73+
reusing versus performance.
74+
- object-functions.
75+
- for what concerns the related operators, such as * and *=,
76+
the choice to be made consitent reuse or performant
77+
specialization of each operator.
78+
4879
### Polymorphism (directory: [`polymorphism`](polymorphism))
4980

5081
First create a Pentagon and an Hexagon and call computePerimeter. Can be used to break the ice.
@@ -79,22 +110,6 @@ See and solve the compilation issue about missing Drawable constructor. Understa
79110
See the new id being printed twice.
80111

81112

82-
### Operator overloading (directory: [`operators`](operators))
83-
84-
This exercise is about making `main` run successfully by completing the implementation of `Fraction`.
85-
Implement a constructor for `Fraction` and add two integer data members for numerator and denominator.
86-
Comment out everything in `main` except the first two LOCs.
87-
This should compile now and print nothing.
88-
89-
Then uncomment the `std::cout` statements and implement `operator<<` for `Fraction`.
90-
Compile and run.
91-
92-
Proceed this way through the entire exercise.
93-
There are multiple possibilities to implement some operators, e.g. as members, as hidden friends, or as free functions.
94-
Also when and where to normalize a fraction is up to the students.
95-
All solutions are fine, as long as the `main` function runs successfully.
96-
97-
98113
Modern C++ Exercises
99114
--------------------
100115

‎exercises/classes/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
classes classes_sol

‎exercises/classes/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Set up the project.
2+
cmake_minimum_required( VERSION 3.12 )
3+
project( operators LANGUAGES CXX )
4+
5+
# Set up the compilation environment.
6+
include( "${CMAKE_CURRENT_SOURCE_DIR}/../common.cmake" )
7+
8+
# Create the user's executable.
9+
add_executable( classes "classes.cpp" )
10+
11+
# Create the "solution executable".
12+
add_executable( classes_sol EXCLUDE_FROM_ALL "solution/classes_sol.cpp" )
13+
add_dependencies( solution classes_sol )

‎exercises/classes/Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
all: classes
2+
solution: classes_sol
3+
4+
clean:
5+
rm -f *o classes *~ classes_sol
6+
7+
classes : classes.cpp
8+
${CXX} -g -std=c++17 -O0 -Wall -Wextra -L. -o $@ $<
9+
10+
classes_sol : solution/classes_sol.cpp
11+
${CXX} -g -std=c++17 -O0 -Wall -Wextra -L. -o $@ $<

‎exercises/classes/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
## Instructions
3+
4+
STEP 1
5+
- Complete the class Fraction so that a Fraction can be construct from one or two integer.
6+
Check the first two lines of main() are working (comment out the rest)
7+
- Add the function equal().
8+
Check the second section of main() works.
9+
- Add the function multiply().
10+
Check the whole main() works.
11+
12+
STEP 2
13+
- Replace the function printTestResult() by a class TestResultPrinter
14+
with a method process() that take the same arguments as before.
15+
Upgrade CHECK() and main().
16+
- Transform the WIDTH constant into a variable member of TestResultPrinter,
17+
which is initialized in its constructor.
18+
Upgrade main().
19+
20+
OPTIONAL STEP 3
21+
- Move multiply() and compare() as friend functions within the class Fraction.
22+
Check main() works.
23+
- Remove the accessors numerator() and denominator().
24+
Check main() works.
25+
26+
OPTIONAL STEP 4
27+
- Remove the systematic call to normalize().
28+
- Add a equivalent() method to Fraction.
29+
- Upgrade the tests accordingly.
30+
- Transform the private normalize() into a public const normalized() method
31+
which return the normalized fraction.
32+
- Add some tests to check normalized().
33+

‎exercises/classes/classes.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include <iomanip>
2+
#include <iostream>
3+
#include <numeric>
4+
5+
class Fraction {
6+
7+
public:
8+
9+
// ADD YOUR CODE HERE
10+
11+
std::string str() const {
12+
std::ostringstream oss;
13+
oss << m_num << '/' << m_denom;
14+
return oss.str();
15+
}
16+
17+
int numerator() const {
18+
return m_num;
19+
}
20+
int denominator() const {
21+
return m_denom;
22+
}
23+
24+
private:
25+
26+
void normalize() {
27+
const int gcd = std::gcd(m_num, m_denom);
28+
m_num /= gcd;
29+
m_denom /= gcd;
30+
}
31+
32+
int m_num, m_denom;
33+
};
34+
35+
// ADD YOUR CODE HERE
36+
37+
#define CHECK(print,what) print(#what, what)
38+
39+
unsigned int WIDTH {20};
40+
41+
void printTestResult(std::string const & what, bool passed) {
42+
std::cout << std::setw(WIDTH) << what << ": " << (passed ? "PASS" : "** FAIL **") << '\n';
43+
}
44+
45+
int main() {
46+
47+
// create a fraction with values 3 (which is 3/1) and 1/3
48+
std::cout<<std::endl;
49+
const Fraction three{3};
50+
const Fraction third{1, 3};
51+
std::cout<<three.str()<<' '<<third.str()<<'\n';
52+
53+
// equality
54+
std::cout<<std::endl;
55+
CHECK(printTestResult,equal(three,three));
56+
CHECK(printTestResult,equal(third,third));
57+
CHECK(printTestResult,equal(three,Fraction{3}));
58+
CHECK(printTestResult,equal(three,Fraction{3, 1}));
59+
CHECK(printTestResult,equal(third,Fraction{1, 3}));
60+
CHECK(printTestResult,equal(Fraction{3},three));
61+
CHECK(printTestResult,equal(Fraction{1, 3},third));
62+
CHECK(printTestResult,equal(third,Fraction{2, 6}));
63+
64+
// multiply
65+
std::cout<<std::endl;
66+
CHECK(printTestResult,equal(multiply(third,2),Fraction{2, 3}));
67+
CHECK(printTestResult,equal(multiply(2,third),Fraction{2, 3}));
68+
CHECK(printTestResult,equal(multiply(three,third),Fraction{1, 1}));
69+
CHECK(printTestResult,equal(multiply(3,third),1));
70+
71+
// end
72+
std::cout<<std::endl;
73+
74+
}
75+

‎exercises/classes/classes_sol

94.9 KB
Binary file not shown.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#include <iomanip>
2+
#include <iostream>
3+
#include <sstream>
4+
#include <numeric>
5+
6+
class Fraction {
7+
8+
public:
9+
10+
Fraction(int a_num, int a_denom = 1) : m_num(a_num), m_denom(a_denom) {}
11+
12+
std::string str() const {
13+
std::ostringstream oss;
14+
oss << m_num << '/' << m_denom;
15+
return oss.str();
16+
}
17+
18+
friend bool equal( Fraction const & lhs, Fraction const & rhs ) {
19+
return (lhs.m_num==rhs.m_num) && (lhs.m_denom==rhs.m_denom);
20+
}
21+
22+
friend bool equivalent( Fraction const & lhs, Fraction const & rhs ) {
23+
return (lhs.m_num*rhs.m_denom==rhs.m_num*lhs.m_denom);
24+
}
25+
26+
friend Fraction multiply( Fraction const & lhs, Fraction const & rhs ) {
27+
return {lhs.m_num*rhs.m_num, lhs.m_denom*rhs.m_denom};
28+
}
29+
30+
Fraction normalized() const {
31+
const int gcd = std::gcd(m_num, m_denom);
32+
return {m_num/gcd, m_denom/gcd};
33+
}
34+
35+
private:
36+
37+
int m_num, m_denom;
38+
};
39+
40+
class TestResultPrinter {
41+
42+
public:
43+
44+
TestResultPrinter( unsigned int a_width ) : m_width(a_width) {}
45+
46+
void process(std::string const & what, bool passed) {
47+
std::cout << std::left << std::setw(m_width) << what << ": " << (passed ? "PASS" : "** FAIL **") << '\n';
48+
}
49+
50+
private:
51+
52+
unsigned int m_width;
53+
54+
};
55+
56+
#define CHECK(printer,what) printer.process(#what, what)
57+
58+
int main() {
59+
60+
// create a fraction with values 3 (which is 3/1) and 1/3
61+
std::cout<<std::endl;
62+
const Fraction three{3};
63+
const Fraction third{1, 3};
64+
std::cout<<three.str()<<' '<<third.str()<<'\n';
65+
66+
// equality
67+
std::cout<<std::endl;
68+
TestResultPrinter p1{27};
69+
CHECK(p1,equal(three,three));
70+
CHECK(p1,equal(third,third));
71+
CHECK(p1,equal(three,Fraction{3}));
72+
CHECK(p1,equal(three,Fraction{3,1}));
73+
CHECK(p1,equal(third,Fraction{1,3}));
74+
CHECK(p1,equal(Fraction{3},three));
75+
CHECK(p1,equal(Fraction{1,3},third));
76+
77+
// equivalence
78+
std::cout<<std::endl;
79+
TestResultPrinter p2{40};
80+
CHECK(p2,!equal(third,Fraction{2,6}));
81+
CHECK(p2,equivalent(third,Fraction{2,6}));
82+
CHECK(p2,equal(third,Fraction{2,6}.normalized()));
83+
84+
// multiply
85+
std::cout<<std::endl;
86+
TestResultPrinter p3{48};
87+
CHECK(p3,equal(multiply(third,2),Fraction{2,3}));
88+
CHECK(p3,equal(multiply(2,third),Fraction{2,3}));
89+
CHECK(p3,equivalent(multiply(three,third),Fraction{1,1}));
90+
CHECK(p3,equivalent(multiply(3,third),1));
91+
92+
// end
93+
std::cout<<std::endl;
94+
95+
}

‎exercises/operators/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
operators
2+
operators_sol

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /