程序代写 CS 136 Winter 2022 03: Imperative C 1

Introduction to Imperative C
Optional Textbook Readings: CP:AMA 2.4, 3.1, 4.2–4.5, 5.2, 10
• the ordering of topics is different in the text
• some portions of the above sections have not been covered yet

Copyright By PowCoder代写 加微信 powcoder

• some previously listed sections have now been covered in more detail
The primary goal of this section is to be able to write programs that use I/O and mutation.
CS 136 Winter 2022 03: Imperative C 1

Functional programming
In CS 135 we used the functional programming paradigm:
• functions are “pure” (a.k.a. “mathematical”):
– functions only return values
– return values only depend on argument values
• only constants are used
In the imperative programming paradigm functions may be
“impure” and we will use variables.
A programming paradigm can also be thought of as a
programming “approach”, “philosophy” or “style”.
CS 136 Winter 2022 03: Imperative C 2

Compound statement
In English, an imperative is an instruction: “Give me your money!”
In imperative programming, a sequence of instructions (or “statements”) are executed. We have already seen this:
int main(void) {
trace_int(1 + 1);
assert(3 > 2);
// do this first
// then do this
// and then do this
A block {} is formally known as a compound statement, which is
simply a sequence of statements† (to be executed in order).
† Blocks can also contain local variable definitions.
CS 136 Winter 2022 03: Imperative C 3

Imperative programming
A program is mostly a sequence of statements to be executed. Control flow is used to change the order of statements (Section 04).
The most significant difference between the functional and imperative paradigms is:
Imperative programming uses side effects (functional programming does not).
In this section we explore side effects, beginning with output.
CS 136 Winter 2022 03: Imperative C 4

I/O (Input/Output) is the term used to describe how programs
interact with the “real world”.
A program (“app”) on your phone may interact with you in many
different ways:
Input: touch screen (onscreen keyboard), voice, camera Output: screen (display), sounds, vibrations
It may also interact with non-human entities:
files, printers, GPS, other computers on the internet
In this course, we only use simple text-based I/O.
CS 136 Winter 2022 03: Imperative C 5

To display text output in C, we use the printf function.
// My first program with I/O
#include “cs136.h”
int main(void) {
printf(“Hello, World”);
Hello, World
printf is different than the tracing tools we use to debug and informally test our code (more on this distinction later).
CS 136 Winter 2022 03: Imperative C 6

int main(void) {
printf(“Hello, World”);
printf(“C is fun!”);
Hello, WorldC is fun!
The newline character (\n) is necessary to properly format output to appear on multiple lines.
printf(“Hello, World\n”);
printf(“C is\nfun!\n”);
Hello, World
CS 136 Winter 2022
03: Imperative C 7

The first parameter of printf is a “string”.
To output values, use a format specifier (the f in printf) within the
string and provide an additional argument.
For an integer in “decimal format” the format specifier is “%d”.
printf(“2 plus 2 is: %d\n”, 2 + 2);
2 plus 2 is: 4
In the output, the format specifier is replaced by the additional argument value.
Strings are introduced in Section 09.
CS 136 Winter 2022 03: Imperative C 8

There can be multiple format specifiers, each requiring an additional argument.
printf(“%d plus %d is: %d\n”, 2, 10 / 5, 2 + 2);
2 plus 2 is: 4
To output a percent sign (%), use two (%%).
printf(“I am %d%% sure you should watch your”, 100);
printf(“spacing!\n”);
I am 100% sure you should watch yourspacing!
Similarly,
• to print a backslash (\), use two (\\)
• to print a quote (“), add an extra backslash (\”)
CS 136 Winter 2022 03: Imperative C 9

Many computer languages have a printf function and use the same format specifier syntax as C.
The full C printf format specifier syntax controls the format and alignment of output.
printf(“4 digits with zero padding: %04d\n”, 42);
4 digits with zero padding: 0042
See CP:AMA 22.3 for more details.
In this course, simple “%d” formatting is usually sufficent.
CS 136 Winter 2022 03: Imperative C 10

Functions with side effects
Consider the two functions below:
int sqr(int n) {
return n * n;
int noisy_sqr(int n) {
printf(“Yo! I’m squaring %d!\n”, n);
return n * n;
Both functions return the same value.
However, noisy_sqr does more than return a value. In addition to returning a value, it also produces output. noisy_sqr has a side effect.
CS 136 Winter 2022 03: Imperative C 11

Side effects and state (introduction)
In general, a programming side effect is when the state of something “changes”.
State refers to the value of some data (or “information”) at a moment in time.
Consider the following “real world” example: You have a blank piece of paper, and then you write your name on that paper.
You have changed the state of that paper: at one moment it was blank, and in the next it was “autographed”.
In other words, the side effect of writing your name was that you changed the state of the paper.
CS 136 Winter 2022 03: Imperative C 12

Documenting side effects
The printf function has a side effect: it changes the output (or “display”).
By calling printf, the function noisy_sqr also has a side effect. Clearly communicate if a function has a side effect.
// noisy_sqr(n) computes n^2
// effects: produces output
int noisy_sqr(int n) {
printf(“Yo! I’m squaring %d!\n”, n);
return n * n;
Add an effects: section to document any side effects.
CS 136 Winter 2022 03: Imperative C 13

If a side effect occurs conditionally, add the word “may”:
// noisy_abs(n) computes |n|
// effects: may produce output
int noisy_abs(int n) {
if (n < 0) { printf("Yo! I'm changin' the sign!\n"); return -n; return n; } In this course, there is no need to provide any detail in the “effects:” section ( // effects: produces output is sufficient). Occasionally, you may want to describe the output in the purpose (e.g., understanding the output is essential to understanding the core behaviour of the function). CS 136 Winter 2022 03: Imperative C 14 Debugging tools Statements used for debugging and informal testing (e.g., assert, trace_int) are not considered side effects. Do not document asserts or tracing in the “effects:” section. Feel free to leave your tracing code in your assignments: they will not affect your test results. Large software projects often have thousands of assert and tracing statements to aid debugging. They are usually disabled (or “turned off”) when a project is finalized to improve performance, but they remain in the code. CS 136 Winter 2022 03: Imperative C 15 I/O terminology In the context of I/O, be careful with terminology. int sqr(int n) { return n * n; Informally, someone might say: “if you input 7 into sqr, it outputs 49” . This is poor terminology: sqr does not read input and does not print any output. Instead, say: “if 7 is passed to sqr, it returns 49”. CS 136 Winter 2022 03: Imperative C 16 int noisy_sqr(int n) { printf("Yo! I'm squaring %d!\n", n); return n * n; For noisy_sqr, say: “if 7 is passed to noisy_sqr, it outputs a message and returns 49”. It is common for beginners to confuse output (e.g., via printf) and the return value. Ensure you understand the correct terminology and read your assignments carefully. CS 136 Winter 2022 03: Imperative C 17 Testing I/O asserts can test that sqr and noisy_sqr return the correct values: int main(void) { assert(sqr(-3) == 9); assert(sqr(7) == 49); assert(noisy_sqr(-3) == 9); assert(noisy_sqr(7) == 49); But assert cannot be used to test that noisy_sqr produces the correct output. We will need a new method to test output... CS 136 Winter 2022 03: Imperative C 18 Seashell: [RUN] vs. [I/O TEST] In Seashell there are two ways of “running” a program. The only difference is the I/O behaviour: • With the [RUN] button, input is read from the keyboard. Any output is displayed in the console (“screen”). • With the [I/O TEST] button, input is read from input file(s) (e.g., testfile.in) instead of the keyboard. If a corresponding output test file exists (e.g., testfile.expect), Seashell checks the output against the expected output test file to see if they match. CS 136 Winter 2022 03: Imperative C 19 example: I/O test int noisy_sqr(int n) { printf("Yo! I'm squaring %d!\n", n); return n * n; int main(void) { assert(noisy_sqr(-3) == 9); assert(noisy_sqr(7) == 49); test1.expect: Yo! I'm squaring -3! Yo! I'm squaring 7! A blank test1.in would also be necessary (I/O tests always require an .in file). CS 136 Winter 2022 03: Imperative C 20 Our tracing tools print to a different output stream than printf (like writing on two different pieces of paper). By default, printf outputs to the stdout (standard output) stream. Our tracing tools output to the stderr (standard error) stream, which is used for errors and other diagnostic messages. In Marmoset, and when Seashell performs an [I/O TEST], only the stdout stream is tested. When you [RUN] your code, the two streams may appear mixed together in the screen (console) output. CS 136 Winter 2022 03: Imperative C 21 void functions noisy_sqr has a side effect and returns a value. A function may only have a side effect, and no return a value. The void keyword is used to indicate a function returns “nothing”. // display_score(score, max) displays the player score // effects: produces output void display_score(int score, int max) { printf("your score is %d out of %d.\n", score, max); return; // optional In a void function, the return is optional and has no expression (when the end of a void function is reached, it returns automatically). CS 136 Winter 2022 03: Imperative C 22 printf return value Surprisingly, printf is not a void function (it returns an int). printf returns the number of characters printed. printf("hello!\n") returns 7 (\n is a single character). In the following code, where does the 7 “go”? int main(void) { printf("hello!\n"); Let’s revisit what a statement is... CS 136 Winter 2022 03: Imperative C 23 Expression statements The following expressions all have a value of 11: sqr(6) - sqr(5) printf("expression\n") printf("five\n") + 6 An expression statement is an expression with a semicolon (;). int main(void) { sqr(6) - sqr(5); printf("expression\n"); printf("five\n") + 6; What happens to all of those elevens? CS 136 Winter 2022 03: Imperative C 24 The value of an expression statement is discarded after it is executed. The purpose of an expression statement is to generate side effects. Imperative programming is “programming by side effects”. Seashell will give a warning if an expression statement obviously has no side effect: 8 + 1;. If an expression contains a function call there is no warning because side effects are “assumed” (even if there are none). CS 136 Winter 2022 03: Imperative C 25 Statements There are only three types of C statements: • compound statements (blocks) {} a sequence of statements (to be executed in order) • expression statements for generating side effects (values are discarded) • control flow statements control the order in which other statements are executed (e.g., return, if and else) We discuss control flow in more detail in Section 04. CS 136 Winter 2022 03: Imperative C 26 More side effects In addition to: • Output (e.g., printf) we will encounter two more types of side effects (in this section): • Mutation (modifying variables) All side effects involve changing state. CS 136 Winter 2022 03: Imperative C 27 Variables store values. To define a variable in C, we need (in order): • the type (e.g., int) • the identifier (“name”) • the initial value int my_variable = 7; // definition The equal sign (=) and semicolon (;) complete the syntax. Definitions are not statements. They are different “things” (syntactic units). CS 136 Winter 2022 03: Imperative C 28 When the value of a variable is changed, it is known as mutation. int main(void) { int m = 5; trace_int(m); trace_int(m); trace_int(m); // definition (with initialization) // mutation! // more mutation! CS 136 Winter 2022 03: Imperative C 29 At every moment in time, a variable must have a value. When mutation occurs, the “state” (value) of the variable changes. Mutation is a side effect. For a “real world” example, consider your bank account balance. At any moment in time, your account balance has a specific value (or “state”). When you withdraw money from your account, the balance changes to a new value. Withdrawing money has a side effect: it changes the value your bank balance. CS 136 Winter 2022 03: Imperative C 30 For most imperative programmers, mutation is second nature and not given a special name (they rarely use the term “mutation”). The word “mutation” does not appear in the CP:AMA textbook. CS 136 Winter 2022 03: Imperative C 31 Assignment Operator In C, mutation is achieved with the assignment operator (=). m = m + 1; • The “right hand side” (RHS) must be an expression that produces a value with the same type as the LHS. • The LHS must be the name of a variable (for now). • The LHS variable is changed (mutated) to store the value of the RHS expression. In other words, the RHS value is assigned to the variable. • This is a side effect: the state of the variable has changed. CS 136 Winter 2022 03: Imperative C 32 The use of the equal sign (=) can be misleading. The assignment operator is not symmetric. is not the same as Some languages use to make the assignment more obvious. CS 136 Winter 2022 03: Imperative C 33 In addition to the mutation side effect, the assignment operator (=) also produces the right hand side value. This is occasionally used to perform multiple assignments. x = y = z = 0; // (x = (y = (z = 0))); Avoid having more than one side effect per expression statement. printf("%d\n", y = 5); printf("%d\n", y = 5 + (x = 3)); z = 1 + (z = z + 1); // never do this! // this is even worse! // really bad style! CS 136 Winter 2022 03: Imperative C Remember, always use a double == for equality, not a single = (which we now know is the assignment operator). if (i = 13) { printf("disaster!\n"); (i = 13) assigns 13 to i and produces the value 13, so the if expression is always true, and it always prints disaster! Pro Tip: some defensive programmers get in the habit of writing (13 == i) instead of (i == 13). This causes an error if they accidentally use a single =. CS 136 Winter 2022 03: Imperative C 35 Initialization C allows a variable definition without initialization, but it is bad style. int my_variable = 7; // initialized int another_variable; // uninitialized (BAD!) Always initialize variables. In Section 04 we discuss the behaviour of uninitialized variables. CS 136 Winter 2022 03: Imperative C 36 Initialization is not assignment The = used in initialization is not the assignment operator. Both initialization and assignment use the equal sign (=), but they have different semantics. int n = 5; // initialization syntax n = 6; // assignment operator The distinction is not too important now, but the subtle difference becomes important later. This distinction is especially important in C++. CS 136 Winter 2022 03: Imperative C 37 C allows you to define more than one variable at once. int x = 0, y = 2, z = 3; Most modern style guides discourage this (bad style). In the following example, x is uninitialized. int x, y = 0; CS 136 Winter 2022 03: Imperative C 38 More assignment operators The compound addition assignment operator (+=) combines the addition and assignment operator (for convenience). x += 2; // x = x + 2; Additional compound operators include: -=, *=, /=, %=. There are also increment and decrement operators that increase or decrease a variable by one (either prefix or postfix). ++x; x++; // x += 1; --x; x--; // x -= 1; If you follow our “one side effect per expression” rule it does not matter if you use prefix or postfix (see next slide). CS 136 Winter 2022 03: Imperative C 39 The language C++ is a pun: one bigger (better) than C. The prefix (++x) and postfix (x++) increment operators have different precedences within the order of operations. x++ produces the “old” value of x and then increments x. ++x increments x and then produces the “new” value of x. j = x++; // j = 5, x = 6 j = ++x; // j = 6, x = 6 Prefix (++x) is usually preferred to improve clarity and efficiency. CS 136 Winter 2022 03: Imperative C 40 A constant is a “variable” that is immutable (not mutable). In other words, the value of a constant cannot be changed. const int my_constant = 42; To define a C constant, we add the const keyword to the type. In this course, the term “variable” is used for both variable and constant identifiers. In the few instances where the difference matters, we use the terms “mutable variables” and “constants”. CS 136 Winter 2022 03: Imperative C 41 It is good style to use const when appropriate, as it: • communicates the intended use of the variable, • prevents ‘accidental’ or unintended mutation, and • may help to optimize (speed up) your code. We often omit const in the slides, even where it would be good style, to keep the slides uncluttered. CS 136 Winter 2022 03: Imperative C 42 Global and local variables Variables are either global or local. Global variables are defined outside of functions (at the “top level”). Local variables are defined inside of functions. int my_global_variable = 7; void f(void) { int my_local_variable = 11; CS 136 Winter 2022 03: Imperative C 43 Variable Scope The scope of a variable is the region of code where it is “accessible” or “visible”. For global variables, the scope is anywhere below its definition. int g = 7; int main(void) { printf("%d\n", g); // g OUT of scope // g IN scope // g IN scope We will revisit global scope in Section 06. CS 136 Winter 2022 03: Imperative C 44 Block (local) scope Local variables have block scope. Their scope extends from their definition to the end of the block they are defined in. void f(int n) { if (n > 0) {
int b = 19;
// b OUT of scope
// b OUT of scope
// b IN scope
// b OUT of scope
CS 136 Winter 2022
03: Imperative C 45

Variables with the same name can shadow other variables from outer scopes, but this is obviously poor style.
The following code defines three different variables named n. int n = 1;
int main(void) {
trace_int(n);
int n = 2;
trace_int(n);
int n = 3;
trace_int(n);
trace_int(n);
CS 136 Winter 2022
03: Imperative C 46

In older versions of C, all the local variable definitions had to be at the start of the function block (before any statements).
In C99, you may define a local variable anywhere in a block.
Modern programming guides recommend that you define a variable:
• in the narrowest scope possible
• as close to its first use as possible
This improves readability and ensures that when a variable is
first used its type and initial value are accessible.
CS 136 Winter 2022 03: Imperative C 47

“Impure” functions
Recall that the functional paradigm requires “pure” functions:
• functions only return values (no side effects)
• return values only depend on argument values
For example, the noisy_sqr function is “impure” because it has a side effect (produces output).
int noisy_sqr(int n) {
printf(“Yo! I’m squaring %d!\n”, n);
return n * n;
“Impure” functions are sometimes called “procedures” or “routines” to

程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com