ICS 45C Spring 2022
Exercise Set 1

Due date and time: Wednesday, April 13, 11:59pm


Getting started

First of all, be sure that you've read the Reinforcement Exercises page, which explains everything you'll need to know, generally, about how the reinforcement exercises will work this quarter. Make sure you read that page before you continue with this one.

Before you begin work on these reinforcement exercises, there's a chore that you'll need to complete on your ICS 45C VM to get it set up to proceed.

Refreshing your ICS 45C VM environment

Even if you previously downloaded your ICS 45C VM, you will probably need to refresh its environment before proceeding with these exercises. Log into your VM and issue the command ics45c version to see what version of the ICS 45C environment you currently have stored on your VM. Note, in particular, the timestamp; if you see a version with a timestamp older than the one listed below, you'll need to refresh your environment by running the command ics45c refresh to download the latest one before you proceed with these exercises.

2022-04-06 19:52:05
Exercise Set 1 template added

If you're unable to get outgoing network access to work on the ICS 45C VM — something that afflicts a handful of students each quarter — then the ics45c refresh command won't work, but an alternative approach is to download the latest environment from the link below, then to upload the file on to your ICS 45C VM using SCP. (See the Project #0 write-up for more details on using SCP.) Once the file is on your VM, you can run the command ics45c refresh_local NAME_OF_ENVIRONMENT_FILE, replacing NAME_OF_ENVIRONMENT_FILE with the name of the file you uploaded; note that you'd need to be in the same directory where the file is when you run the command.

Creating your project directory on your ICS 45C VM

A project template has been created specifically for this set of exercises, containing a similar structure to the basic template you saw in Project #0. Among other things, it contains a version of the gather script that's different from the ones in the projects, so you'll absolutely need to use the set1 template for these exercises, as opposed to the basic one.

Decide on a name for your project directory, then issue the command ics45c start YOUR_CHOSEN_PROJECT_NAME set1 to create your new project directory using the set1 template. (For example, if you wanted to call your project directory set1, you would issue the command ics45c start set1 set1.)

A word about organizing your answers

Please do not copy and paste the problem (or portions of the problem) into the answer you submit. We are well aware of what question you're asking, so copying and pasting the problem simply slows us down when grading your work. Consequently, we will be deducting points when problems are copied and pasted into solutions.


Problem 1 (2 points)

The term language processor is often used to describe a tool whose input and output are computer programs. A C++ compiler is an example of such a tool; its job is to take portions of a C++ program (one source file at a time) as input and emit a new, equivalent portion of code in some other language (usually some form of machine code for a particular processor). But compilers are by no means the only language processors; there are also tools whose job is to reorganize code, reformat it, optimize it, display it using colors and allow it to be edited, and so on. While the details of implementing a language processor lie firmly outside of the scope of this course, let's think about them at a high level, so we can understand a little more about the problem a C++ compiler faces.

Early on, when we were discussing C++ Basics, we saw that there are three different kinds of loops offered by C++: the while loop, the do .. while loop, and the classic for loop. (There's at least one more kind of loop that we've not yet seen, but other kinds of loops are not germane here.) We've also seen that these three kinds of loops are somewhat interchangeable, that if you know how to use one of them, you could accomplish everything provided by the others; however, the reason that all three of them exist is because each more cleanly expresses a commonly-occurring looping pattern than the others can.

Now let's suppose that there's a programming language called C+-, which is exactly the same as C++ except that the only one of these three loops that's available is the while loop. Suppose, too, that you're implementing a language processor whose job is to translate C++ code into C+- code — which is to say that it needs to leave everything as-is except that it needs to convert do .. while loops and classic for loops to while loops instead. Your goal in this problem is to propose a strategy for doing that, by answering two questions:

To be clear, we're not asking you to implement a translator here; we're asking you to consider what output you would expect from a hypothetical translator given certain inputs.

What to submit

Add one PDF file to your problems directory with this name: problem1.pdf, which contains your strategies for converting loops.


Problem 2 (1 point)

In the Course Introduction, we discussed a few of the overarching design goals of C++. This wasn't just dull history. When you learn a programming language, one thing you must eventually understand is why the language was designed the way it was, not just because you're curious, but because it increases your ability to learn the parts of the language you've not yet seen, as well as helping you to remember the details of the parts you haven't seen in a while; if you understand the "why," you can quite often infer the "what" even if you haven't seen it (or have forgotten it).

In our conversation about Strings, we saw that there are two ways to "index" into a string (i.e., to fetch or change one of its characters): the [ ] operator and a member function called at(). At first blush, they appear to be two different syntaxes for accomplishing the same goal, but, as we've seen, they're actually subtly different.

Which of the key design goals of C++ is the reason why these two ways to index a string were designed in the way they were? In other words, why are there two different ways to index into a string? Since they're different, why is [ ] the way it is and at() is the way it is, as opposed to them being the other way around? In a couple of sentences, briefly explain your answer.

What to submit

Add one PDF file to your problems directory with this name: problem2.pdf, which contains your answer to this question.


Problem 3 (3 points)

Write a C++ function with the following signature:

void readAndConvert()

The function takes no parameters and returns no value. Instead, it reads its input from std::cin and writes its output to std::cout. Both the input and output are information describing a sequence of stock trades, albeit in different formats.

Input format

The input will be formatted according to the following specification. You may freely assume that the input will be in the format described here; it doesn't matter what your function does with input that doesn't meet those requirements.

One example input that follows that format is as follows, though your function would need to work on any input that follows the specification, not just the one example.

4
BOO
Forever Boo Enterprises
bqrzxfq 50.00 100
hhpncstvz 60.75 200
cjjm 7.90 150
frqyzvt 100.15 175

Output format

Your function's output is a reorganization of the information from the input, which you would write in the following format.

The correct output for the example input above is as follows.

BOO (Forever Boo Enterprises)
[bqrzxfq] 5000
[hhpncstvz] 12150
[cjjm] 1185
[frqyzvt] 17526

It is irrelevant whether your function prints all of the output only after reading the input, or whether it prints the output while it reads input; this is your choice. The only requirement is that your output meets the formatting requirements.

What to submit

Add one C++ source file to your problems directory with this name: problem3.cpp, which contains the definition of your function.


Problem 4 (2 points)

We've seen that when we write programs that consist of more than one C++ source file, a technique called Separate Compilation is used to compile and link them. One key piece of advice that we discussed is that functions ought to be defined in source files, while the declarations of those functions (but never their definitions) sometimes also appear in corresponding header files. Let's check your understanding of why that advice was so important. It's one thing to know a pattern and follow it, but it's substantially better to understand why the pattern is there, so that when we start to encounter issues and when we start to realize that there exceptions to the rule, we'll be able to figure out why. To check your understanding, answer two questions about header and source files.

What to submit

Add one PDF file to your problems directory with this name: problem4.pdf, which contains your answer to these questions.


Problem 5 (2 points)

In our conversation about what goes on Behind the Scenes of a C++ program, we learned some details of how variables, control structures, and functions are implemented. While that sounds like a matter of curiosity, it's not; understanding what our code actually means behind the scenes is vitally important, particularly in a language like C++, where we'll find we have so many design choices available to us, even when we're doing seemingly simple things like deciding where and how to store a value in memory. If we have no understanding of how our C++ code runs on our underlying machine, we'll have no means to make the distinctions that C++ asks us to make in our designs.

To calibrate your understanding of the implementation of variables, control structures, and functions, let's consider one kind of design choice and assess the impact these implementation-level details have on the performance of a hypothetical program in which we've made that choice.

In prerequisite coursework, you've no doubt seen that there are two fundamental ways to achieve repetition in a computer program (i.e., to do the same thing repeatedly without having to write the code over and over again). One common way to solve that problem is to use a loop. Another common way is to use recursion. For the most part, anything you can write using a loop, you can also write using recursion; going the other way can be trickier, as it turns out. So, if recursion is the more flexible option, it's worth considering why we find ourselves using loops in C++ so often.

Suppose that you're implementing a straightforward looping algorithm — say, finding the maximum value in a collection or printing n copies of the same text to std::cout. Now suppose that you instead solved the same problem recursively. (So, in other words, we're talking about a problem that could be solved relatively simply either way.) Answer the following questions about the two design choices.

What to submit

Add one PDF file to your problems directory with this name: problem5.pdf, which contains your answer to these questions.


Deliverables

In Canvas, you'll find a separate submission area for each problem. Submit your solution to each problem into the appropriate submission area. Be sure that you're submitting the correct file into the correct area (i.e., submitting your Problem 1 solution to the area for Problem 1, and so on). Under no circumstances will we offer credit for files submited in the incorrect area.

Submit each file as-is, without putting it into a .tar.gz file or arranging it in any other way. (There is a gather script in the set1 template, but there's no need to use it.) If we asked for a PDF, for example, all we want is a PDF; no more, no less. If you submit something other than what we asked for, we will not be offering you any credit on the submission. There are no exceptions to this rule.

Of course, you should also be aware that you're responsible for submitting precisely the version of your work that you want graded. We won't regrade an exercise simply because you submitted the wrong version accidentally, and we won't be able to offer any credit on exercises that you forgot to submit.

Can I submit after the deadline?

Unlike some of the projects in this course, the reinforcement exercises cannot be submitted after the deadline; there is no late policy for these. Each is worth only 3% of your grade (and the lowest score doesn't count), so it's not a disaster if you miss one of them along the way.

What do I do if Canvas slightly adjusts my filename?

Canvas will sometimes modify your filenames when you submit them (e.g., when you submit the same file twice, it will change the name of your second submission to end in -1.tar.gz instead of just .tar.gz). In general, this is fine; as long as the file you submitted has the correct name, we'll be able to obtain it with that same name, even if Canvas adjusts it.

Can I work on this outside of the VM?

Yes, but be aware that you must submit the files in the appropriate format, and that any C++ code you submit must compile and run on the ICS 45C VM.