Comments
Description
Transcript
講義用資料
プログラムの設計と実現 I(第5回:2016/05/12) ◎第4回の演習の解答例 #include <stdio.h> int combination(int n, int r) { if (r == 1) { /* nC1 = n */ return n; } else if (n == r) { /* nCn = 1 */ return 1; } else { /* nCr = n-1Cr-1 + n-1Cr */ return combination(n-1,r-1) + combination(n-1,r); } } int main(void) { int num1, num2; do { printf("nCr を計算します。\n"); do { printf("正の整数 n を入力してください:"); scanf("%d", &num1); } while (num1 <= 0); do { printf("正の整数 r (r<=n) を入力してください:"); scanf("%d", &num2); } while (num2 <= 0); } while (num1<num2); printf("nCr は%d です。\n", combination(num1, num2)); return 0; } ◎文字型 文字型変数の定義 char ch; ch は文字型の変数(実際には 1 バイト整数型) 各文字には数値が決められている → ASCII 文字コード(世界共通) ※文字コードはいろいろ存在し、漢字等の扱い方法も様々である。 英数字は ASCII でほぼ問題はない。 漢字については、最近は UTF が用いられることが多いが、JIS, ShiftJIS, EUC も利用されている。 ◎ASCII 文字コード 0x00~0x1f,0x7f 制御文字, 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f ! " # $ % & ' ( ) * + , . / 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x20~0x7e 印字可能文字 @ A B C D E F G H I J K L M N O 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f P Q R S T U V W X Y Z [ \ ] ^ _ 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 0x60 0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x6a 0x6b 0x6c 0x6d 0x6e 0x6f ` a b c d e f g h i j k l m n o 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 0x70 0x71 0x72 0x73 0x74 0x75 0x76 0x77 0x78 0x79 0x7a 0x7b 0x7c 0x7d 0x7e p q r s t u v w x y z { | } ~ ※C 言語では ASCII 文字コードに限定していないが、少なくとも数字の 0~9 はこの順で一つずつ値が大きくなることを規定している。 ◎文字の入出力 キーボードから入力した文字を画面に表示するプログラム #include <stdio.h> int main(void) { int ch; /* 文字読み込み用の変数。ch は int 型であることに注意 */ while ((ch = getchar()) != EOF) { /* 1文字読み込み、返り値が EOF になるまで繰り返す */ /* キーボード入力の場合、Ctrl+d を入力すると EOF となる */ printf("%c", ch); /* 読み込んだ文字を画面に出力する */ /* char 型の値をプリントアウトするには %c を用いる */ } /* getchar()が EOF の場合、上のループを抜けて、ここに到達。*/ printf("%d\n", ch); /* EOF の値(ch)を確認。表示の型が int であることに注意 */ return 0; /* 正常終了 */ } getchar() ・標準入力から一文字読込む関数。 ・文字が読込まれた場合はその文字の数値が返る。 ・ファイル終端の場合や予期せぬエラーの場合、EOF が返る。 ・EOF は stdio.h で定義されており、マイナスの値をとる(そのため、 getchar() の返り値の型は int 型でなければならない) 。 1 文字出力する関数として、putchar()という関数も存在する。上記の printf("%c", ch); は以下のように変更可能。 putchar(ch); ◎文字定数 文字を' 'でくくると、その文字の数値(ASCII コード等)となる。 たとえば上記のプログラム例の while を以下のように変えると、 文字 E を入力した時に終了するようになる。 while ((ch = getchar()) != 'E') { 'E'は実際には 69 という整定数を表すが、プログラマはその値を知る必 要はなく、'E'と書くだけでよい。 ◎文字列 文字列とは文字が連続したもの →C 言語では文字の配列として表現される(配列の各要素は一文字) プログラム例(List9-2) #include <stdio.h> int main(void) { char str[4]; str[0] str[1] str[2] str[3] = = = = 'A'; 'B'; 'C'; '\0'; メモリ空間 配列 str[] 'A' (65) str[0] 'B' (66) str[1] 'C' (67) str[2] ‘¥0' (0) str[3] printf("文字列 str は%s です。\n", str); return 0; } '\0'は特別な記号 → 文字列の終端を表わす 文字列をプリントアウトするには%s を用い、文字列(配列)の[]は 付けない('\0'の直前の文字までが出力される) C 言語では配列変数の大きさは最初に決めなければいけない →文字列を記憶する配列はあらかじめ大きめに確保しておき、終端を '\0'で示すことにより実現している 上記の前半部分は以下のようにも書ける。 char str[] = {'A', 'B','C', '\0'}; または char str[] = "ABC"; /* " " で囲まれた文字列を文字列定数/文字列リテラルと呼ぶ */ たとえば、以下のように配列のサイズを指定した場合、 char comp[10] = "Mozart"; メモリー上には以下のように配置される。 プログラム例(List9-4) #include <stdio.h> int main(void) { char name[40]; printf("お名前は:"); scanf("%s", name); /* scanf で文字列も読込める。 なぜ&がなくて配列名だけなのかは後日に理解可能となる */ printf("こんにちは、%s さん!!\n", name); return 0; } ◎文字列の応用プログラム例 #include <stdio.h> int str_length(char s[]) /* 文字列 s を受け取り、その長さ('\0'は含まない)を返す関数 */ { メモリ空間 int len = 0; 'A' (65) len=0 while (s[len] != '\0') { 配列 'B' (66) len=1 len++; s[] 'C' (67) len=2 } ‘¥0' (0) len=3 return(len); } void str_copy(char s[], char t[]) /* 文字列 s と t を受け取り、s に t の内容をコピーする関数 */ { メモリ空間 int i; for (i=0; t[i] != '\0'; i++) { 'A' (65) 文字'A'のコピー s[i] = t[i]; 配列 'B' (66) 文字'B'のコピー s[] /* '\0'の直前までコピーする */ 'C' (67) 文字'C'のコピー } '¥0' (0) 終端記号'¥0'の代入 s[i] = '\0'; /* 最後に'\0'を追加 */ 'A' (65) return; 配列 'B' (66) } t[] 'C' (67) int main(void) ‘¥0' (0) { char s[100]; char t[100]; printf("文字列 t を入力してください:"); scanf("%s", t); printf("文字列 t\"%s\"の長さは%d です。\n", t, str_length(t)); printf("文字列 s に文字列 t\"%s\"をコピーすると", t); str_copy(s,t); printf("文字列 s は\"%s\"となります。\n", s); return 0; } 実行例: 文字列 t を入力してください:ABC 文字列 t"ABC"の長さは 3 です。 文字列 s に文字列 t"ABC"をコピーすると文字列 s は"ABC"となります。 ◎文字列の配列 文字列の配列も作成可能で、二次元配列として表現される。 プログラム例(List9-11 改) #include <stdio.h> void put_strary(char s[][6], int n) { int i; for (i = 0; i < n; i++) { printf("s[%d]=\"%s\"\n", i, s[i]); /* s[][]の括弧が一つだけであることに注意 */ } return; } int main(void) { char s[][6] = {"Turbo", "NA", "DOHC"}; put_strary(s, 3); return 0; } メモリ上には 6×3 バイトの 連続領域に配置される。 配列 s[3][6] s[0] s[1] s[2] メモリ空間 'T' 'u' 'r' 'b' 'o' '¥0' 'N' 'A' '¥0' ??? ??? ??? 'D' 'O' 'H' 'C' '¥0' ??? s[0][0] s[0][1] s[0][2] s[0][3] s[0][4] s[0][5] s[1][0] s[1][1] s[1][2] s[1][3] s[1][4] s[1][5] s[2][0] s[2][1] s[2][2] s[2][3] s[2][4] s[2][5]