# Creation and Use of Functions

(関数の作り方と使い方)

## Computing Practice I

### 5th lecture, May 10, 2018

http://www.sw.it.aoyama.ac.jp/2018/CP1/lecture5.html

### Martin J. Dürst

© 2005-18 Martin J. Dürst 青山学院大学

# Today's Schedule

• Minitest
• About previous exercises
• Functions
• Declarations and definitions
• Function extraction and refactoring
• Functions calling themselves, recursion
• About today's exercises

# ミニテスト

• 授業開始までにログイン済み
• ナビゲーションは左に畳み、ブラウザは全画面に拡大
• 授業開始まで教科書、資料、筆箱、財布などを鞄に入れ、鞄を椅子の下に
• テスト終了後その場で待つ

# Applications of C: Linux

• Open source operating system (kernel)
• Development started by Linus Torwalds to study operating systems;
first published in 1991
• Currently used in most servers, some PCs (Debian, Fedora, Ubuntu,...), Android, embedded devices
• Usage is similar to Unix (origin of C language), but implementation is different

# 独力・独走の約束

(前々週・前週の出来事)

• 学生 A は締め切りが近いのに、演習課題に苦戦
• A は学生 B を呼び出し、助言をお願い
• B が A のプログラムを理解できず、B なりの解法を一から教える
• 一回目の授業で説明した範囲 (Q&A フォーラムと同じ程度) をはるかに超える
• 約束通り、一週間分の点数を全部没収
• 早めの取り組みと Q&A フォーラムの活用を強くお勧めする

# Results of Previous Exercises

 04A1 04A2 04A3 04B1 04B2 04C1 100 points 89 77 72 58 24 - 60 points 10 22 27 33 65 8 partial (10 points or more) - - - - - 34 partial (less than 10) - - - - - 17 error - - - 1 12 not submitted 1 1 1 8 7 29

# Example Solutions for 04C1

• Solution strategies:
• Nested `switch`/`if`s
• State machine
• Small buffer
• Hints:
• Treat newline like a regular character
• Treat EOF (almost) like a regular character
• Separate !=EOF test and getchar() call
• Establish invariants (e.g. always keep the next character ready in a variable)
• Use notation that is simple, compact, and easy to understand
`if (c == 97)``if (c == 'a')`
`putchar('&'); putchar('a');``printf("&a");`

# Importance of Functions

• Structure program by splitting it up into smaller pieces
• Avoid repeated code doing the same (or similar) things
• Separate What? from How?
• Abstract from How? to What?

# Functions in Programming Languages and in Mathematics

• 数学的理論では「関数」さえあれば「計算」は万能
• 数学の関数と C の関数は少し違う:
• 数学: 結果は普遍、副作用 (side effects) なし
• C: 副作用あり (入出力、参照渡しなど)
• 関数型言語 (functional programming language):
• 関数が多くて短いプログラムの方がいい
(オブジェクト思考言語や関数型言語では 10 行の関数は長い)

# Concepts and Terms around Functions

• Function name
• Argument/parameter
• Formal parameter (defined in function, similar to variable)
• Actual parameter (value passed to function when called)
• Return value

# How to Think about Functions

Clearly separate thinking about:

• Usage of a function
• Think about function name, number and types of parameters, type of return value
• Ignore internal details of function implementation
• Construction/contents of a function
• Think about internal details of function implementation
• Ignore usage context (→ make usable in many different contexts)
• Never use global variables
• Avoid functions with side effects where possible
• Limit input/output to `main` function, or functions dedicated to input only or output only

# Declarations and Definitions

Distinguished for functions (and global variables)

• Declaration
• Declares existence of identifier, name, and type
• Example: `long fibonacci(int i);`
• If functions are used across files, declarations are included in a `.h` (header) file
• Definition
• Defines actual presence, memory use, initialization, working details
• Also serves as declaration
• Example: ```long fibonacci(int i)     { ... }```
• Always in `.c` file

Attention: Our coursebook uses a lot of unnecessary declarations:

```int main(void); // this declaration is unnecessary```

`int main(void)`

`{...`

# 関数の抽出の手順

• (空の) 新関数を作成 (意図に合った名前)
• 抽出したいコードを新関数にコピー
• 抽出したコード内のローカル変数の使用をチェック
→新関数のローカル変数または引数
• 抽出したコードでのローカル変数の変更をチェック
→一個の場合、新関数の戻り値
→複数の場合、関数の抽出を再検討
• コンパイル (新関数の文法チェック)
• 元の場所で抽出されたコードを新関数の呼出しに変更
• 新関数だけで使用された変数を元の場所で削除
• コンパイル、テスト

(Refactoring: Improving the Design of Existing Code, Martin Fowler et al., Addison-Wesley, 1999 の「メソッドの抽出」より)

# Refactoring

• 更なる機能の追加の準備や
デサインの向上のため、
プログラムの機能を変更せずに
プログラムを書き直す
• 簡単にできるプログラムの小さな変更
• 例:
• 一時変数の導入 (または削除)
• 関数の名前の変更
• 関数の抽出 (又はインライン化)
• オブジェクト指向プログラミングでよく使われるが、C でも利用可能
• テストとの組み合わせで力を発揮

# A Function Calling Itself

Very simple example: Calculating the sum of integers from 1 to n (∑ni=0 i):

`int sumN (int n){   if (n <= 0)       return 0;   else       return n + sumN(n-1);}`

Mathematical justification: ∑ni=0 i = n + ∑n-1i=0 i (for n>0); ∑0i=0 i = 0

# Execution Example for `sumN`

• `sumN`A(`n`A=3)
• `n`A > 0
• `sumN`B(`n`B=2)
• `n`B > 0
• `sumN`C(`n`C=1)
• `n`C > 0
• `sumN`D(`n`D=0)
• `n`D ≦ 0
• `return` 0
• `return` 1 + 0
• `return` 2 + 1
• `return` 3 + 3

Result: `6`

# Recursive Functions

• A function that calls itself is called a recursive function
• The principle is called recursion
• Recursion can be direct or indirect (e.g. a()→b()→a())
• Recursion is strongly related to mathematical induction
• For some problem specifications, recursive functions may be very easy to write

# One More Example of a Recursive Function

Convert a number i to n-ary representation:

`void printNary (int i, int n) {    static char letters[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";    if (i < n)        putchar (letters[i]);      else {        printNary (i/n, n);        putchar (letters[i%n]);    }}`

# Execution Example for `printNary`

• `printNary`A(iA=83, nA=6)
• iA ≧ nA
• `printNary`B(iB=13, nB=6)
• iB ≧ nB
• `printNary`C(iC=2, nC=6)
• iC < nC
• `putchar`('2')
• `putchar`('1')
• `putchar`('5')

Result: `215`

# Important Points about Recursive Functions

• Recursion helps simplify many problems
• Formal parameters and local variables exist separately for each invocation
• Better to think about "a function doing the same work" rather than "the same function"
(not "the same person", but rather "a person doing the same work")

# Parts of a Recursive Function

1. Non-recursive base case
• Important: Has to come first
• Otherwise, there may be infinite recursion
(resulting in a stack overflow or segmentation fault)
2. Actual recursion

# Recursion Patterns

• Recursion, processing (`sumN`, `printNary`,...)
• Processing, recursion (tail recursion)
• Processing, recursion, processing (05C2)
• Recursion, recursion, processing (Fibonacci function)
• Recursion, processing, recursion (tower of Hanoi)

[recursion: recursive function call; processing: data processing local to the function]

# プログラム開発のコツ

(advice for program development)

• 大きいプログラムを小さい部分に分ける
• 開発は小さい部分で:
• 全体をおおまかな分割から (top-down)
• 一部の小さい機能から (bottom-up)
• 常に正しいインデント、読みやすさを維持
• 常にコンパイルできる状態を維持
• まめにコンパイル・実行・テスト

# 問題の再利用の目的

• 実世界でプログラムの更新が新開発より圧倒的に多い
• リファクタリングとテストの練習
• 時間の短縮 (短い時間で長い問題に挑戦可能)
• 自分のプログラムの読み直し (何週間後で再読)
• 複数のプログラミングスタイルの比較

# 演習問題の概要

• 05A1: 簡単なプログラムから階乗関数を抽出
• 05B1: Josephus 関数
• 05B2: Fibonacci 関数 (数列) の再帰的プログラム
• 05B3: 組み合わせの表の計算
• 05C1: 学生番号分析プログラムを関数で書き直す
(リファクタリングとテストの応用)
• 05C2 (発展問題、月曜締切、部分点無し、ネタバレに厳重注意): 再帰を使って入力を逆順にする

ヒント: 入力の関数の戻り値をうまく利用

(05C1 以外は全部非常に短い)

# 次回の準備

• 今日の復習
• 残った演習問題を宿題として完成させる
• 教科書の第 10 章 (構造体, pp. 242-279) を読む (pp. 272-273 (`typedef`) を含む)

# Glossary

function

operating system
オペレーティングシステム
embedded device

state machine

function name

argument/parameter

formal parameter

actual parameter

return value

global variable
グローバル変数
side effect

(function) invocation
(関数の) 呼出
declaration

definition

function extraction

refactoring
リファクタリング
recursion

recursive function

mathematical induction

stack overflow
スタック・オーバーフロー
tail recursion

tower of Hanoi
ハノイの塔