C言語入門

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