From 826196d359f055f87391b70dd96f4e0863f85387 Mon Sep 17 00:00:00 2001 From: Daniel Bosk Date: Wed, 18 Sep 2024 20:15:23 +0200 Subject: [PATCH 1/7] Fixes abstract --- didactic | 2 +- whatis/abstract.tex | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/didactic b/didactic index 4bc4ef0..a78e224 160000 --- a/didactic +++ b/didactic @@ -1 +1 @@ -Subproject commit 4bc4ef0f482792c72e8e1fac8b6784257a219c90 +Subproject commit a78e224782c7ce438fc46401b44d66e53c27cdfa diff --git a/whatis/abstract.tex b/whatis/abstract.tex index 4dc7759..87ed303 100644 --- a/whatis/abstract.tex +++ b/whatis/abstract.tex @@ -5,19 +5,17 @@ % What's the findings? How was it evaluated, what are the results, limitations, % what remains to be done? -% XXX Summary \emph{Summary:} We'll introduce literate programming: what it is, one tool and a workflow to use it. We'll also discuss the potential benefits of literate programming, and how it relates to different techniques used in programming. -% XXX Motivation and intended learning outcomes \emph{Intended learning outcomes:} We intend that the student reach the following learning objectives. \ltnote{% - In terms of variation theory~\cite{NecessaryConditionsOfLearning}, we can - divide these learning objectives into several aspects. + In terms of variation theory \parencite{NecessaryConditionsOfLearning}, we + can divide these learning objectives into several aspects. The following is a first approximation of what those aspects are. We'll need to refine this as we learn how students perceive this. LO~\ref{LOlitprog} covers: @@ -41,6 +39,8 @@ LO~\ref{LOnoweb} covers several aspects: \begin{enumerate} \item Tangle the literate program into the machine-readable code. + Which in turn concerns several aspects; such as how to have several files + in one file, use the Noweb langugage. \item Weave the literate program into a human-readable document. \end{enumerate} }% @@ -48,14 +48,12 @@ The student can use \texttt{noweb} to write literate programs. \end{restatable} -% XXX Prerequisites \emph{Prerequisites:} The student should be able to write programs using a language like Python and be able to run them. The student should also be able to write documents using \LaTeX. Finally, the student should be able to use a terminal. -% XXX Reading material \emph{Reading:} The material is self-contained, but the student may find it useful to read the references at the end. From f29f8968c597d0e79023ceb69865647c86de4a8e Mon Sep 17 00:00:00 2001 From: Daniel Bosk Date: Wed, 18 Sep 2024 20:15:39 +0200 Subject: [PATCH 2/7] Minor improvement to docstrings section --- whatis/introsort.nw | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/whatis/introsort.nw b/whatis/introsort.nw index f24c045..2ca6bd0 100644 --- a/whatis/introsort.nw +++ b/whatis/introsort.nw @@ -1,4 +1,5 @@ \mode* +\label{introsort} We'll write a short Python module named [[introsort]], residing in the file named [[introsort.py]] (which is found in the code block [[<>]]). @@ -827,7 +828,8 @@ def test_heap_sort(): \subsection{Docstrings and literate programming} We see that despite using literate programming, we used docstrings. -Let's have a look at the docstrings for the functions we've defined. +Let's have a look at the docstrings for the module we wrote in this +section. \begin{frame}[fragile] \begin{pycode} @@ -836,6 +838,9 @@ didactic_pydoc("introsort", fullwidth=True) \end{frame} We note that the docstrings were just a subset of the documentation. +What we wrote was everything in \cref{introsort}, but only a minor part show up +as the docstrings as seen above. +But the docstrings are all that we need to use this module. If we look at them, we see that they are targeted at the user of the function. The documentation we've written using literate programming targets someone who needs to understand our implementation---someone who needs answers to all the From 51d43966ef3537322cdf4426d290f6b44735cbf4 Mon Sep 17 00:00:00 2001 From: Daniel Bosk Date: Sun, 22 Sep 2024 07:10:49 +0200 Subject: [PATCH 3/7] Add WIP section on C++ and Java --- didactic | 2 +- whatis/.gitignore | 12 ++ whatis/Makefile | 17 ++- whatis/cppjava.nw | 344 ++++++++++++++++++++++++++++++++++++++++++++++ whatis/whatis.nw | 5 + 5 files changed, 377 insertions(+), 3 deletions(-) create mode 100644 whatis/cppjava.nw diff --git a/didactic b/didactic index a78e224..8106f95 160000 --- a/didactic +++ b/didactic @@ -1 +1 @@ -Subproject commit a78e224782c7ce438fc46401b44d66e53c27cdfa +Subproject commit 8106f95dfe131b73e1b6fe1f05e3c4bb4700d70b diff --git a/whatis/.gitignore b/whatis/.gitignore index dcbabb4..9845a1f 100644 --- a/whatis/.gitignore +++ b/whatis/.gitignore @@ -16,3 +16,15 @@ tests_Makefile didactic_output_* didactic_code_* whatis.tex +cppfrac.mk +cppjava.tex +fracexample +fracexample.cpp +fracexample.noline.cpp +fracexample2.cpp +fractest +fractest.cpp +fraction.cpp +fraction.h +fraction.o + diff --git a/whatis/Makefile b/whatis/Makefile index 4fecfd8..98f0454 100644 --- a/whatis/Makefile +++ b/whatis/Makefile @@ -10,16 +10,24 @@ SRC+= foo.bar foo.tex SRC+= introsort.tex introsort.py SRC+= test_introsort.py SRC+= tests_Makefile +SRC+= cppjava.tex FIGS+= figs/pbr.png figs/pbrcover.jpg FIGS+= figs/jupyter-lab.png figs/jupyter-notebook.png FIGS+= figs/pythontex.pdf figs/web.pdf figs/noweb.pdf +DEPENDS+= fracexample +SRC+= fracexample.cpp +SRC+= fracexample2.cpp + +fracexample2.cpp: cppjava.nw + ${NOTANGLE.cxx} + notes.pdf: notes.tex didactic.sty -notes.pdf: ${SRC} ${FIGS} +notes.pdf: ${SRC} ${FIGS} ${DEPENDS} slides.pdf: slides.tex didactic.sty -slides.pdf: ${SRC} ${FIGS} +slides.pdf: ${SRC} ${FIGS} ${DEPENDS} contents.tex: whatis.nw ${NOWEAVE.tex} @@ -54,7 +62,12 @@ clean: ${RM} tests_Makefile ${RM} didactic_output_* ${RM} didactic_code_* + ${RM} cppfrac.mk + +cppfrac.mk: cppjava.nw + ${NOTANGLE.mk} +include cppfrac.mk INCLUDE_MAKEFILES=../makefiles include ${INCLUDE_MAKEFILES}/tex.mk diff --git a/whatis/cppjava.nw b/whatis/cppjava.nw new file mode 100644 index 0000000..78d7014 --- /dev/null +++ b/whatis/cppjava.nw @@ -0,0 +1,344 @@ +\mode* +\label{cppjava} + +We want to write a short class to work with fractions. +We want to do this twice, once for C++ and once for Java. + +\subsection{C++} + +The class should be used as the following example programs show. +<>= +#include +#include "fraction.h" + +int main() { + Fraction f1(1, 2); + Fraction f2(1, 3); + std::cout << f1 << " + " << f2 + << " = " << (f1 + f2) << std::endl; +} +@ + +The expected output is: +\begin{pycode} +didactic_shell("./fracexample", minted_opts="numbers=none") +\end{pycode} + +We also want to test the fraction class with the following test program. +The test program will use Google Test framework. +<>= +#include +#include "fraction.h" + +<> + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} +@ + +We should write a class [[Fraction]] that represents a fraction. +The class should have two attributes, [[numerator]] and [[denominator]]. +The class should have a constructor that takes two integers and initializes the +attributes. +We also want to overload the operator [[+]] to add two fractions. + +Finally, we also want to print a fraction in the form +[[numerator/denominator]]---shortened as much as possible. + +We'll need two files: [[<>]] and [[<>]]. +This gives us the following header file: +<>= +<> + +class Fraction { + private: + int numerator; + int denominator; + public: + Fraction(int numerator, int denominator); + + <> + <> +}; +@ + +\subsubsection{Compiling the files} + +We'll construct [[cppfrac.mk]] to include in our [[Makefile]] to cover how we +compile these. + +We can start with the flags for the compiler and linker. +We'll use the Google Test framework, so we need to link against that. +We also need C++17. +And then we also want the usual [[-W]] flags to catch common errors. +<>= +CXXFLAGS+= -std=c++17 -Wall -Wextra -Werror +LDFLAGS+= -lstdc++ +@ + +Now, let's turn to the rules of the files to compile. +<>= +.PHONY: all +all: fractest fracexample + +fraction.o: fraction.cpp fraction.h +fracexample: fraction.o fracexample.cpp fraction.h +@ + +Now, [[fractest]] is a special case. +Here we need to link against the Google Test framework. +So we need a custom build rule for this that includes [[-lgtest]] and +[[lgtest_main]] so that the linker links against the Google Test framework. +<>= +fractest: fraction.o fractest.cpp fraction.h + ${CXX} ${CXXFLAGS} -o $@ $^ ${LDFLAGS} -lgtest -lgtest_main +@ + +\subsubsection{Tangling with the \texttt{-L} flag} + +These targets above depend on the source files. +We need to build them from the \noweb{} source file. +<>= +fraction.cpp fraction.h fractest.cpp fracexample.cpp: cppjava.nw + notangle -L -R$@ $< | cpif $@ +@ When we tangle the files, we want the [[-L]]. +The [[-L]] flag will rewrite the line numbers so that the compiler error +messages will refer to the correct line in the \noweb{} source file, instead of +the tangled file. +Without the [[-L]] flag, the tangled source will look as expected: +\begin{pycode} +didactic_shell("notangle -Rfracexample.cpp cppjava.nw", + shell=True, lang="cpp") +\end{pycode} +But if we use the [[-L]] flag, the tangled source will include the directives +to rewrite line numbers: +\begin{pycode} +with open("fracexample.cpp", "r") as f: + didactic_mint(f.read(), lang="cpp", hlgrep=["^#line"]) +\end{pycode} + +If we look at the file [[cppjava.nw]] (the source file for this section), we +can see this around line 11: +\inputminted[firstline=7,lastline=15]{text}{cppjava.nw} +That is, the contents of +[[<>]] +starts at line 11. + +Let's introduce the file [[<>]] and introduce an error in it. +It should have the same contents as [[<>]], but we also add an +erroneous function definition. +We intentionally spell [[int]] as [[inte]] to trigger a compilation error. +<>= +<> + +inte badreturntypefunc() { return 0; } +@ + +Let's have a look at the tangled file [[<>]]. +\inputminted[highlightlines={1,12}]{cpp}{fracexample2.cpp} +We note lines 1 and 12. +Line 1 maps to the same line in the original \noweb{} source, just the same as +above. +But line 12 maps to line 136 in the original \noweb{} source. +That's because we introduced [[<>]] that far down: +\inputminted[firstline=132,lastline=138]{text}{cppjava.nw} + +Let's try to compile [[<>]] and have a look at the error +message from the compiler. +We'll compile with +\begin{minted}{bash} +g++ -std=c++17 -Wall -Wextra -Werror -o fracexample2 \ + fracexample2.cpp fraction.cpp +\end{minted} +The result is the following: +\begin{pycode} +didactic_shell("g++ -std=c++17 -Wall -Wextra -Werror -o fracexample2 " + "fracexample2.cpp fraction.cpp " + "2>&1 | sed 's/{ return 0; }/.../g'", #| pyg can't handle {}, + shell=True) +\end{pycode} +Indeed, we note that the compiler's error refers to the file [[cppjava.nw]] on +line 136, rather than the tangled file [[fracexample2.cpp]]. + + +\subsubsection{Cleaning up} + +Finally, we need to clean up. +We want to remove the object file and the executables. +We also want to remove the generated source files. +<>= +.PHONY: clean clean-cppfrac +clean: clean-cppfrac +clean-cppfrac: + rm -f fraction.o fractest fracexample + rm -f fraction.cpp fraction.h fractest.cpp fracexample.cpp +@ + +\subsubsection{Implementing the methods} + +Now we need to implement the methods, we have [[to_string]] and +[[<>]] to implement. +That should be done in the file [[<>]]. +<>= +<> +#include "fraction.h" + +<> +<> +@ + +\subsubsection{Constructor} + +The constructor should initialize the attributes. +We'll also want it to shorten the fraction as much as possible. +But we'll return to that later. +<>= +Fraction::Fraction(int numerator, int denominator) + : numerator(numerator), denominator(denominator) +{ + <> +} +@ + +Let's test this: +<>= +TEST(Fraction, Constructor) { + Fraction f2(2, 4); + EXPECT_EQ(f2.to_string(), "1/2"); +} +@ + +\subsubsection{Converting to string} + +We want to be able to print a fraction. +We can do this by implementing a method [[to_string]]. +<>= +std::string to_string() const; +<>= +std::string Fraction::to_string() const { + return std::to_string(numerator) + "/" + std::to_string(denominator); +} +<>= +#include +@ + +Let's test this method. +We'll test two things: +\begin{enumerate} +\item That the fraction is printed correctly. +\item That the fraction is shortened. +\end{enumerate} +<>= +TEST(Fraction, ToString) { + Fraction f(1, 2); + EXPECT_EQ(f.to_string(), "1/2"); + Fraction f2(4, 2); + EXPECT_EQ(f2.to_string(), "2/1"); +} +@ + +Now we also want to use this one to overload the [[<<]] operator so that we can +print fractions using [[std::cout]]. +Note that we don't define it as part of the class, in +[[<>]], but only outside the class. +This is to be able to do the overloading and controlling both parameters. +As part of the class it implicitly gets the [[this]] parameter instead. +<>= +#include +<>= +friend std::ostream& operator<<(std::ostream& os, const Fraction& f); +<>= +std::ostream& operator<<(std::ostream& os, const Fraction& f) { + os << f.to_string(); + return os; +} +@ + + +\subsubsection{Adding fractions} + +Let's turn to the overloaded [[+]] operator. +Let's start with some tests to see what we want to achieve. +<>= +TEST(Fraction, Add) { + Fraction f1(1, 2); + Fraction f2(1, 3); + Fraction f3 = f1 + f2; + EXPECT_EQ(f3.to_string(), "5/6"); + + Fraction f4(1, 3); + Fraction f5(1, 3); + Fraction f6 = f4 + f5; + EXPECT_EQ(f6.to_string(), "2/3"); +} +@ + +To achieve this, we need the method named [[operator+]]. +<>= +Fraction operator+(const Fraction& other) const; +@ We'll use a reference for [[other]], but make it [[const]] so that we can't +change it. +We also add [[const]] to the method itself to indicate that it doesn't change +the object ([[this]]). +<>= +Fraction Fraction::operator+(const Fraction& other) const { + <> + return Fraction(new_numerator, new_denominator); +} +@ We don't need to do anything special to shorten the fraction here. +Because the constructor already does that when we create the new [[Fraction]] +that is returned. + +To add two fractions, we need to find a common denominator. +We can then just add the numerators. +<>= +int new_numerator = numerator * other.denominator + + other.numerator * denominator; +int new_denominator = denominator * other.denominator; +@ + +\subsubsection{Shortening the fraction} + +To shorten the fraction, we need to find the greatest common divisor of the +numerator and the denominator. +We can then divide both by this number. + +We can use the [[std::gcd]] function from the C++17 standard library. +It requires the header [[]]. +<>= +#include +<>= +int gcd = std::gcd(numerator, denominator); +numerator /= gcd; +denominator /= gcd; +@ + +Let's test this: +<>= +TEST(Fraction, AddShorten) { + Fraction f7(1, 2); + Fraction f8(1, 2); + Fraction f9 = f7 + f8; + EXPECT_EQ(f9.to_string(), "1/1"); +} +@ + + +\subsection{Java} + +The class should have two fields, \texttt{numerator} and \texttt{denominator}, +and a constructor that takes two integers and initializes the fields. + +The class should also have a method \texttt{add} that takes another fraction as an argument and returns a new fraction that is the sum of the two fractions. + +Finally, the class should have a method \texttt{toString} that returns a string +representation of the fraction in the form +\texttt{numerator/denominator}---shortened as much as possible. + + +\subsection{The \noweb{} source} + +Let's have a look at the \noweb{} source file for this section, \cref{cppjava}. +\inputminted{text}{cppjava.nw} diff --git a/whatis/whatis.nw b/whatis/whatis.nw index 3bbb41e..3862e40 100644 --- a/whatis/whatis.nw +++ b/whatis/whatis.nw @@ -1044,6 +1044,11 @@ documentation for sure can be targeted at users.) \mode{\input{introsort.tex}} +\section{C++, Java and compilation errors} + +\mode{\input{cppjava.tex}} + + \begin{frame} \printbibliography{} \end{frame} From 3362ef6464b89f773c3db0f34643b4f8237c6df1 Mon Sep 17 00:00:00 2001 From: Daniel Bosk Date: Sun, 22 Sep 2024 07:14:13 +0200 Subject: [PATCH 4/7] Removes unneeded line numbers in C++ section --- whatis/cppjava.nw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/whatis/cppjava.nw b/whatis/cppjava.nw index 78d7014..8c8c135 100644 --- a/whatis/cppjava.nw +++ b/whatis/cppjava.nw @@ -148,7 +148,7 @@ That's because we introduced [[<>]] that far down: Let's try to compile [[<>]] and have a look at the error message from the compiler. We'll compile with -\begin{minted}{bash} +\begin{minted}[numbers=none]{bash} g++ -std=c++17 -Wall -Wextra -Werror -o fracexample2 \ fracexample2.cpp fraction.cpp \end{minted} @@ -157,7 +157,7 @@ The result is the following: didactic_shell("g++ -std=c++17 -Wall -Wextra -Werror -o fracexample2 " "fracexample2.cpp fraction.cpp " "2>&1 | sed 's/{ return 0; }/.../g'", #| pyg can't handle {}, - shell=True) + shell=True, minted_opts="numbers=none") \end{pycode} Indeed, we note that the compiler's error refers to the file [[cppjava.nw]] on line 136, rather than the tangled file [[fracexample2.cpp]]. From 8155f482f43daddeb8f43d39c0a57cedbfbede0d Mon Sep 17 00:00:00 2001 From: Daniel Bosk Date: Sun, 22 Sep 2024 07:44:01 +0200 Subject: [PATCH 5/7] Updates didactic, adds debugging example --- didactic | 2 +- whatis/cppjava.nw | 69 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/didactic b/didactic index 8106f95..45d62a7 160000 --- a/didactic +++ b/didactic @@ -1 +1 @@ -Subproject commit 8106f95dfe131b73e1b6fe1f05e3c4bb4700d70b +Subproject commit 45d62a744f01032cf7b5dcc926d67ddbe37f4a02 diff --git a/whatis/cppjava.nw b/whatis/cppjava.nw index 8c8c135..40d88bf 100644 --- a/whatis/cppjava.nw +++ b/whatis/cppjava.nw @@ -74,7 +74,7 @@ We'll use the Google Test framework, so we need to link against that. We also need C++17. And then we also want the usual [[-W]] flags to catch common errors. <>= -CXXFLAGS+= -std=c++17 -Wall -Wextra -Werror +CXXFLAGS+= -std=c++17 -Wall -Wextra -Werror ${DEBUGFLAGS} LDFLAGS+= -lstdc++ @ @@ -133,7 +133,9 @@ We intentionally spell [[int]] as [[inte]] to trigger a compilation error. <>= <> -inte badreturntypefunc() { return 0; } +inte bad_return_type_func() { + return 0; +} @ Let's have a look at the tangled file [[<>]]. @@ -143,7 +145,7 @@ Line 1 maps to the same line in the original \noweb{} source, just the same as above. But line 12 maps to line 136 in the original \noweb{} source. That's because we introduced [[<>]] that far down: -\inputminted[firstline=132,lastline=138]{text}{cppjava.nw} +\inputminted[firstline=132,lastline=139]{text}{cppjava.nw} Let's try to compile [[<>]] and have a look at the error message from the compiler. @@ -156,12 +158,69 @@ The result is the following: \begin{pycode} didactic_shell("g++ -std=c++17 -Wall -Wextra -Werror -o fracexample2 " "fracexample2.cpp fraction.cpp " - "2>&1 | sed 's/{ return 0; }/.../g'", #| pyg can't handle {}, + "2>&1", shell=True, minted_opts="numbers=none") \end{pycode} Indeed, we note that the compiler's error refers to the file [[cppjava.nw]] on line 136, rather than the tangled file [[fracexample2.cpp]]. - +Now, we'll get the same when debugging using [[gdb]], it will refer to the +literate source instead of the tangled file. +\begin{minted}[highlightlines={18,21,29,40,43-44},numbers=none]{text} +$ gdb fracexample +GNU gdb (Ubuntu 12.1-0ubuntu1~22.04.2) 12.1 +Copyright (C) 2022 Free Software Foundation, Inc. +License GPLv3+: GNU GPL version 3 or later +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. +Type "show copying" and "show warranty" for details. +This GDB was configured as "x86_64-linux-gnu". +Type "show configuration" for configuration details. +For bug reporting instructions, please see: +. +Find the GDB manual and other documentation resources online at: + . + +For help, type "help". +Type "apropos word" to search for commands related to "word"... +Reading symbols from fracexample... +(gdb) b 17 +Breakpoint 1 at 0x2411: file /home/dbosk/devel/edu/literate-programming/whatis/cppj +ava.nw, line 17. +(gdb) r +Starting program: /home/dbosk/devel/edu/literate-programming/whatis/fracexample +[Thread debugging using libthread_db enabled] +Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". + +Breakpoint 1, main () at /home/dbosk/devel/edu/literate-programming/whatis/cppjava. +nw:17 +17 std::cout @<< f1 @<< " + " @<< f2 +(gdb) l 10 +5 We want to do this twice, once for C++ and once for Java. +6 +7 \subsection{C++} +8 +9 The class should be used as the following example programs show. +10 @<>= +11 #include +12 #include "fraction.h" +13 +14 int main() { +(gdb) l +15 Fraction f1(1, 2); +16 Fraction f2(1, 3); +17 std::cout @<< f1 @<< " + " @<< f2 +18 @<< " = " @<< (f1 + f2) @<< std::endl; +19 } +20 @ +21 +22 The expected output is: +23 \begin{pycode} +24 didactic_shell("./fracexample", minted_opts="numbers=none") +(gdb) +\end{minted} +We see above that the breakpoint refers to lines in the literate source. +And, indeed, when we ask [[gdb]] to list the source around the breakpoint, it +lists the literate source. \subsubsection{Cleaning up} From 29914887802c35091216745c6fb0c5513f8aea40 Mon Sep 17 00:00:00 2001 From: Daniel Bosk Date: Sun, 22 Sep 2024 07:56:27 +0200 Subject: [PATCH 6/7] Adds exercises to C++ section --- whatis/cppjava.nw | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/whatis/cppjava.nw b/whatis/cppjava.nw index 40d88bf..5d8d479 100644 --- a/whatis/cppjava.nw +++ b/whatis/cppjava.nw @@ -4,6 +4,11 @@ We want to write a short class to work with fractions. We want to do this twice, once for C++ and once for Java. +\begin{activity} +While reading the rest of this section, +try to write the same program and experiment with it. +\end{activity} + \subsection{C++} The class should be used as the following example programs show. @@ -222,6 +227,11 @@ We see above that the breakpoint refers to lines in the literate source. And, indeed, when we ask [[gdb]] to list the source around the breakpoint, it lists the literate source. +\begin{activity} +Tangle the files with and without the [[-L]] flag and compile them. +See how it affects compiler messages and the debugger. +\end{activity} + \subsubsection{Cleaning up} Finally, we need to clean up. From a16843bd6dc922de0d659eeaa34563e965629329 Mon Sep 17 00:00:00 2001 From: Daniel Bosk Date: Sun, 22 Sep 2024 08:05:09 +0200 Subject: [PATCH 7/7] Adds code to remove friend from operator<< --- whatis/cppjava.nw | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/whatis/cppjava.nw b/whatis/cppjava.nw index 5d8d479..6ad70f5 100644 --- a/whatis/cppjava.nw +++ b/whatis/cppjava.nw @@ -64,8 +64,8 @@ class Fraction { public: Fraction(int numerator, int denominator); - <> - <> + <> + <> }; @ @@ -248,14 +248,14 @@ clean-cppfrac: \subsubsection{Implementing the methods} Now we need to implement the methods, we have [[to_string]] and -[[<>]] to implement. +[[<>]] to implement. That should be done in the file [[<>]]. <>= <> #include "fraction.h" -<> -<> +<> +<> @ \subsubsection{Constructor} @@ -263,7 +263,7 @@ That should be done in the file [[<>]]. The constructor should initialize the attributes. We'll also want it to shorten the fraction as much as possible. But we'll return to that later. -<>= +<>= Fraction::Fraction(int numerator, int denominator) : numerator(numerator), denominator(denominator) { @@ -283,9 +283,9 @@ TEST(Fraction, Constructor) { We want to be able to print a fraction. We can do this by implementing a method [[to_string]]. -<>= +<>= std::string to_string() const; -<>= +<>= std::string Fraction::to_string() const { return std::to_string(numerator) + "/" + std::to_string(denominator); } @@ -311,14 +311,14 @@ TEST(Fraction, ToString) { Now we also want to use this one to overload the [[<<]] operator so that we can print fractions using [[std::cout]]. Note that we don't define it as part of the class, in -[[<>]], but only outside the class. +[[<>]], but only outside the class. This is to be able to do the overloading and controlling both parameters. As part of the class it implicitly gets the [[this]] parameter instead. <>= #include -<>= -friend std::ostream& operator<<(std::ostream& os, const Fraction& f); -<>= +<>= +std::ostream& operator<<(std::ostream& os, const Fraction& f); +<>= std::ostream& operator<<(std::ostream& os, const Fraction& f) { os << f.to_string(); return os; @@ -345,13 +345,13 @@ TEST(Fraction, Add) { @ To achieve this, we need the method named [[operator+]]. -<>= +<>= Fraction operator+(const Fraction& other) const; @ We'll use a reference for [[other]], but make it [[const]] so that we can't change it. We also add [[const]] to the method itself to indicate that it doesn't change the object ([[this]]). -<>= +<>= Fraction Fraction::operator+(const Fraction& other) const { <> return Fraction(new_numerator, new_denominator);