Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
C言語入門 第12週
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ,
情報処理言語Ⅰ(実習を含む。)
1
文字列の基本
2
𝑁進数
• 各桁は𝑁種類の数字(0~𝑁 − 1)で表す
• 下の桁から、 𝑁0の桁、 𝑁1の桁、 𝑁2の桁、 …
• 現在の桁数で表せない数値は桁上がりする
2進数 8進数 10進数 16進数
0 0 0 0
1 1 1 1
10 2 2 2
11 3 3 3
100 4 4 4
101 5 5 5
110 6 6 6
111 7 7 7
1000 10 8 8
1001 11 9 9
1010 12 10 a
1011 13 11 b
1100 14 12 c
1101 15 13 d
1110 16 14 e
1111 17 15 f
10000 20 16 10
3
2の桁へ 桁上がり
4の桁へ 桁上がり
8の桁へ 桁上がり
16の桁へ 桁上がり
8の桁へ 桁上がり
10の桁へ 桁上がり
16の桁へ 桁上がり
2進数3桁 ⇕
8進数1桁
2進数4桁 ⇕
16進数1桁
𝑁進数
2進数 4桁(場合の数 2 4) 16進数 1桁(場合の数16 1) 2進数 8桁(場合の数 2 8) 16進数 2桁(場合の数16 2) 2進数16桁(場合の数 216) 16進数 4桁(場合の数16 4) 2進数32桁(場合の数 232) 16進数 8桁(場合の数16 8) 2進数64桁(場合の数 264) 16進数16桁(場合の数1616)
2進数 8進数 10進数 16進数
11111000 370 248 f8
11111001 371 249 f9
11111010 372 250 fa
11111011 373 251 fb
11111100 374 252 fc
11111101 375 253 fd
11111110 376 254 fe
11111111 377 255 ff
100000000 400 256 100
100000001 401 257 101
100000010 402 258 102
100000011 403 259 103
100000100 404 260 104
100000101 405 261 105
100000110 406 262 106
100000111 407 263 107
100001000 400 264 108
4
256の桁へ 桁上がり
256の桁へ 桁上がり
2進数3桁 ⇕
8進数1桁
2進数4桁 ⇕
16進数1桁
𝑥バイト(8𝑥ビット)の数値は 2𝑥桁の16進数で表すことが出来る
8bit整数の10進表現
2進 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
16進 0 1 2 3 4 5 6 7 8 9 A B C D E F
0000 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0001 1 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0010 2 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
0011 3 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
0100 4 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
0101 5 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
0110 6 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
0111 7 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
1000 8 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
1001 9 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
1010 A 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
1011 B 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
1100 C 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
1101 D 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
1110 E 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
1111 F 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
上位4ビット
下位4ビット
5
2進数と10進数は桁数の対応で収まりが悪い
8bit整数の2進表現
2進 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
16進 0 1 2 3 4 5 6 7 8 9 A B C D E F
0000 0 0000 0000 0000 0001 0000 0010 0000 0011 0000 0100 0000 0101 0000 0110 0000 0111 0000 1000 0000 1001 0000 1010 0000 1011 0000 1100 0000 1101 0000 1110 0000 1111
0001 1 0001 0000 0001 0001 0001 0010 0001 0011 0001 0100 0001 0101 0001 0110 0001 0111 0001 1000 0001 1001 0001 1010 0001 1011 0001 1100 0001 1101 0001 1110 0001 1111
0010 2 0010 0000 0010 0001 0010 0010 0010 0011 0010 0100 0010 0101 0010 0110 0010 0111 0010 1000 0010 1001 0010 1010 0010 1011 0010 1100 0010 1101 0010 1110 0010 1111
0011 3 0011 0000 0011 0001 0011 0010 0011 0011 0011 0100 0011 0101 0011 0110 0011 0111 0011 1000 0011 1001 0011 1010 0011 1011 0011 1100 0011 1101 0011 1110 0011 1111
0100 4 0100 0000 0100 0001 0100 0010 0100 0011 0100 0100 0100 0101 0100 0110 0100 0111 0100 1000 0100 1001 0100 1010 0100 1011 0100 1100 0100 1101 0100 1110 0100 1111
0101 5 0101 0000 0101 0001 0101 0010 0101 0011 0101 0100 0101 0101 0101 0110 0101 0111 0101 1000 0101 1001 0101 1010 0101 1011 0101 1100 0101 1101 0101 1110 0101 1111
0110 6 0110 0000 0110 0001 0110 0010 0110 0011 0110 0100 0110 0101 0110 0110 0110 0111 0110 1000 0110 1001 0110 1010 0110 1011 0110 1100 0110 1101 0110 1110 0110 1111
0111 7 0111 0000 0111 0001 0111 0010 0111 0011 0111 0100 0111 0101 0111 0110 0111 0111 0111 1000 0111 1001 0111 1010 0111 1011 0111 1100 0111 1101 0111 1110 0111 1111
1000 8 1000 0000 1000 0001 1000 0010 1000 0011 1000 0100 1000 0101 1000 0110 1000 0111 1000 1000 1000 1001 1000 1010 1000 1011 1000 1100 1000 1101 1000 1110 1000 1111
1001 9 1001 0000 1001 0001 1001 0010 1001 0011 1001 0100 1001 0101 1001 0110 1001 0111 1001 1000 1001 1001 1001 1010 1001 1011 1001 1100 1001 1101 1001 1110 1001 1111
1010 A 1010 0000 1010 0001 1010 0010 1010 0011 1010 0100 1010 0101 1010 0110 1010 0111 1010 1000 1010 1001 1010 1010 1010 1011 1010 1100 1010 1101 1010 1110 1010 1111
1011 B 1011 0000 1011 0001 1011 0010 1011 0011 1011 0100 1011 0101 1011 0110 1011 0111 1011 1000 1011 1001 1011 1010 1011 1011 1011 1100 1011 1101 1011 1110 1011 1111
1100 C 1100 0000 1100 0001 1100 0010 1100 0011 1100 0100 1100 0101 1100 0110 1100 0111 1100 1000 1100 1001 1100 1010 1100 1011 1100 1100 1100 1101 1100 1110 1100 1111
1101 D 1101 0000 1101 0001 1101 0010 1101 0011 1101 0100 1101 0101 1101 0110 1101 0111 1101 1000 1101 1001 1101 1010 1101 1011 1101 1100 1101 1101 1101 1110 1101 1111
1110 E 1110 0000 1110 0001 1110 0010 1110 0011 1110 0100 1110 0101 1110 0110 1110 0111 1110 1000 1110 1001 1110 1010 1110 1011 1110 1100 1110 1101 1110 1110 1110 1111
1111 F 1111 0000 1111 0001 1111 0010 1111 0011 1111 0100 1111 0101 1111 0110 1111 0111 1111 1000 1111 1001 1111 1010 1111 1011 1111 1100 1111 1101 1111 1110 1111 1111
上位4ビット
下位4ビット
6
2進数は桁が多過ぎて直感的に分かり難い
8bit整数16進表現
2進 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
16進 0 1 2 3 4 5 6 7 8 9 A B C D E F
0000 0 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
0001 1 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
0010 2 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
0011 3 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
0100 4 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
0101 5 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
0110 6 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
0111 7 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
1000 8 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f
1001 9 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
1010 A a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af
1011 B b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
1100 C c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf
1101 D d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df
1110 E e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef
1111 F f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
上位4ビット
下位4ビット
7
2進数と16進数は相性が良い。2進数4桁が16進数1桁に対応するので直感的に分かり易い
ASCII文字コード表
16進 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI 1 DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US 2 SP ! " # $ % & ' ( ) * + , - . / 3 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 4 @ A B C D E F G H I J K L M N O 5 P Q R S T U V W X Y Z [ ¥ ] ^ _ 6 ` a b c d e f g h i j k l m n o 7 p q r s t u v w x y z { | } ~ DEL 8 9 A B C D E F
上位4ビット
下位4ビット
赤字は制御コード
教科書 p.51.,第2週資料 p.67.
http://ja.wikipedia.org/wiki/ASCII
8
標準ヘッダ <ctype.h>
// 文字コードの調査(cが該当する文字なら真を返す) int islower(int c); //小文字 int isupper(int c); //大文字 int isdigit(int c); //10進数(数字) int isxdigit(int c);//16進数 int isalpha(int c); //英字 (isupper(c)||islower(c)) int isalnum(int c); //英数字(isalpha(c)||isdigit(c)) int iscntrl(int c); //制御文字(0x00~0x1f, 0x7f) int isspace(int c); //空白文字(' ','¥f','¥n','¥r','¥t','¥v') int isprint(int c); //印字可能文字(0x20~0x7e) int isgraph(int c); //印字可能文字(スペースを除く) isprint(c)&&!isspace(c) int ispunct(int c); //印字可能文字(スペース、英数字を除く)isgraph(c)&&!isalnum(c) // 文字コードの変換 int tolower(int c); //cを小文字に変換 int toupper(int c); //cを大文字に変換
9 [1] pp.303.
JM: isalpha (3) toupper (3) 講義資料の ctype_test.c, ctype_test.xlsx も参照
char型変数と文字コード
• char, unsigned char 型
• 半角文字の文字コードを1つ つまり1バイト(=8ビット)を格納出来るサイズ
• char : -128~127
• unsigned char : 0~255
10 教科書 pp.44, 96-99., 第2週資料 pp.54-63.
c
0110 1000
変数の実体はNバイト(8Nビット)のメモリ つまり内部的には2進数が入っている
16進数リテラルによる初期化 char c = 0x68; // =104='h'
文字コードに対応する文字を表示 printf("%c¥n", 104); // "%c"に文字コードを与えると対応する文字が表示される
char型変数と文字コード
• 以下の変数宣言と初期化は全く同じ結果
11 教科書 pp.44, 96-99., 第2週資料 pp.54-63.
c
0110 1000 どの方法で初期化しようと結局 char型(1バイト)の変数 c を 0b01101000 で初期化している
文字コードを代入したい場合 文字定数リテラルで書くと 数値リテラルで書くよりも 意味が分かり易くなる
結果は同じでも読んだ時 分かり易いのはどれだろう?
必要であれば 読んだ人が分かり易いよう コメントで情報を補うと良い
文字定数リテラルによる初期化 char c = 'h'; // 0x68
10進数リテラルによる初期化 char c = 104; // 'h'
16進数リテラルによる初期化 char c = 0x68; // 'h'
c
104
c
0x68
c
'h'
char型配列と文字列
• 以下の変数宣言と初期化は全く同じ結果
12
文字定数リテラルによる初期化 char s[] = {'h', 'e', 'l', 'l', 'o', '¥0'};
文字列定数リテラルによる初期化 char s[] = "hello";
教科書 pp.44, 96-99., 第2週資料 pp.54-63.
10進数リテラルによる初期化 char s[] = {104, 101, 108, 108, 111, 0};
16進数リテラルによる初期化 char s[] = {0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x00};
s[0]
'h'
s[1]
'e'
s[2]
'l'
s[3]
'l'
s[4]
'o'
s[5]
'¥0' 文字列は配列に格納した 一連の文字コード 終端には 0 を格納する
どれで書いても良いが 普通は面倒だから 文字列の初期化は 文字列定数リテラルを 用いる
char型配列と文字列
• 文字列の表示
13
文字列定数リテラルによる初期化 char s[] = "hello";
教科書 pp.44, 96-99., 第2週資料 pp.54-63.
s[0]
'h'
s[1]
'e'
s[2]
'l'
s[3]
'l'
s[4]
'o'
s[5]
'¥0'
文字列の表示 printf("%s¥n", s); // "%s"に与えたアドレス以降'¥0'が現れるまで // メモリに格納された文字コードに対応する文字が表示される
関数の引数とよく使われる名前
• p, ptr, pointer : ポインタ • c, ch, chr, character : 文字 • s, str, string : 文字列 • s, src, source : 発信元 • d, dst, destination : 送信先 • t, txt, text : テキスト • l, len, length : 長さ • w, wid, width : 幅 • h, hei, height : 高さ • n, num, number : (個)数 • s, size : サイズ • b, buf, buff, buffer : バッファ • i, idx, index : 添え字 • s, stat, status : 状態
14
標準ヘッダ <string.h>
size_t strlen(const char *s); // 文字列の長さ char *strcpy(char *dst, const char *src); // 文字列のコピー char *strncpy(char *dst, const char *src, size_t n); // 文字列のコピー(最長制限付) char *strcat(char *dst, const char *src); // 文字列の連結 char *strncat(char *dst, const char *src, size_t n); // 文字列の連結(最長制限付) char *strcmp(const char *s1, const char *s2); // 文字列の比較 char *strncmp(const char *s1, const char *s2, size_t n); // 文字列の比較(最長制限付) char *strchr(const char *s, char c); // 文字の検索(先頭から) char *strrchr(const char *s, char c); // 文字の検索(末尾から) int strspn(const char *s, const char *t); // 先頭部分の文字列の長さ(∈t) int strcspn(const char *s, const char *t); // 先頭部分の文字列の長さ(∉t) char *strpbrk(const char *s, const char *t); // 文字の検索(∈t) char *strstr(const char *s, const char *t); // 文字列の検索 char *strtok(char *s, const char *t); // 文字列の分割 void *memset(void *s, int c, size_t n); // メモリへ値を設定 void *memcpy(void *dst, const void *src, size_t n); // メモリのコピー void *memmove(void *dst, const void *src, size_t n); // メモリの移動 int memcmp(const void *s1, const void *s2, size_t n); // メモリの比較 void *memchr(const void *s, int c, size_t n); // メモリの検索
15
strlen 関数
• size_t strlen(const char *s); • 文字列 s の長さを返す
• 引数: • s: 長さを調べる文字列
• 戻り値 • 文字列 s の長さを返す
16 教科書 p.312., [1] pp.313-315.
JM: strlen (3)
strcpy 関数
• char *strcpy(char *dst, const char *src); • '¥0'を含めてsrcをdstへコピーする
• 引数: • dst: コピー先のアドレス • src: コピー元の文字列
• 戻り値 • dst を返す • dst が十分な大きさでないとバッファオーバーフローを引き起こすの
で注意
17 教科書 p.308., [1] pp.313-315.
JM: strcpy (3)
strncpy 関数
• char *strncpy(char *dst, const char *src, size_t n); • srcから最大n文字dstへコピーする
• 引数: • dst: コピー先のアドレス • src: コピー元の文字列 • n: コピーする最大文字数
• 戻り値 • dst を返す • src が n 文字より短い場合は、残りの dst の末尾に '¥0' を詰
めて、合計 n バイト書き込む
18 教科書 p.308., [1] pp.313-315.
JM: strcpy (3)
strcat 関数
• char *strcat(char *dst, const char *src); • 文字列dstの末尾に文字列srcを連結する
• 引数: • dst: 連結先の文字列 • src: 連結元の文字列
• 戻り値 • dst を返す • dst が十分な大きさでないとバッファオーバーフローを引き起こすの
で注意
19 教科書 p.309., [1] pp.313-315.
JM: strcat (3)
strncat 関数
• char *strncat(char *dst, const char *src, size_t n); • 文字列dstの末尾に文字列srcを最大n文字連結する
• 引数: • dst: 連結先の文字列 • src: 連結元の文字列 • n: 連結する最大文字数
• 戻り値 • dst を返す • dst は strlen(dst)+min(strlen(stc),n)+1 の大きさがなけ
ればバッファオーバーフローが発生する
20 教科書 p.309., [1] pp.313-315.
JM: strcat (3)
strcmp 関数
• char *strcmp(const char *s1, const char *s2); • 文字列s1とs2を比較する
• 引数: • s1: 比較する文字列1 • s2: 比較する文字列2
• 戻り値 • s1がs2に比べて小さければマイナスの値を返す • s1とs2が等しければ0を返す • s1がs2に比べて大きければプラスの値を返す
21 教科書 p.309., [1] pp.313-315.
JM: strcmp (3)
strncmp 関数
• char *strncmp(const char *s1, const char *s2, size_t n); • 文字列s1とs2の先頭n文字を比較する
• 引数: • s1: 比較する文字列1 • s2: 比較する文字列2 • n: 比較する最大文字数
• 戻り値 • strcmpに同じ
22 教科書 p.310., [1] pp.313-315.
JM: strcmp (3)
strchr 関数
• char *strchr(const char *s, char c); • 文字列sのなかで最初に現れるcを見つける
• 引数: • s: 検索する文字列 • c: 検索する文字
• 戻り値 • 最初に見つかったcへのポインタを返す • 見つからなかった場合はNULLを返す
23 教科書 p.312., [1] pp.313-315.
JM: strchr (3)
strrchr 関数
• char *strrchr(const char *s, char c); • 文字列sのなかで最後に現れるcを見つける
• 引数: • s: 検索する文字列 • c: 検索する文字
• 戻り値 • 最後に見つかったcへのポインタを返す • 見つからなかった場合はNULLを返す
24 教科書 p.313., [1] pp.313-315.
JM: strchr (3)
strspn 関数
• int strspn(const char *s, const char *t); • 文字列sの先頭から、tに含まれる文字だけからなる文字列の長さを
返す
• 引数: • s: 検索する文字列 • t: 検索する文字の集合
• 戻り値 • tに含まれる文字からなる接頭子(prefix)の長さを返す
25 [1] pp.313-315.
JM: strspn (3)
strcspn 関数
• int strcspn(const char *s, const char *t); • 文字列sの先頭から、tに含まれない文字だけからなる文字列の長さ
を返す
• 引数: • s: 検索する文字列 • t: 検索する文字の補集合
• 戻り値 • tに含まれない文字からなる接頭子(prefix)の長さを返す
26 [1] pp.313-315.
JM: strspn (3)
strpbrk 関数
• char *strpbrk(const char *s, const char *t); • 文字列sのなかで、tに含まれる文字が最初に出てくる位置を見つけ
る
• 引数: • s: 検索する文字列 • t: 検索する文字の集合
• 戻り値 • tに含まれる文字が最初に見つかった位置へのポインタを返す • 見つからなかった場合はNULLを返す
27 [1] pp.313-315.
JM: strpbrk (3)
strstr 関数
• char *strstr(const char *s, const char *t); • 文字列sのなかで、文字列tが最初に現れる位置を見つける
• 引数: • s: 検索する文字列 • t: 検索する文字列
• 戻り値 • 文字列tが最初に見つかった位置へのポインタを返す • 見つからなかった場合はNULLを返す
28 教科書 p.314., [1] pp.313-315.
JM: strstr (3)
strtok 関数
• char *strtok(char *s, const char *t); • 文字列sのなかから、 tに含まれる文字で区切られるトークンを見つ
ける
• 引数: • s: 検索する文字列 • t: トークンを区切る文字の集合
• 戻り値 • トークンへのポインタを返す • 2つ目以降のトークンは s を NULL にして呼ぶことで順次切り出さ
れる • トークンがなくなったらはNULLを返す • s は区切り文字の位置が終端文字'¥0'で破壊される
29 [1] pp.313-315.
JM: strtok (3)
memset 関数
• void *memset(void *s, int c, size_t n); • sの先頭からnバイトをcで埋めsを返す
• 引数: • s: データで埋める先頭アドレス • c: メモリを埋める1バイトのデータ • n: データcを埋めるバイト数
• 戻り値 • s を返す • 要 string.h
30 [1] pp.313-315.
JM: memset (3)
memcpy 関数
• void *memcpy(void *dst, const void *src, size_t n); • dstにsrcの内容をnバイトコピーする • dstとsrcは領域が重なっていてはならない。重なっている場合は
memmoveを用いる
• 引数: • dst: データのコピー先 • src: データのコピー元 • n: コピーするバイト数
• 戻り値 • dst を返す • 要 string.h
31 [1] pp.313-315.
JM: memcpy (3)
memmove 関数
• void *memmove(void *dst, const void *src, size_t n); • dstとsrcは領域が重なっていても良い点を除けば、memcpyと同じ
• 引数: • dst: データのコピー先 • src: データのコピー元 • n: コピーするバイト数
• 戻り値 • dst を返す • 要 string.h
32
JM: memmove (3)
[1] pp.313-315.
memcmp 関数
• int memcmp(const void *s1, const void *s2, size_t n); • s1とs2の最初のnバイトを比較する
• 引数: • s1: 比較するメモリ1 • s2: 比較するメモリ2 • n: 比較するバイト数
• 戻り値 • strcmpに同じ • 要 string.h
33
JM: memcmp (3)
[1] pp.313-315.
memchr 関数
• void *memchr(const void *s, int c, size_t n); • sの中でcが最初に現れる位置を見つける
• 引数: • s: 検索するメモリ • c: 検索する値 • n: 検索する範囲のバイト数
• 戻り値 • cが最初に見つかった位置へのポインタを返す • 見つからなかった場合はNULLを返す要 string.h
34
JM: memchr (3)
[1] pp.313-315.
標準ヘッダ <stdlib.h>
// 文字列を数値に変換
double atof(const char *s); //文字列をdouble型の数値に変換
int atoi(const char *s); //文字列をint型の数値に変換
long atol(const char *s); //文字列をlong型の数値に変換
double strtod(const char *s, char **endp);
long strtol(const char *s, char **endp, int base);
unsigned long strtoul(const char *s, char **endp, int base);
// 文字列を double, long, unsigned long 型の数値に変換する
// endp が NULL でない場合、
// *endp は変換に用いた最後の文字の次の文字へのポインタとなる
// base は変換元の文字列の基数
// base が 0 の場合、文字列先頭の 0 や 0x を解釈し
// 8 進数や 16 進数として扱う
35 [1] pp.316-317.
JM: atof (3) atoi (3)
strtod (3) strtol (3)
シーザー暗号
文字列の演習
36
シーザー暗号
• アルファベットをN文字シフトする暗号
• 例: IBM→1文字左へ→HAL
37
演習: caesar.c
• 与えられた文字列をシーザー暗号で暗号化する関数caesar(n,s)を作成せよ。 • 文字コードが0x20~0x7eの文字ついてのみ処理し、それ以外の文字について
は処理せずそのまま残すこと。 • 0x20~0x7eからはみ出す値は値域の反対側に繋がるよう循環するよう変換せ
よ。例えばn=1なら0x61('a')は0x62('b')に、0x7eは0x20に変換される変換される。n=-1の場合も同様で、0x20は0x7eに変換される。
• caesar_main.c と共にコンパイルして動作を確認せよ • 引数:
• int n : 暗号鍵(シフトする文字数) • char s[] : 暗号化する文字列(終端が'¥0')
• 戻り値 • なし(void) • 与えた配列 s を上書きしてシーザー暗号で
暗号化した文字列で上書きせよ
38
mintty + bash + GNU C $ gcc caesar_main.c caesar.c && ./a n = 1 s = hal ibm
ヒント
• プロトタイプ宣言の末尾の ; を {} に変えれば関数の定義になる。
• 文字の末尾は ¥0 で終端されている。 • i を増やしながら s[i] != '¥0' の間ループを続
ければ良い。
• s 全体を暗号文で上書きするには各 s[i] を暗号化して s[i] に戻してやれば良い。
39
caerar_main.c void caesar(int n, char s[]); 4
ヒント
• 0x20未満、0x7e超になった場合の処理は幾つかやり方がある
• if 文等で場合分けする方法
• 剰余算を使う方法
• 等々
40
参考文献
• [1] B.W.カーニハン/D.M.リッチー著 石田晴久 訳、プログラミング言語C 第2版 ANSI 規格準拠、共立出版(1989)
41