● 先週のプログラムのキーポイント
【ソースコードの作成・コンパイル・実行の流れ】
C言語のプログラム(先週の ex01-1.cなど)は,エディタ(emacs)で作成した「文書」であり, コ ンピュータにとっては「単なる文字のならび」に過ぎない. (ただし,C言語の文法に沿って記述さ れた文書である.)これをプログラム・ソースコード(または単にソースコード)と呼ぶ.
ソースコードを「コンピュータが理解可能な命令の列」に変換する操作をコンパイルと呼ぶ. 先週の 例では “gcc ex01-1.c”というコマンドが,ソースコードex01-1.cを “gcc”という「C言語処理 系」(「コンパイラ」)によって, 「コンピュータが処理可能な命令の列」 a.outに変換する命令で ある.
したがって,ソースコードに記述した「プログラム」を「実行」するには,コンパイラが生成した「実 行可能コード」a.outを
% ./a.out Return
と実行する必要がある.
【コメント】
「/*」から「*/」までの間はコメントと呼ばれ, プログラムの制御には直接関係しない部分である. コメントには,あとからプログラムをみたときに容易にわかるように, そのプログラムが何をするも のなのかなどを書く1.
【プログラムの基本構造】
先週のプログラム例のいずれも
#include <stdio.h>
int main(int argc, char **argv) {
return 0 ; }
という形をしている.
• 「#include <stdio.h>」,「return 0」,「int main(int argc, char **argv)」の部分は, 今のところは,「おまじない」と思っておこう.
• プログラムはmainの次の行の“{”の部分から 順次 実行され,対応する“}”までで終了する2.
• プログラムの各行は「;」で終わっている. これも, 今のところ「そんなものだ」と思っておこ う3.
1より正確には,コメント部分は言語処理系の翻訳処理の前段階において削除され,翻訳処理には渡されない.
2正確に言えば正しくない. しかし,今のところ「そんなものだ」と思っておこう.
3正しくは,C言語では「行」という概念は存在しない.
【画面への出力】
以上の考察からex01-1.cは「printf("Hello World\n")」を実行して終了する. その実行例から わかるように, 「printf」はその中に書かれた 「"」で囲まれた部分を「画面」に出力する. なお
「\n」は「改行文字」を出力することを表す4.
【変数】
ex01-2.cでは「値を格納する場所」を定義し,簡単な「計算」を行っている.
• 「int i」, 「int i, j」などは「値を格納する場所」を定義している. (「値を格納する場所 を定義して,そこにi,jなどの名前をつけている」と理解するのがよい.)これを変数と呼ぶ.
• 「変数」には「値」を代入することが可能である.「i = 1」は,変数iに値1を代入している.
• 値(または変数)に対して「演算」を施して,新たな値を計算することができる. 「i+j」は,変 数iに入っている値と,jに入っている値の「和」を計算する. したがって,「k = i+j」は,変 数iに入っている値と,jに入っている値の「和」の値を計算し,その結果をkに代入すること を表わす5.
【値の出力】
値を出力するには printfを用いて,「printf("%d %d\n",i,j)」などとする. この時%dの部分に 対応する値が出力される. この対応づけは, 左から順に「%d」が見つかるたびに,後ろに書かれた変 数や定数の値が出力される.
printf("%d %d\n",i,j) 6
?
4「改行文字を出力する」という言葉の意味が分からない場合には,「printf("Hello World\n")」のかわりに「printf("Hello
World")」と書いたプログラムを実行すれば理解できるであろう.
5 , .
★ 重要な注意
「コマンド」を実行する場合には,そのコマンドが何を意味しているか,どのような結果が得られるのか を, 各自で理解した上で実行しなければならない. (もちろん,やってみてから何が起ったかを考えてもよ い.)そのためには,配布資料の該当部分と実行結果(または,その予測)を見比べることが重要である.
● 実習内容
【UNIX】
【シェルとワイルドカード】
• “ls-alg”コマンドを利用して, カレントディレクトリのファイルの一覧を表示させる.
• “ls-alg|more”コマンドを利用して,カレントディレクトリのファイルの一覧を表示さ せる. 上の場合と比べて何がうれしいのかを考えてみよう. (コマンドのパイプの意味を考 えてみよう.)(資料section 4.4.2.2, section 4.5.2.6)
• foo1.txt,foo2.txt,bar.txtという3つのファイルを作成してから,「ワイルドカード」
を用いて,foo1.txtとfoo2.txtだけを消去することを考えてみよう. (資料section 4.4.2)
• foo1.txt,foo2.txt,bar1.txtという3つのファイルを作成してから,「ワイルドカード」
を用いて,foo1.txtとbar1.txtだけを消去することを考えてみよう. (資料section 4.4.2)
★ 発展課題 foo1.txt,foo2.txtという2つのファイルのみがあった状態で,これらをそれぞれ bar1.txt,bar2.txtという名前のファイルに置き換えたい. これを“mvfoo?.txtbar?.txt” により望む結果が得られるのか? もし,そうでないならば,その理由は何か?
【ディレクトリ操作 (1)】
• cdコマンドを実行してみる. (資料section 4.5.1.1)
さらに,pwdコマンドを実行してみる. (資料section 4.5.1.2) これは何をしているのか, さらに何が起ったのかを考えよう.
• mkdirコマンドを利用して, サブディレクトリを作成する. (資料 section 4.5.1.3)(サブ ディレクトリの名前は各自が考えることである.)
• cdコマンドを利用して,作成したサブディレクトリに移動する. (資料section 4.5.1.1)
• 上で作成したサブディレクトリを削除する. これには rmdirコマンドを利用すれば良い. (資料section 4.5.1.4)
【ディレクトリ操作 (2)】
以下では,ここまでに学んだコマンドを利用して, ディレクトリ構造を「いじりまわす」練習で ある.
その際には「既存のファイル」を消去しないように十分な注意を払う必要がある. 「既存のファ イル」を消去してしまうと, ログインできなくなったり, いろいろな不都合が生じる可能性が ある.
• 下に書いたようなディレクトリ構造を各自で作成しよう.
(楕円で囲まれたものがディレクトリで, 四角のものはファイル. なお, ファイルはemacs を使って「ちょっとしたもの」を作成すればよい.)
ホームディレクトリ
foo bar
foo0.txt foo1.txt bar.txt
• 各種のコマンドを用いて,上で作成したディレクトリ構造から,次のディレクトリ構造へつ くり直そう.
ホームディレクトリ
foo bar
foo0.txt foo1.txt bar.txt
• さらに次のディレクトリ構造へつくり直そう.
ホームディレクトリ
foo
bar
foo0.txt
foo1.txt bar.txt
• 次に, 「ワイルドカード」を利用して,一部のファイルだけを消去して,次のディレクトリ 構造へつくり直そう.
ホームディレクトリ
foo bar
foo0.txt
• 最後に,bar以下をすべて(一度に)消去しよう.
【C言語】
• 第1回の実習で作成した “Hello World” (ex01-1.c)を以下のようにコンパイルする. (その ファイル名をex01-1.cと仮定している)
% gccex01-1.c-oex01-1 Return
-oex01-1をつけたことにより,生成される実行ファイルの名前がex01-1となる.
• 次に,おなじex01-1.cを
% gccex01-1.c-otest Return
としてコンパイルしてみよう. さらに,
% test Return
としたときと
% ./test Return
としたときの実行結果には何か違いが生じるかを調べ,その理由を考えてみよう. (資料section
4.4.5.1)なお,資料中で推奨しているコンパイル方法は,
% gcc-ansi-pedantic-errors-Wallex01-1.c-otest Return
である. しかし,前回および今回のプログラムをこのオプションのもとでコンパイルすると,いくつかの警 告が発生する.
以後は以下のようにコンパイルするのが望ましい.
% gcc-ansi-Wallex01-1.c-oex01-1 Return
• 以下のようなプログラムを書き,printf関数の意味をもう少し詳しく調べてみよう. (今日配 布した資料や参考書をもとに,来週までに%dとかの意味を調べてこよう.)(資料section 6.7.2) 電子メールで「今日の講義の感想や意見」を送ってください.
★ 注意
• なお,
for(i=0;i<10;i=i+1) { ....
}
とは, 変数iの値を0 から1づつ加えながら i<10が「真」である間, 括弧の中を繰り返す命令で ある.
• 以下のプログラムの記述方法は,現時点で理解しやすいように書いたものであり, C言語の記述方法 としては,必ずしも「標準的」ではないことに注意が必要である.
★
ex02-1.c
の内容
/* 1から10までの和を計算する */
/* $Id: ex02-1.c,v 1.4 2005-04-18 20:27:01+09 naito Exp $ */
/* ex01-1.c */
#include <stdio.h>
int main(int argc, char **argv) {
int sum ; int i ;
sum = 0 ;
for(i=1;i<=10;i=i+1) { sum = sum + i ; }
printf("sum = %d\n", sum) ; return 0 ;
}
★
ex02-2.c
の内容
/* y = 2*x + 1 の値を順に計算する */
/* $Id: ex02-2.c,v 1.5 2005-04-18 20:27:10+09 naito Exp $ */
/* ex02-2.c */
#include <stdio.h>
int main(int argc, char **argv) {
int i, j ;
printf("f(x) = 2 x + 1\n") ; for(i=0;i<20;i=i+2) {
j = 2*i + 1 ;
printf("f(%d) = %d\n", i, j) ; }
return 0 ; }
★
ex02-3.c
の内容
/* 偶奇を判定する */
/* $Id: ex02-3.c,v 1.3 2005-04-18 20:27:22+09 naito Exp $ */
/* ex02-3.c */
#include <stdio.h>
int main(int argc, char **argv) {
int i ;
for(i=0;i<20;i=i+1) { if ((i%2) == 0) {
printf("%d is even\n", i) ; }
else {
printf("%d is odd\n", i) ; }
}
return 0 ; }
★
ex02-4.c
の内容
/* y = x/2*2, y = x*2/2 の値を順に計算する */
/* $Id: ex02-4.c,v 1.8 2005-04-18 20:30:23+09 naito Exp $ */
/* ex02-4.c */
#include <stdio.h>
int main(int argc, char **argv) {
int i, j, k ;
printf("f(x) = x/2*2, g(x) = x*2/2\n") ; for(i=0;i<20;i++) {
j = i/2*2 ; k = i*2/2 ;
printf("f(%d) = %d, g(%d) = %d\n", i, j, i, k) ; }
return 0 ; }
【課題】
★ exercise-02-1 プログラムex02-1.cをもとにして,次のプログラムを書きなさい.
• n= 20として,k= 1, . . . , nに対して「1からkまでの和」を表示するプログラム.
★ exercise-02-2 プログラムex02-2.cを「変数j」を使わないように書き直しなさい.
★ exercise-02-3 プログラムex02-3.cをもとにして,次のプログラムを書きなさい.
• n= 20として, k= 1, . . . , nに対して,それぞれのk を3 で割ったあまりを表示するプロ
グラム.
★ exercise-02-4 プログラムex02-4.cは「不思議」な出力を出している. それはなぜかを考えよ.