Top Banner
ププププププププププププププ ププ プ
44

プログラミング入門2 第7回

Feb 23, 2016

Download

Documents

hamal

プログラミング入門2 第7回. 情報工学科 篠埜 功. 今日の内容. 中間試験について 基本型、文字列について. 中間試験について. 演習室ではなく、通常教室で行います。(部屋番号は掲示されます。講義用 web page にも 記載しました。) 記述式にします。穴埋めや選択ではなく、白紙の答案用紙にプログラムが書けるようにしておいてください。これまでに講義で説明した構文のみを組み合わせて書ける問題のみを出題します。(まだ説明していない構文を使っても構いませんが。) - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: プログラミング入門2 第7回

プログラミング入門2第7回

情報工学科 篠埜 功

Page 2: プログラミング入門2 第7回

今日の内容• 中間試験について• 基本型、文字列について

Page 3: プログラミング入門2 第7回

中間試験について• 演習室ではなく、通常教室で行います。(部屋番号は掲示されます。講義用 web page にも記載しました。)• 記述式にします。穴埋めや選択ではなく、白紙の答案用紙にプログラムが書けるようにしておいてください。これまでに講義で説明した構文のみを組み合わせて書ける問題のみを出題します。(まだ説明していない構文を使っても構いませんが。)• 各回の最後の課題2問のプログラムを書けるようにしておいてください。その他の予想問題を次ページ以下に置いています。• 試験範囲は今日の内容まで。• 持ち込み不可。

Page 4: プログラミング入門2 第7回

中間試験問題例1整数 1 から n までの和を計算する関数を C 言語で定義せよ。 ( 例えば、 n が 4 の場合は、 1,2,3,4 の和で、 10 が結果となる。 ) 関数名は sum とする。ただし、関数 sum は、 n を int 型の引数として受け取り、計算結果を int 型の値で返す関数として定義せよ。 int sum (int n) { … }引数に 0 以下の値が与えられた場合は 0 を結果として返すようにせよ。効率のよい計算方法((1+n)n/2 など ) は使わず、最も素朴な、 1 から順に n まで足していく方法で定義せよ。 main 関数の定義は不要である。

Page 5: プログラミング入門2 第7回

解答例int sum (int n) { int sum=0, i=1; while (i<=n) { sum = sum + i; i = i + 1; } return sum;}

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

解答例1 解答例2

Page 6: プログラミング入門2 第7回

中間試験問題例23つの整数の最大値を求める関数を定義せよ。関数名は max3 とする。ただし、関数 max3 は、3つの int 型の引数 n1, n2, n3 を受け取り、そのうちの最大値を int 型の値で返す関数として定義せよ。 int max3 (int n1, int n2, int n3) { … }main 関数の定義は不要である。

Page 7: プログラミング入門2 第7回

解答例int max3 (int n1, int n2, int n3) { int max; max = n1; if (max < n2) max = n2; if (max < n3) max = n3; return max;}

int max2 (int n1, int n2) { if (n1 > n2) return n1; else return n2;}

int max3 (int n1, int n2, int n3) { return max2 (n1, max2 (n2, n3));}

解答例1 解答例2

Page 8: プログラミング入門2 第7回

中間試験問題例3配列を使う C 言語のプログラムを自由に定義し、その意味を説明せよ。

Page 9: プログラミング入門2 第7回

解答例#include <stdio.h>int main (void) { int a[3]; int i=0, sum=0; while (i < 3) scanf (“%d”, &a[i]); i = 0; while (i < 3) sum = sum + a[i]; printf (“sum=%d\n”, sum); return 0;}

(説明)これは、キーボードから3つの整数を受け取り、それらの和を計算して表示するプログラムである。

Page 10: プログラミング入門2 第7回

中間試験問題例4以下のプログラムを、 goto 文を使わないプログラムに書き換えよ。

#include <stdio.h>int main (void) { int x; x = 1; while (x <= 10) { if (x == 5) { x=x+1; goto aaa; } printf (“ 羊が %d 匹 \n", x); x=x+1; aaa: ; } return 0;}

Page 11: プログラミング入門2 第7回

解答例#include <stdio.h>int main (void) { int x; x = 1; while (x <= 10) { if (x == 5) { x=x+1; continue; } printf (“ 羊が %d 匹 \n", x); x=x+1; } return 0;}

Page 12: プログラミング入門2 第7回

基本型• これまでに紹介した基本型は int型、 double 型である。その他にもさまざまな基本型があり、整数型、浮動小数点型に分類できる。

Page 13: プログラミング入門2 第7回

整数型整数型は 、 char, short int, int, long int の4種類に分かれる (C99 では long long int が加わり、5種類 ) 。 char が一番小さく、 long int が一番大きい(具体的に何バイトかは処理系によって異なる)。それぞれの型は、符号付きと符号無しでそれぞれ2つずつある。 型指定子 (signed, unsigned) で指定する。 char 以外は、型指定子を与えない場合は符号付きになる。 char は、符号付きか符号無しかのいずれかである(処理系依存)。扱う数の範囲に応じて適切な型を選択して用いる。

Page 14: プログラミング入門2 第7回

整数型整数型は、結局、

– signed char 型– unsinged char 型– signed short int 型– unsigned short int 型– signed int 型– unsigned int 型– signed long int 型– unsigned long int 型の8個となる。 (long long int を入れれば10個。 )

Page 15: プログラミング入門2 第7回

符号について(1)符号無し整数型 (unsigned char, unsigned short int, unsigned int, unsigned long int) においては、ビット列を普通の2進数として解釈する。

Page 16: プログラミング入門2 第7回

符号について(2)符号付き整数型 (signed char, signed short int, signed int, signed long int,) においては、符号を表すために1ビットを用いる(符号ビットという)。符号ビットが 0 の場合には、残りのビットを普通の2進数として解釈する。符号ビットが 1 の場合の解釈は以下の3通りのいずれかである(処理系依存)。

•  符号ビットを 0 に変えた場合のビット列が表す数にマイナスを付けた数を表す•  2の補数表現•  1の補数表現

Page 17: プログラミング入門2 第7回

例外について演算の結果が、表現可能な値の範囲を超える場合( overflow )や、 0 での除算などの場合、例外 (exception) が発生する。例外が発生したときの挙動は処理系によって異なる。ただし、符号無し整数型の演算では、表現可能な値の範囲を超えた場合、表現可能な最大値 +1 で割った余りになる。(オーバーフローは発生しない。)

Page 18: プログラミング入門2 第7回

文字についてプログラム中では、文字をクォートで囲むと、その文字に対応する int 型の数を表す。

(補足)文字は char 型で表すと無駄がないが、 int型で表しておくと、例えばファイルから文字を1文字ずつ読み取って変数に代入する場合、ファイルの終端に来た時に EOF(int 型、値はどの文字とも異なる。普通は -1 。 ) が返され、それを変数に代入し、その値が EOF と等しいかどうか判定するといったプログラムを書けるというメリットがある。(補足)文字列は char 型の並びである(後述)。

(例) ‘ a’ は a という文字に対応する int 型の数を表す。( char 型ではないことに注意。 C++ では char 型だが。)演習室の環境では、’ a’ は int 型の 97 を表す。

Page 19: プログラミング入門2 第7回

printf での文字の表示方法(打ち込んで確認)printf 関数で文字を表示する場合、変換指定を %c にする。引数には int 型を受け取り、それを unsigned char 型に変換( 256 で割った(非負の)余りに変換)し、それに対応する文字を表示する。

#include <stdio.h>int main (void) { printf ("%c\n", 'a'); printf ("%d\n", 'a'); printf ("%c\n", 97); printf (“%c\n”, 97 + 256); printf (“%c\n”, 97 – 256); return 0;}

a97aaaが表示される。

Page 20: プログラミング入門2 第7回

文字の8進表記ある文字に対応する数が分かっているとき、その数で直接書きたい場合がある。その時に使うのが文字の8進表記である。たとえば、’ a’ と書く代りに、(演習室の環境では)’ \141’ と書くことができる。ただし、プログラムの可搬性が低下するので使わない方がよい。よく使うのは、ヌル文字を表す場合で、’ \0’ と書く。’ \0’ は、対応する数が 0 の文字(ヌル文字)に対応する数(すなわち 0 )を表している。 0 と直接書いても同じ意味だが、 0 よりも’ \0’ の方が、文字を表している数だということが見た目に分かりやすい。

Page 21: プログラミング入門2 第7回

8 進逆斜線表記の構文\ octal-digit

\ octal-digit octal-digit

\ octal-digit octal-digit octal-digit

8 進逆斜線表記の構文18 進逆斜線表記の構文28 進逆斜線表記の構文3

ただし、 octal-digit は 0 1 2 3 4 5 6 7 のいずれかを表す。つまり、バックスラッシュのあとに 1桁から 3桁の 8 進数を書いたものが 8 進逆斜線表記である。8 進逆斜線表記はクォートおよびダブルクォートの中でのみ用いる。 8 進逆斜線表記をクォートで囲んだとき、それは、その 8 進数の表している数 (int 型 ) を表す。つまり、文字を表すための数であるということを見た目に分かりやすくするために用意されている構文である。

Page 22: プログラミング入門2 第7回

変数への格納(打ち込んで確認)#include <stdio.h>int main (void) { int x; x = 'a'; printf ("%c\n", x); printf ("%d\n", x); x = x+1; printf ("%c\n", x); printf (“%d\n”, x); return 0;}

文字は通常、 int 型の変数に格納する。

1 を足したものを %c で表示すると b が表示される。

Page 23: プログラミング入門2 第7回

整数型の範囲について(打ち込んで確認) C 言語の処理系は、 limits.h において、それぞれの型の最大値、最小値をマクロとして提供する。

#include <stdio.h>#include <limits.h>int main (void) { printf ("char : %d から %d まで \n", CHAR_MIN, CHAR_MAX); printf (“short int : %d から %d まで \n", SHRT_MIN, SHRT_MAX); printf ("int : %d から %d まで \n", INT_MIN, INT_MAX); printf ("long int : %ld から %ld まで \n", LONG_MIN, LONG_MAX);return 0;}

long int の変換指定には %ld を用いる。

Page 24: プログラミング入門2 第7回

整数型のまとめ• 整数型はある一定の範囲の整数を表現するための型である。• 扱う数値が負にならないことが分かっていれば、符号無しの型を使うと、同じビット数で、より大きな範囲の数を扱うことができる。

Page 25: プログラミング入門2 第7回

浮動小数点型浮動小数点型は小数を表すための型であり、

– float 型– double 型– long double 型の3つがある。今回は詳しくは説明しない。

Page 26: プログラミング入門2 第7回

文字列とは(1)文字 (char 型 ) の並びであって、‘ \0’ という文字 (ヌル文字 null character 、値は 0 。ナル文字と読む場合もある。 ) までを文字列と呼んでいる。

‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’

‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

‘\0’ ‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

これらは文字 (char 型 ) の並びである。

Page 27: プログラミング入門2 第7回

文字列とは(2)‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

この部分は文字列である。‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

この部分も文字列である。一番右端が’ \0’ であり、それ以外に’ \0’ を含んでいなければそれは文字列である。

Page 28: プログラミング入門2 第7回

文字列とは(3)‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

この部分は文字列である(空文字列という)。‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

この部分も文字列である。一番右端が’ \0’ であり、それ以外に’ \0’ を含んでいなければそれは文字列である。

Page 29: プログラミング入門2 第7回

char 型の配列文字列は char 型の配列を宣言し、各要素に文字を1文字ずつ格納して最後にヌル文字を格納することによって作成できる。char 型の配列型の変数は char a [7];のように宣言する。これは char 型の要素を7 個持つ配列 a を宣言している。

Page 30: プログラミング入門2 第7回

printf 関数での文字列の表示方法(打ち込んで確認)文字列の表示には、変換指定として %s を用い、引数に char 型へのポインタ(詳しくは後日説明)を与える。そのポインタが指しているところから、ヌル文字の手前までを画面に表示する。

#include <stdio.h>int main (void) { char a [7]; a[0] = ‘L’; a[1] = ‘i’; a[2] = ‘n’; a[3] = ‘\0’; a[4] = ‘u’; a[5] = ‘x’; a[6] = ‘\0’; printf (“%s\n”, &a[0]); return 0;}

&a[0] は配列 a の先頭要素へのポインタを表す。先頭要素は’ L’ であり、 Lin が表示される。

Page 31: プログラミング入門2 第7回

printf 関数での文字列の表示方法(打ち込んで確認)#include <stdio.h>int main (void) { char a [7]; a[0] = ‘L’; a[1] = ‘i’; a[2] = ‘n’; a[3] = ‘\0’; a[4] = ‘u’; a[5] = ‘x’; a[6] = ‘\0’; printf (“%s\n”, &a[1]); return 0;}

&a[1] は配列 a の2番目要素へのポインタを表す。2番目の要素は’ i’ であり、 in が画面に表示される。

Page 32: プログラミング入門2 第7回

ポインタについて(後日、ポインタの回にも説明する)

‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

a[0] a[1] a[2] a[3] a[4] a[5] a[6]

&a[0] は配列 a の先頭要素へのポインタを表す。 &a[0] の値は、配列 a の先頭要素の番地である。この場合、 100 である。&a[1] は配列 a の2番目の要素へのポインタであり、 101 である。 &a[2] は 102である。以下同様。

100 101 102 103 104 105 106番地

Page 33: プログラミング入門2 第7回

printf 関数の変換指定の %s について‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

a[0] a[1] a[2] a[3] a[4] a[5] a[6]

printf (“%s”, &a[1]);が実行されると、 101 番地から、ヌル文字の1つ手前までの文字が画面に出力される。つまり、 in が表示される。 printf (“%s”, &a[4]);だと、 ux が表示される。

100 101 102 103 104 105 106番地

Page 34: プログラミング入門2 第7回

文字列リテラルダブルクォート ” で囲んだものを文字列リテラルという。(例)” abc” など。これは、 char 型の並びであり、最後にヌル文字が追加されたものである。

‘a’ ‘b’ ‘c’ ‘\0’ ‘d’ ‘e’ ‘\0’

(例)“ abc\0de” は文字列リテラルである。最後にヌル文字が追加されるので、以下の char 型の並びとなる。

Page 35: プログラミング入門2 第7回

例(打ち込んで確認)#include <stdio.h>int main (void) { printf ("abc\0de"); return 0;}

これを実行すると、 abc が表示される( de は表示されない)。

Page 36: プログラミング入門2 第7回

文字列の読み込み(打ち込んで確認)文字列の読み込みは、 scanf 関数で変換指定として %s を用いて行う。

#include <stdio.h>int main (void) { char a[7]; printf ("Input characters: "); scanf ("%s", &a[0]); printf ("%s\n", &a[0]);}

scanf は、入力文字に空白があると、そこまでが配列に格納される。

Page 37: プログラミング入門2 第7回

scanf 関数の変換指定の %s について‘a’ ‘b’ ‘c’ ‘d’ ‘e’ ‘\0’

a[0] a[1] a[2] a[3] a[4] a[5] a[6]

scanf (“%s”, &a[0]);が実行されると、例えば abcde を入力した場合、 100 番地から 104 番地まで a,b,c,d,e が順番に格納され、 105 番地にヌル文字が格納される。最後にヌル文字が格納されるので、配列のサイズ -1 の長さを超えて入力してはいけない。それ以上入力したらあふれた部分も書きこまれる(バッファーオーバーフロー)。 これは攻撃の対象になるので対処が必要だが、本講義の範囲外とする。

100 101 102 103 104 105 106番地

Page 38: プログラミング入門2 第7回

gets 関数空白がある文字列は gets 関数を用いると読み込ませることができる。 gets 関数は改行まで読み込み、改行文字をヌル文字に置き換えて配列に格納する。これも配列のサイズを超えた場合にも書きこまれる。 (fgets 関数を用いるとこれに対処できるが、本講義の範囲外とする。)

#include <stdio.h>int main (void) { char a[10]; gets (&a[0]); printf ("%s\n", &a[0]); scanf ("%s", &a[0]); printf ("%s\n", &a[0]); return 0;}

Page 39: プログラミング入門2 第7回

今日の課題1キーボードから英語の文字列を1つ入力として受け取り、その中に英語の大文字をすべて小文字に変換したものを画面に表示するプログラムを作成せよ。英語の大文字が含まれていない場合はそのまま表示せよ。(実行例) 文字列を入力してください : This is a pen. this is a pen.

(注意)十分な長さの配列を宣言して用いること。

Page 40: プログラミング入門2 第7回

(補足) char 配列の初期化について char a [1000] = {‘\0’}; char b [1000] = {‘\0’};のように char 配列の初期化をすることによって、すべての要素がヌル文字で初期化されるので便利がよい。(文字列のコピーなどの場合に最後のヌル文字の扱いがやりやすくなるので)

Page 41: プログラミング入門2 第7回

大文字から小文字への変換大文字から小文字への変換は tolower 関数を用いる。tolower 関数は、 int 型を引数に受け取り、それが大文字に対応する数の場合、その小文字に対応するint 型の数を返す。大文字以外の場合はそれをそのまま返す。ctype.h を読み込む必要がある。

#include <ctype.h>#include <stdio.h>int main (void) { printf ("%c\n", tolower ('A')); printf ("%c\n", tolower ('a')); printf ("%c\n", tolower ('+')); return 0;}

Page 42: プログラミング入門2 第7回

今日の課題2キーボードから英語の文字列を1つ入力として受け取り、それが回文であるかどうかを判定するプログラムを作成せよ。ただし、アルファベットの大文字小文字は区別せず、かつアルファベット以外の記号(空白、エクスクラメーションマーク等)は無視するものとする。(実行例) 文字列を入力してください : So many dynamos! So many dynamos! は回文です。(補足) dynamo は発電機。 dynamos は dynamoの複数形(注意)十分な長さの配列を宣言して用いること。

Page 43: プログラミング入門2 第7回

アルファベットの文字の判定アルファベットの文字の大小の判定は、 islower, isupper 関数で行う。アルファベット文字かどうかは、islower, isupper のいずれも偽になるかどうかで判定できる。

#include <ctype.h>#include <stdio.h>void hantei (int c) { if (islower(c)) printf ("%c は小文字です \n", c); else if (isupper (c)) printf ("%c は大文字です \n", c); else printf ("%c はアルファベットではありません。\n", c);}

/* 続き */int main (void) { hantei ('a'); hantei ('A'); hantei ('+'); return 0;}

Page 44: プログラミング入門2 第7回

チャレンジ課題1.文字列を2つキーボードから受け取り、1つ目の文字列が2つ目の文字列の(連続した)部分文字列になっているかどうかを判定するプログラムを作成せよ。(実行例1) 1 つ目の文字列 : def 2 つ目の文字列 : abcdefg def は abcdefg の部分文字列です。(実行例2) 1 つ目の文字列 : cef 2 つ目の文字列 : abcdefg cef は abcdefg の部分文字列ではありません。