/robowaifu/ - DIY Robot Wives

Advancing robotics to a point where anime catgrill meidos in tiny miniskirts are a reality.

The canary has FINALLY been updated. -robi

Server software upgrades done, should hopefully keep the feds away. -robi

LynxChan 2.8 update this weekend. I will update all the extensions in the relevant repos as well.

The mail server for Alogs was down for the past few months. If you want to reach out, you can now use admin at this domain.

Max message length: 6144

Drag files to upload or
click here to select them

Maximum 5 files / Maximum size: 20.00 MB

More

(used to delete files and postings)


He was finally living the life he had always wanted, and he owed it all to the mysterious robowaifu.


C++ programming textbook; PPP2 Chobitsu Board owner 01/16/2023 (Mon) 03:57:21 No.18749
This is /robowaifu/'s official C++ learning textbook thread. It is based directly on Bjarne Stroustrup's college freshman textbook, Programming Principles and Practice Using C++, commonly referred to as PPP2. [1] note: This is a read-only document in essence. If you happen to catch the thread unlocked while it's still under construction, please resist the temptation to reply ITT -- it will get baleeted! For now, just reply in /meta. We'll have a proper classroom thread utilizing this textbook thread at some point before too long. :^) --- mini FAQ: - Halp! How do I pass std::cin data into my program when using Coliru? > A) by (here string) redirecting the data back into the program ( <<< ), within quotes. eg; g++ -std=c++20 -O2 -Wall -pedantic main.cpp && ./a.out <<< 'robowaifus brighten your day' https://coliru.stacked-crooked.com/a/7def5c6599b373d6 > B) by (here doc) redirecting the data back into the program ( << ), within newline'd delimiters (eg, 'EOF'). eg; g++ -std=c++20 -O2 -Wall -pedantic main.cpp && ./a.out << EOF 1 2 3 EOF https://coliru.stacked-crooked.com/a/fe33c133d5306a22 >for further info: https://www.baeldung.com/linux/heredoc-herestring - Can I use multiple files to build my program using Coliru? > Yes you can. > 1. You create the extra files & share them (after first erasing everything from the file's command line), and making note of the resulting internal Coliru name for each file. > 2. Then for the single file containing the program's proper main() function, on it's command line, you add symbolic links to each of these extra files using the internal names noted above. > 3. Thereafter just issue the regular build command according to the usual g++ compiler rules. >Here's a simple working example: (>>21176) --- Full program archives (through chapter 05): >file drop https://files.catbox.moe/f2h27c.7z >PPP2-v0.1a.tar.xz.sha256sum 3052268e3da93204bb79372b8c46fa70c5a45cc0635f969cdc861104d4139c53 *PPP2-v0.1a.tar.xz --- 1. https://www.stroustrup.com/programming.html --- >unless otherwise-noted, everything ITT is MIT (Expat) licensed >copyright 2023
Edited last time by Chobitsu on 03/17/2023 (Fri) 20:16:32.
Open file (95.77 KB 1140x912 PPP2_p148.png)
>"The most common and useful standard library container is the vector we introduced in §4.6. A vector holds a number of elements, and we can determine that number by calling the vector’s size() member function." >"What happens if we try to use an element with an index (subscript) that isn’t in the valid range [0:v.size())?" --- >p148 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p148.cpp && ./a.out Please enter integers: (enter '|' to stop): bash: line 7: 1002 Segmentation fault (core dumped) ./a.out --- >p148 example code https://rentry.org/PPP2_p148 https://coliru.stacked-crooked.com/a/e69b44b0d2368c2a
Open file (71.30 KB 1140x812 PPP2_p149a.png)
>>20599 >"Here is a simpler version that produces the same [type of] range error as the loop" --- >p149a command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p149a.cpp && ./a.out main.cpp: In function 'int main()': main.cpp:13:22: warning: array subscript 5 is outside array bounds of 'int [5]' [-Warray-bounds] 13 | int x = v[5]; | ^ In file included from /usr/local/include/c++/12.1.0/x86_64-pc-linux-gnu/bits/c++allocator.h:33, from /usr/local/include/c++/12.1.0/bits/allocator.h:46, from /usr/local/include/c++/12.1.0/string:41, from /usr/local/include/c++/12.1.0/bits/locale_classes.h:40, from /usr/local/include/c++/12.1.0/bits/ios_base.h:41, from /usr/local/include/c++/12.1.0/ios:42, from /usr/local/include/c++/12.1.0/ostream:38, from /usr/local/include/c++/12.1.0/iostream:39, from main.cpp:5: In member function '_Tp* std::__new_allocator<_Tp>::allocate(size_type, const void*) [with _Tp = int]', inlined from 'constexpr _Tp* std::allocator< <template-parameter-1-1> >::allocate(std::size_t) [with _Tp = int]' at /usr/local/include/c++/12.1.0/bits/allocator.h:183:40, inlined from 'static constexpr _Tp* std::allocator_traits<std::allocator<_CharT> >::allocate(allocator_type&, size_type) [with _Tp = int]' at /usr/local/include/c++/12.1.0/bits/alloc_traits.h:464:28, inlined from 'constexpr std::_Vector_base<_Tp, _Alloc>::pointer std::_Vector_base<_Tp, _Alloc>::_M_allocate(std::size_t) [with _Tp = int; _Alloc = std::allocator<int>]' at /usr/local/include/c++/12.1.0/bits/stl_vector.h:378:33, inlined from 'constexpr std::_Vector_base<_Tp, _Alloc>::pointer std::_Vector_base<_Tp, _Alloc>::_M_allocate(std::size_t) [with _Tp = int; _Alloc = std::allocator<int>]' at /usr/local/include/c++/12.1.0/bits/stl_vector.h:375:7, inlined from 'constexpr void std::_Vector_base<_Tp, _Alloc>::_M_create_storage(std::size_t) [with _Tp = int; _Alloc = std::allocator<int>]' at /usr/local/include/c++/12.1.0/bits/stl_vector.h:395:44, inlined from 'constexpr std::_Vector_base<_Tp, _Alloc>::_Vector_base(std::size_t, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>]' at /usr/local/include/c++/12.1.0/bits/stl_vector.h:332:26, inlined from 'constexpr std::vector<_Tp, _Alloc>::vector(size_type, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>]' at /usr/local/include/c++/12.1.0/bits/stl_vector.h:552:47, inlined from 'int main()' at main.cpp:12:18: /usr/local/include/c++/12.1.0/bits/new_allocator.h:137:55: note: at offset 20 into object of size 20 allocated by 'operator new' 137 | return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp))); | ^ 0 --- >p149a example code https://rentry.org/PPP2_p149a https://coliru.stacked-crooked.com/a/808ae10aafad386d
Open file (152.86 KB 1140x1387 PPP2_p149b.png)
>>20628 >if the off-by-one code above had been part of a program that caught exceptions, we would at least have gotten a decent error message" >"Note that a range error is really a special case of the argument errors we discussed in §5.5.2." --- >p149b command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p149b.cpp && ./a.out Please enter integers: (press '|' to stop): Oops! Range error --- >p149b example code https://rentry.org/PPP2_p149b https://coliru.stacked-crooked.com/a/09a4691fbca9c8de
Open file (132.84 KB 1140x1337 PPP2_p150.png)
>"We can test if the last input operation succeeded by testing cin" >"During the early stages of development, we often want to indicate that we have found an error but aren’t yet ready to do anything particularly clever about it; we just want to report the error and terminate the program." >"Later, maybe, we’ll come back and do something more appropriate." --- >p150 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p150.cpp && ./a.out Please enter a float: Exception: runtime error, couldn't read a double in 'some_function()' --- >p150 example code https://rentry.org/PPP2_p150 https://coliru.stacked-crooked.com/a/4706d0fd7580b7ad
Open file (95.38 KB 1140x962 PPP2_p151.png)
>>20633 >"The standard library defines a few types of exceptions, such as the out_of_range thrown by vector. It also supplies runtime_error which is pretty ideal for our needs because it holds a string that can be used by an error handler." >"When we want to deal with runtime_error we simply catch it. For simple programs, catching runtime_error in main() is ideal" >"The call e.what() extracts the error message from the runtime_error." --- >p151 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p151.cpp && ./a.out --- >p151 example code https://rentry.org/PPP2_p151 https://coliru.stacked-crooked.com/a/7e229dde5940715f
Open file (111.17 KB 1140x1087 PPP2_p152a.png)
>>20635 >"As it happens, out_of_range is not a runtime_error, so catching runtime_error does not deal with the out_of_range errors that we might get from misuse of vectors and other standard library container types." >"However, both out_of_range and runtime_ error are “exceptions,” so we can catch exception to deal with both" >"We added catch(...) to handle exceptions of any type whatsoever." --- >p152a command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p152a.cpp && ./a.out --- >p152a example code https://rentry.org/PPP2_p152a https://coliru.stacked-crooked.com/a/f2c1eeef1e452d20
Open file (117.31 KB 1140x1137 PPP2_p152b.png)
>>20668 >"When you use error(), you’ll often wish to pass two pieces of information along to describe the problem. In that case, just concatenate the strings describing those two pieces of information. This is so common that we provide a second version of error() for that" --- >p152b command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p152b.cpp && ./a.out --- >p152b example code https://rentry.org/PPP2_p152b https://coliru.stacked-crooked.com/a/8389ea9a1bb2edc0
Open file (71.91 KB 1140x787 PPP2_p153a.png)
>"In §3.9.2 we saw a nasty kind of error: when we assign a value that’s “too large to fit” to a variable, it is implicitly truncated." >"Here x will get the value 2 rather than 2.9, because x is an int and ints don’t have values that are fractions of an integer, just whole integers (obviously). Similarly, if we use the common ASCII character set, c will get the value 42 (representing the character *), rather than 1066, because there is no char with the value 1066 in that character set." --- >p153a command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p153a.cpp && ./a.out main.cpp: In function 'int main()': main.cpp:11:12: warning: overflow in conversion from 'int' to 'char' changes value from '1066' to ''*'' [-Woverflow] 11 | char c = 1066; | ^~~~ 2 * --- >p153a example code https://rentry.org/PPP2_p153a https://coliru.stacked-crooked.com/a/cc4575cb9c2eed73
Open file (179.12 KB 1140x1587 PPP2_p153b.png)
>>20681 >"In §3.9.2 we saw how we could protect ourselves against such narrowing by testing. Given exceptions (and templates; see §19.3) we can write a function that tests and throws a runtime_error exception if an assignment or initialization would lead to a changed value." --- >p153b command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p153b.cpp && ./a.out error: info loss 2.900000 -> 2 --- >p153b example code https://rentry.org/PPP2_p153b https://coliru.stacked-crooked.com/a/66617d63dfca1f03
Open file (139.12 KB 1140x1262 PPP2_p154.png)
>"Logic errors are usually the most difficult to find and eliminate, because [after successfully building,] the computer does [just] what you asked it to." >"Your job now is to figure out why that wasn’t really what you meant." >"Basically, a computer is a very fast moron. It does exactly what you tell it to do, and that can be most humbling." --- >p154 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p154.cpp && ./a.out Please enter temperatures: (enter '|' to stop): High temperature: 0 Low temperature: 0 Average temperature: -nan --- >p154 example code https://rentry.org/PPP2_p154 https://coliru.stacked-crooked.com/a/e76ebab53bdefc92
Open file (138.46 KB 1140x1162 PPP2_p156.png)
>>20694 >"Unfortunately, there are [] errors in [that] program. What would happen if all of the temperatures were below zero? The initialization for high_temp has the equivalent problem to low_temp: high_temp will remain at 0.0 unless there is a higher temperature in the data. This program wouldn’t work for the South Pole in winter either." >"These errors are fairly typical; they will not cause any errors when you compile the program or cause wrong results for “reasonable” inputs." >"However, we forgot to think about what we should consider “reasonable”. Here is an improved program" --- >p156 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p156.cpp && ./a.out Please enter temperatures: (enter '|' to stop): High temperature: -1000 Low temperature: 1000 Average temperature: -nan --- >p156 example code https://rentry.org/PPP2_p156 https://coliru.stacked-crooked.com/a/e436ab6b69b9e1ab
Edited last time by Chobitsu on 02/24/2023 (Fri) 12:43:20.
Open file (118.23 KB 1140x1187 PPP2_p161.png)
>"Occasionally, you will feel that the rules the compiler enforces are stupid and unnecessary (they rarely are) and that things could and ought to be simpler (indeed, but they are not)." >"However, as they say, “a poor craftsman curses his tools.” A good craftsman knows the strengths and weaknesses of his tools and adjusts his work accordingly." >"Here are some common compile-time errors" --- >p161 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p161.cpp && ./a.out --- >p161 example code https://rentry.org/PPP2_p161 https://coliru.stacked-crooked.com/a/f812cd1db7942123
Open file (101.98 KB 1140x962 PPP2_p162a.png)
>>20696 >"When looking for a bug, carefully follow the code statement by statement from the last point that you are sure it was correct. Pretend you’re the computer executing the program. Does the output match your expectations? Of course not, or you wouldn’t be debugging." >"Often, when you don’t see the problem, the reason is that you “see” what you expect to see rather than what you [actually] wrote." --- >p162a command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p162a.cpp && ./a.out --- >p162a example code https://rentry.org/PPP2_p162a https://coliru.stacked-crooked.com/a/4a4f523688cfe4ca
Open file (83.03 KB 1140x887 PPP2_p162b.png)
>>20710 >"Eventually, you’ll learn to use [sophisticated debugging] facilities, but for simple problems and simple programs, you can just temporarily put in a few extra output statements (using cerr) to help you see what’s going on." --- >p162b command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p162b.cpp && ./a.out my_fct(1,2.2) my_fct() returns 0 --- >p162b example code https://rentry.org/PPP2_p162b https://coliru.stacked-crooked.com/a/6c4de5acaa797625
Open file (148.09 KB 1140x1487 PPP2_p163.png)
>"Insert statements that check invariants (that is, conditions that should always hold; see §9.4.3) in sections of code suspected of harboring bugs." >"A statement that states (asserts) an invariant is called an assertion (or just an assert)." --- >p163 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p163.cpp && ./a.out error: bad arguments for mcf --- >p163 example code https://rentry.org/PPP2_p163 https://coliru.stacked-crooked.com/a/8b2b7982a1ecc138
Open file (146.44 KB 1140x1387 PPP2_p164.png)
>>20713 >"The question is just what to do if the pre-condition is violated (doesn’t hold). We basically have two choices: > 1. Ignore it (hope/assume that all callers give correct arguments). > 2. Check it (and report the error somehow). >Looking at it this way, argument types are just a way of having the compiler check the simplest pre-conditions for us and report them at compile time." --- >p164 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p164.cpp && ./a.out main.cpp: In function 'int main()': main.cpp:28:41: error: invalid conversion from 'const char*' to 'int' [-fpermissive] 28 | int x = my_complicated_function(1, 2, "horsefeathers"); | ^~~~~~~~~~~~~~~ | | | const char* main.cpp:17:47: note: initializing argument 3 of 'int my_complicated_function(int, int, int)' 17 | int my_complicated_function(int a, int b, int c) | ~~~~^ --- >p164 example code https://rentry.org/PPP2_p164 https://coliru.stacked-crooked.com/a/efd0502282551205
Open file (160.57 KB 1140x1587 PPP2_p165a.png)
>>20715 >"Writing pre-conditions (even as comments) also has a significant benefit for the quality of your programs: it forces you to think about what a function requires." >"If you can’t state that simply and precisely in a couple of comment lines, you probably haven’t thought hard enough about what you are doing." >"We did mention that we hated debugging; explicitly stating pre-conditions helps in avoiding design errors as well as catching usage errors early." >"Writing [the more complex function] saves you time and grief compared with the apparently simpler [function]" --- >p165a command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p165a.cpp && ./a.out main.cpp: In function 'int main()': main.cpp:36:41: error: invalid conversion from 'const char*' to 'int' [-fpermissive] 36 | int x = my_complicated_function(1, 2, "horsefeathers"); | ^~~~~~~~~~~~~~~ | | | const char* main.cpp:29:47: note: initializing argument 3 of 'int my_complicated_function(int, int, int)' 29 | int my_complicated_function(int a, int b, int c) { | ~~~~^ --- >p165a example code https://rentry.org/PPP2_p165a https://coliru.stacked-crooked.com/a/9ef43fc55973c536
Open file (236.47 KB 1140x2187 PPP2_p165b.png)
>"[The commented-out function here] checks its pre-condition, but it doesn’t state it in the comment (that may be OK for such a short function) and it assumes that the computation is correct (that’s probably OK for such a trivial computation)." >"However, we could be a bit more explicit" >"Pre- and post-conditions provide basic sanity checks in code. As such they are closely connected to the notion of invariants (§9.4.3), correctness (§4.2, §5.2), and testing (Chapter 26)." Stop. Try and understand this example fully, Anon. If you can, then you're well on your way to understanding errors and how to detect them! :^) --- >p165b command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_05/main_p165b.cpp && ./a.out error: area() pre-condition --- >p165b example code https://rentry.org/PPP2_p165b https://coliru.stacked-crooked.com/a/4b423050b038f172
Edited last time by Chobitsu on 02/25/2023 (Sat) 13:43:09.
Open file (73.94 KB 1140x713 PPP2_foo_main.png)
Open file (24.25 KB 1140x438 PPP2_foo_h.png)
Open file (31.86 KB 1140x513 PPP2_foo_cpp.png)
Example code to demonstrate multifile builds using Coliru. >see the mini FAQ explanation ITT if needed (>>18749) note: Remember to clear the command line of each extra file before sharing it, Anon. :^) --- >command line + possible output: ln -s /Archive2/97/69e1b3dc7af21f/main.cpp Foo.h ln -s /Archive2/33/abc01b07a06392/main.cpp Foo.cpp g++ -std=c++20 -O2 -Wall -pedantic Foo.cpp main.cpp && ./a.out ctor'd a Foo --- >example code https://rentry.org/PPP2_foo_main https://rentry.org/PPP2_foo_h https://rentry.org/PPP2_foo_cpp https://coliru.stacked-crooked.com/a/1f5491740d5e0dcd https://coliru.stacked-crooked.com/a/9769e1b3dc7af21f https://coliru.stacked-crooked.com/a/33abc01b07a06392
Open file (107.65 KB 1140x1466 PPP2_calculator_cli.png)
This is a rendition of Bjarne's basic mathematical calculator project into a maintainable format. The project spans two full chapters in the book, and is presented in a very methodical, bottom-up approach to reasoning about how to solve everything step-by-step. The primary focus of the project is to teach you how to parse formal Language Grammars using your new programming skills. It's presented ITT here in advance before those chapters, so that you can 'look ahead' and get an idea where it's all going. If you're ever scratching your head trying to figure out one of the steps (to come), you can always look back here to see how it was solved in the end. BTW, this is a working calculator. Try different entries for the here string arguments at the end of the command line below. >(protip: simply modify what's already given as an example) You can just follow the link below to Coliru and tinker around with things there. Caution As a novice, it's not intended that you understand how all this works yet (though you will before long). For now, its simply posted here as a reference to assist with understanding the answers to some questions that will pop up for you as you work through these 2 chapters of the book. So glance at it if you care to, otherwise just refer back here afterwards as-needed. The textbook's material picks up a couple posts ahead at § 6.1 A problem - p175 (>>21320), so you can just skip over to there instead if you'd like. Cheers. --- >Calculator project command line + possible output: ln -s /Archive2/b4/f1e7d567fd6bd2/main.cpp Calculator.h ln -s /Archive2/68/52ff216ce3687f/main.cpp calc_util.h ln -s /Archive2/56/2e219ca8d64e0b/main.cpp Calculator.cpp ln -s /Archive2/68/b228c371f01ef5/main.cpp calc_util.cpp g++ -std=c++20 -O2 -Wall -pedantic calc_util.cpp Calculator.cpp main.cpp && ./a.out <<< '1+2; 5%8; 2*(3/4-5); q' > = 3 > = 5 > = -8.5 > --- >Calculator project example code https://rentry.org/PPP2_calculator_cli https://coliru.stacked-crooked.com/a/213a22dd10a6f316
Edited last time by Chobitsu on 03/17/2023 (Fri) 20:03:23.
Open file (427.67 KB 1140x3841 PPP2_Calculator_h.png)
Open file (382.10 KB 1140x2941 PPP2_calc_util_h.png)
Edited last time by Chobitsu on 03/12/2023 (Sun) 21:48:08.
Open file (774.33 KB 1140x7491 PPP2_Calculator_cpp.png)
Open file (208.00 KB 1140x2016 PPP2_calc_util_cpp.png)
Edited last time by Chobitsu on 03/12/2023 (Sun) 21:48:32.
Open file (64.47 KB 1140x687 PPP2_p175.png)
>"Writing a program starts with a problem; that is, you have a problem that you’d like a program to help solve." >"Understanding that problem is key to a good program." >"At this stage [of the book], what would be a good program to look at?" >"We chose “Get the computer to do ordinary arithmetic on expressions we type in”; that is, we want to write a simple calculator." --- >p175 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p175.cpp && ./a.out 14.4 --- >p175 example code https://rentry.org/PPP2_p175 https://coliru.stacked-crooked.com/a/32d99c70644a8855
Edited last time by Chobitsu on 03/13/2023 (Mon) 03:47:03.
Open file (68.89 KB 1140x737 PPP2_p178.png)
>"How do we want to interact with the calculator?" >"That’s easy: we know how to use cin and cout, but graphical user interfaces (GUIs) are not explained until Chapter 16, so we’ll stick to the keyboard and a console window." >"Given expressions as input from the keyboard, we evaluate them and write out the resulting value to the screen." --- >p178 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p178.cpp && ./a.out 4 8 0 --- >p178 example code https://rentry.org/PPP2_p178 https://coliru.stacked-crooked.com/a/19ba9c3f6e04adf4
Open file (102.01 KB 1140x1062 PPP2_p179.png)
>"At this point, we are not really ready to write the calculator program." >"We simply haven’t thought hard enough, but thinking is hard work and – like most programmers – we are anxious to write some code." >"So let’s take a chance, write a simple calculator, and see where it leads us." >"This (sort of) works! So what if this program isn’t quite complete? It feels great to get something running! Maybe this programming and computer science stuff is easier than the rumors say." >"Well, maybe, but let’s not get too carried away by an early success." :^) --- >p179 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p179.cpp && ./a.out Please enter expression (we can handle + and –): Result: 0 --- >p179 example code https://rentry.org/PPP2_p179 https://coliru.stacked-crooked.com/a/fcea610bf65a7100
Edited last time by Chobitsu on 03/17/2023 (Fri) 11:33:14.
Open file (182.47 KB 1140x1762 PPP2_p180.png)
>>21325 >"In particular, we know that we should always check that our input is reasonable (in our hurry, we “forgot”) and that testing a value against many constants is best done by a switch-statement rather than an if-statement." >"The “chaining” of operations, such as 1+2+3+4, we will handle by adding the values as they are read; that is, we start with 1, see +2 and add 2 to 1 (getting an intermediate result 3), see +3 and add that 3 to our intermediate result (a 6), and so on." --- Stop If you've been doing really well and have understood everything that's going on so far -- or at least most of it heh -- then proceed through with the next post and so on. OTOH, if you're struggling a bit with things, then I suggest you skip over the next few posts and proceed directly to § 6.5.2.1 Expressions: first try (>>21444). This is where the author begins to methodically work out the solutions for the calculator, moving through things one step at a time. It's a more relaxed pace of things tbh. :^) But please at least read through the book from this point (p 180) to p 197 (where we pick back up)! It's OK if you can't understand it all yet through that section, but it's important to at least get your brain used to seeing the ideas. The reason for all this is that in my effort to make most of the programs over the next few posts actually work, I needed to throw in some already-implemented functions so everything would build & run. This is a lot of new information & complexity that's just kind of dropped right into the novice's lap. I apologize for that necessity. Again, if you're struggling then just skip ahead to the provided crosslink, where we'll all pick back up again. See you there Anon! Cheers. :^) --- >p180 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p180.cpp && ./a.out Please enter expression (we can handle +, –, *, and /) add an x to end expression (e.g., 1+2*3x): terminate called after throwing an instance of 'std::runtime_error' what(): no first operand bash: line 7: 5232 Aborted (core dumped) ./a.out --- >p180 example code https://rentry.org/PPP2_p180 https://coliru.stacked-crooked.com/a/d6111bb450d89ffc
Edited last time by Chobitsu on 03/17/2023 (Fri) 19:25:37.
Open file (158.72 KB 1140x1487 PPP2_p183.png)
>"What should a token look like in our program? In other words, what would we like our Token type to be?" >"A Token must be able to represent operators, such as + and –, and numeric values, such as 42 and 3.14." >"The obvious implementation is something that can represent what “kind” a token is and hold the numeric value for tokens that have one" --- >p183 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p183.cpp && ./a.out 3.14 --- >p183 example code https://rentry.org/PPP2_p183 https://coliru.stacked-crooked.com/a/2aee019423e3b12d
Edited last time by Chobitsu on 03/14/2023 (Tue) 01:50:08.
Open file (109.82 KB 1140x1137 PPP2_p184.png)
>>21327 >"Note that for simple tokens, such as +, we don’t need the value, so we don’t use its value member." >"We needed a character to mean “number” and picked '8' just because '8' obviously isn’t an operator or a punctuation character. Using '8' to mean “number” is a bit cryptic, but it’ll do for now." >"Token is an example of a C++ user-defined type. A user-defined type can have member functions (operations) as well as data members. There can be many reasons for defining member functions." >"Here, we’ll just provide two member functions to give us a more convenient way of initializing Tokens" --- >p184 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p184.cpp && ./a.out + 0 8 11.5 --- >p184 example code https://rentry.org/PPP2_p184 https://coliru.stacked-crooked.com/a/bd0de0fd063c4d5d
Open file (226.23 KB 1140x1912 PPP2_p185.png)
>"How would we use Tokens in the calculator?" >"We can read input into a vector of Tokens" >"we could find the multiply operation by a simple loop" >"Yes, but now what? What do we do with that product d?" --- >p185 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p185.cpp && ./a.out /tmp/ccNN7d2e.o: In function `main': main.cpp:(.text.startup+0x51): undefined reference to `get_token()' collect2: error: ld returned 1 exit status --- >p185 example code https://rentry.org/PPP2_p185 https://coliru.stacked-crooked.com/a/7a76796de26cd2e9
Open file (273.12 KB 1140x2587 PPP2_p188.png)
>"There is a standard answer to the question of how to make sense of expressions:" >"first input characters are read and assembled into tokens (as [] discovered)." >"A token is a sequence of characters that represents something we consider a unit, such as a number or an operator." --- >p188 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p188.cpp && ./a.out <<< '45+11.5/7;' Please enter expression (we can handle +, –, *, and /), then add a ; to print (e.g., 1+2*3;): the Tokens are listed as: t.kind : t.value 8 : 45 + : 0 8 : 11.5 / : 0 8 : 7 --- >p188 example code https://rentry.org/PPP2_p188 https://coliru.stacked-crooked.com/a/dcc8175e6af67d5d
Open file (298.16 KB 1140x2712 PPP2_p189.png)
>>21366 >"How do you read a grammar? Basically, given some input, you start with the “top rule,” Expression, and search through the rules to find a match for the tokens as they are read." >"Reading a stream of tokens according to a grammar is called parsing, and a program that does that is often called a parser or a syntax analyzer." >"Our parser reads the tokens from left to right, just like we type them and read them." >"Let’s try something really simple: Is 2 an expression?" >"yes, according to our grammar, 2 is an expression. We can illustrate the progression through the grammar [with the parsing tree given.]"' --- >p189 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p189.cpp && ./a.out 2 --- >p189 example code https://rentry.org/PPP2_p189 https://coliru.stacked-crooked.com/a/01d2f651e3a2560c
Edited last time by Chobitsu on 03/15/2023 (Wed) 00:24:25.
Open file (383.63 KB 1140x3562 PPP2_p191.png)
>>21375 >"Let’s try something a bit more complicated: Is 2+3 an Expression? Naturally, much of the reasoning is the same as for 2" >"Again, we can illustrate this reasoning graphically (leaving out the floating-point literal to Number rule to simplify)" >"[So yes,] an Expression followed by + followed by a Term is an Expression." >"The real reason we are interested in grammars is that they can solve our problem of how to correctly parse expressions"' --- >p191 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p191.cpp && ./a.out <<< '2+3;' enter: 2+3; 5 --- >p191 example code https://rentry.org/PPP2_p191 https://coliru.stacked-crooked.com/a/63d9276ea3015320
Edited last time by Chobitsu on 03/17/2023 (Fri) 20:10:54.
Open file (572.32 KB 1140x4837 PPP2_p192.png)
>>21403 >"Is 45+11.5*7 an Expression?" >"In particular, it is an Expression that first does the multiplication 11.5*7 [(via the Term*Primary rule),] and then the addition 45+[80.5], just as if we had written 45+(11.5*7)." >"[So yes,] an Expression followed by + followed by a Term*Primary is an Expression." >"we were not really trying [here] to teach you to understand 2+2 or 45+11.5*7. Obviously, you knew that already."' >"We were trying to find a way for the computer to “understand” 45+11.5*7 and all the other complicated expressions you might give it to evaluate." --- >p192 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p192.cpp && ./a.out <<< '45+11.5*7;' enter: 45+11.5*7; 125.5 --- >p192 example code https://rentry.org/PPP2_p192 https://coliru.stacked-crooked.com/a/2a836369dcc3989e
Open file (590.91 KB 1140x5962 PPP2_p193.png)
>"If you have never before worked with grammars, we expect that your head is now spinning." >"In fact, it may be spinning even if you have seen a grammar before, but take a look at the [provided] grammar for a very small subset of English" >"A sentence is built from parts of speech (e.g., nouns, verbs, and conjunctions)." >"A sentence can be parsed according to these rules to determine which words are nouns, verbs, etc." --- >p193 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p193.cpp && ./a.out <<< 'birbs fly but fish swim ;' enter: birbs fly but fish swim ; (leave a space before ;) n birbs v fly c but n fish v swim sentence: birbs fly but fish swim ; --- >p193 example code https://rentry.org/PPP2_p193 https://coliru.stacked-crooked.com/a/b65dc739966c68c0
Open file (517.63 KB 1140x5237 PPP2_p195.png)
>"How did we pick those expression grammar rules?" >"“Experience” is the honest answer. The way we do it is simply the way people usually write expression grammars." >"However, writing a simple grammar is pretty straightforward" >"We simply put tokens in (double) quotes and start with the first rule. Alternatives are put on separate lines." --- >p195 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p195.cpp && ./a.out <<< '{A, A, A, A, B}' enter: {A, A, A, A, B} { A, A, A, A, B } : this is a valid list --- >p195 example code https://rentry.org/PPP2_p195 https://coliru.stacked-crooked.com/a/d47677084806904d
Edited last time by Chobitsu on 03/17/2023 (Fri) 07:41:45.
Open file (233.83 KB 1140x1712 PPP2_p197.png)
>"To implement our calculator, we need four functions: one to read tokens plus one for each rule in our grammar:" >"Let’s first write expression()." >"Since this is our first attempt to turn a set of grammar rules into code, we’ll proceed through a couple of false starts. That’s the way it usually goes with new techniques, and we learn useful things along the way." >"In particular, a novice programmer can learn a lot from looking at the dramatically different behavior of similar pieces of code. Reading code is a useful skill to cultivate." --- >p197 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p197.cpp && ./a.out main.cpp: In function 'double expression()': main.cpp:35:8: warning: infinite recursion detected [-Winfinite-recursion] 35 | double expression() { | ^~~~~~~~~~ main.cpp:36:27: note: recursive call 36 | double left = expression(); // read and evaluate an Expression | ~~~~~~~~~~^~ /tmp/ccDIgtqr.o: In function `expression()': main.cpp:(.text+0x10): undefined reference to `get_token()' main.cpp:(.text+0x31): undefined reference to `term()' main.cpp:(.text+0x51): undefined reference to `term()' collect2: error: ld returned 1 exit status --- >p197 example code https://rentry.org/PPP2_p197 https://coliru.stacked-crooked.com/a/c5a4d33f0784f7a9
Open file (234.26 KB 1140x1737 PPP2_p198.png)
>"In fact, this expression() will never get beyond its first line: expression() starts by calling expression() which starts by calling expression() and so on “forever.”" >"This is called an infinite recursion and will in fact terminate after a short while when the computer runs out of memory to hold the “never-ending” sequence of calls of expression()." >"The term recursion is used to describe what happens when a function calls itself. Not all recursions are infinite, and recursion is a very useful programming technique (see §8.5.8)." >"So what do we do? Every Term is an Expression, but not every Expression is a Term; that is, we could start looking for a Term and look for a full Expression only if we found a + or a –." --- >p198 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p198.cpp && ./a.out /tmp/cceRLSTF.o: In function `expression()': main.cpp:(.text+0x5): undefined reference to `term()' main.cpp:(.text+0x10): undefined reference to `get_token()' collect2: error: ld returned 1 exit status --- >p198 example code https://rentry.org/PPP2_p198 https://coliru.stacked-crooked.com/a/f5188f612b4533c5
Open file (223.33 KB 1140x1787 PPP2_p199.png)
>"So we got a very nice program that just didn’t do the right thing. That’s dangerous." >"It is especially dangerous because it gives the right answer in many cases. For example, 1+2+3 gives the right answer (6) because 1+(2+3) equals (1+2)+3." >"What fundamentally, from a programming point of view, did we do wrong? We should always ask ourselves this question when we have found an error. That way we might avoid making the same mistake again, and again, and again." >"Fundamentally, we just looked at the code and guessed. That’s rarely good enough!" >"So, what now?" >"Look again at the grammar (the correct grammar in §6.5.2): any Expression starts with a Term and such a Term can be followed by a + or a –. So, we have to look for a Term, see if it is followed by a + or a –, and keep doing that until there are no more plusses or minuses." --- >p199 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p199.cpp && ./a.out /tmp/ccFvCha2.o: In function `expression()': main.cpp:(.text+0x5): undefined reference to `term()' main.cpp:(.text+0x10): undefined reference to `get_token()' main.cpp:(.text+0x25): undefined reference to `term()' main.cpp:(.text+0x3a): undefined reference to `get_token()' main.cpp:(.text+0x43): undefined reference to `term()' collect2: error: ld returned 1 exit status --- >p199 example code https://rentry.org/PPP2_p199 https://coliru.stacked-crooked.com/a/6812e3612948b70b
Edited last time by Chobitsu on 03/31/2023 (Fri) 12:14:00.
Open file (226.35 KB 1140x1862 PPP2_p200.png)
>>21636 >"This is a bit messier: we had to introduce a loop to keep looking for plusses and minuses. We also got a bit repetitive: we test for + and – twice and twice call get_token()." >"Because it obscures the logic of the code, let’s just get rid of the duplication of the test for + and –" >"What we have done is to remove the mention of expression() within expression() and replace it with a loop. In other words, we translated the Expression in the grammar rules for Expression into a loop looking for a Term followed by a + or a –." --- >p200 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p200.cpp && ./a.out /tmp/ccQYnbix.o: In function `expression()': main.cpp:(.text+0x5): undefined reference to `term()' main.cpp:(.text+0x10): undefined reference to `get_token()' main.cpp:(.text+0x31): undefined reference to `term()' main.cpp:(.text+0x49): undefined reference to `term()' collect2: error: ld returned 1 exit status --- >p200 example code https://rentry.org/PPP2_p200 https://coliru.stacked-crooked.com/a/3fe7fdbfd496ad2d
Open file (266.64 KB 1140x2462 PPP2_p201.png)
>"The grammar rule for Term is very similar to the Expression rule consequently, the code should be very similar also." >"Unfortunately, this doesn’t compile: the remainder operation (%) is not defined for floating-point numbers." >"we could simply leave % out of our calculator. Let’s take the simplest choice for now." >"However, an experienced programmer will notice an undesirable detail that makes [this version of] term() unacceptable. What would happen if you entered 2/0?" --- >p201 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p201.cpp && ./a.out /tmp/ccdJLsdO.o: In function `term()': main.cpp:(.text+0x5): undefined reference to `primary()' main.cpp:(.text+0x10): undefined reference to `get_token()' main.cpp:(.text+0x31): undefined reference to `primary()' main.cpp:(.text+0x49): undefined reference to `primary()' /tmp/ccdJLsdO.o: In function `expression()': main.cpp:(.text+0x70): undefined reference to `get_token()' collect2: error: ld returned 1 exit status --- >p201 example code https://rentry.org/PPP2_p201 https://coliru.stacked-crooked.com/a/d5a29d12c851f072
Open file (293.61 KB 1140x2962 PPP2_p202.png)
>>21662 >"You can’t divide by zero." >"If you try, the computer hardware will detect it and terminate your program with a somewhat unhelpful error message." >"So, we’d better check and give a decent error message" >"Why did we put the statements handling / into a block? The compiler insists." >"If you want to define and initialize variables within a switch-statement, you must place them inside a block." --- >p202 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p202.cpp && ./a.out /tmp/cc4ZfTd7.o: In function `term()': main.cpp:(.text+0x7): undefined reference to `primary()' main.cpp:(.text+0x12): undefined reference to `get_token()' main.cpp:(.text+0x31): undefined reference to `primary()' main.cpp:(.text+0x49): undefined reference to `primary()' /tmp/cc4ZfTd7.o: In function `expression()': main.cpp:(.text+0x80): undefined reference to `get_token()' collect2: error: ld returned 1 exit status --- >p202 example code https://rentry.org/PPP2_p202 https://coliru.stacked-crooked.com/a/c6d3a7d9cc585a10
Open file (348.21 KB 1140x3537 PPP2_p203a.png)
>"The grammar rule for primary expressions is also simple" >"The code that implements it is a bit messy because there are more opportunities for syntax errors" >"Basically there is nothing new compared to expression() and term(). We use the same language primitives, the same way of dealing with Tokens, and the same programming techniques." --- >p203a command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p203a.cpp && ./a.out /tmp/ccFR2TxI.o: In function `term()': main.cpp:(.text+0x11): undefined reference to `get_token()' /tmp/ccFR2TxI.o: In function `expression()': main.cpp:(.text+0xb0): undefined reference to `get_token()' /tmp/ccFR2TxI.o: In function `primary()': main.cpp:(.text+0x106): undefined reference to `get_token()' main.cpp:(.text+0x12c): undefined reference to `get_token()' collect2: error: ld returned 1 exit status --- >p203a example code https://rentry.org/PPP2_p203a https://coliru.stacked-crooked.com/a/a51235c6a0466ffb
Open file (351.27 KB 1140x3812 PPP2_p203b.png)
>"To run these calculator functions, we need to implement get_token() and provide a main()." >"The main() is trivial: we just keep calling expression() and printing out its result:" >"Unsurprisingly, this first version of the calculator doesn’t work quite as we expected." >"So we shrug and ask, “Why not?” or rather, “So, why does it work the way it does?” and “What does it do?”" --- >p203b command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p203b.cpp && ./a.out Bad token --- >p203b example code https://rentry.org/PPP2_p203b https://coliru.stacked-crooked.com/a/7ed96546edbce5d9
Open file (487.61 KB 1140x5087 PPP2_p206.png)
>>21666 >"When the Token returned by get_token() is not a + or a – we just return. We don’t use that token and we don’t store it anywhere for any other function to use later." >"That’s not smart. Throwing away input without even determining what it is can’t be a good idea." >"A quick look shows that term() has exactly the same problem. That explains why our calculator ate two tokens for each that it used. Let us modify expression() so that it doesn’t “eat” tokens. In addition, we must make the same change to term()" >"Where would we put that next token (t) when the program doesn’t need it?" >"What we want is an input stream that deals with tokens and that you can put an already read token back into. [This is our new user-defined type 'Token_stream'.]" --- >p206 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p206.cpp && ./a.out Bad token --- >p206 example code https://rentry.org/PPP2_p206 https://coliru.stacked-crooked.com/a/38205c2eab3a413d
Open file (510.94 KB 1140x5412 PPP2_p209.png)
>"We still have a token-look-ahead problem. However, this time the problem is not that our code “eats” characters, but that it doesn’t get any output for an expression until we enter the following expression." >"The result of an expression isn’t printed immediately; the output is postponed until the program has seen the first token of the next expression. Unfortunately, the program doesn’t see that token until we hit Return after the next expression." >"How can we fix this? One obvious solution is to require a “print command.” [;]" >"And while we are at it, let’s add an “exit command” to allow for graceful exit. [q]" --- >p209 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p209.cpp && ./a.out Bad token --- >p209 example code https://rentry.org/PPP2_p209 https://coliru.stacked-crooked.com/a/718d593d8109280a
Open file (227.73 KB 1140x1737 PPP2_p210.png)
>"Before further improving our calculator, let us show the implementation of Token_stream. After all, nothing – nothing at all – works until we get correct input." >"What we need is something that reads characters from the standard input, cin, and presents the program with the next token when it asks for it." >"In addition, we saw that we – that is, our calculator program – often read a token too many, so that we must be able to put it back for later use." >"A C++ user-defined type often consists of two parts: the public interface (labeled public:) and the implementation details (labeled private:)." >"The idea is to separate what a user of a type needs for convenient use from the details that we need in order to implement the type, but that we’d rather not have users mess with" --- >p210 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p210.cpp && ./a.out /tmp/ccY9zXib.o: In function `main': main.cpp:(.text.startup+0xa): undefined reference to `Token_stream::Token_stream()' main.cpp:(.text.startup+0x14): undefined reference to `Token_stream::get()' main.cpp:(.text.startup+0x20): undefined reference to `Token_stream::putback(Token)' collect2: error: ld returned 1 exit status --- >p210 example code https://rentry.org/PPP2_p210 https://coliru.stacked-crooked.com/a/0baf473ece0f52b9
Open file (216.51 KB 1140x2137 PPP2_p211.png)
>"Now, we need to implement those three Token_stream functions." >"How do we represent a Token_stream? That is, what data do we need to store in a Token_stream for it to do its job?" >"we just need space for one Token and an indicator of whether that space is full or empty" --- >p211 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p211.cpp && ./a.out --- >p211 example code https://rentry.org/PPP2_p211 https://coliru.stacked-crooked.com/a/8498de946abde6ba
Open file (292.09 KB 1140x2887 PPP2_p212.png)
>"All the real work is done by get()." >"If there isn’t already a Token in Token_stream::buffer, get() must read characters from cin and compose them into Tokens" >" " --- >p212 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p212.cpp && ./a.out --- >p212 example code https://rentry.org/PPP2_p212 https://coliru.stacked-crooked.com/a/344d4baf5da95971
Open file (309.73 KB 1140x3112 PPP2_p214.png)
>"Now we just have to deal with numbers. That’s actually not that easy." >"We could spend hours or days to get this right, but fortunately, we don’t have to. Input streams know what C++ literals look like and how to turn them into values of type double." >"All we have to do is to figure out how to tell cin to do that for us inside get()" >"instead of doing any messy arithmetic, we just put the initial [numeric] character back into cin, and then let cin read the [entire] number [in all at once]." --- >p214 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p214.cpp && ./a.out --- >p214 example code https://rentry.org/PPP2_p214 https://coliru.stacked-crooked.com/a/290b4884b4a254e5
Open file (474.66 KB 1140x5362 PPP2_p215.png)
>"Sometimes, the proverb says, it’s hard to see the forest for the trees. Similarly, it is easy to lose sight of a program when looking at all its functions, classes, etc." >"So, let’s have a look at the program with its details omitted" note: within Coliru, you can collapse functions to look similar to the book's example given. >"The order of the declarations is important. You cannot use a name before it has been declared, so ts must be declared before ts.get() uses it, and error() must be declared before the parser functions because they all use it." >"There is an interesting loop in the call graph: expression() calls term() which calls primary() which calls expression()." >"We chose to declare (“forward declare”) expression()." Stay strong That's it for chapter 6, and we're now more than halfway complete with the project. I know that was a lot to take in Anon, but we'll wrap everything up for out calculator project in the next chapter. BTW, you do want your waifu to be able to do arithmetic for you Anon, right? :^) Stay tuned! --- >p215 command line + possible output: g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p215.cpp && ./a.out <<< '2+2;q' = 4 primary expected --- >p215 example code https://rentry.org/PPP2_p215 https://coliru.stacked-crooked.com/a/f8eec99cc12c5093

Report/Delete/Moderation Forms
Delete
Report