第15章 文字列処理

第15章
文字列処理
15.1 文字列処理の基本
15.2 文字列処理用ライブラリ関数
今日のポイント
strcpy、strcat、strlen、strchr
などの使い方をマスターする
「strcpyはなんて読む?」
「普通はストリングコピー」
Cのキーワードの読み方に悩んだら下記サイトを参考(前回紹介とは別サイト)
http://www.okakogi.go.jp/People/miwa/program/c_lang/c_furoku.html
15.1 文字列処理の基本
1000
1001
1002
・
・
・
x[0]
x[1]
x[2]
x[3]
x[4]
x[18]
x[19]
W
i
l
l
i
e
¥O
1.文字列は配列に格納
2.文字列の終わりは¥0
この2点が重要ポイント
プログラム例 15.1.1 〜 15.1.3 は授業ではパス.
文字列がわかって来たら、自分で見直すこと.
15.2 文字列処理用ライブラリ関数
15.2.1 文字列のコピーと連結
文字列処理関数を使用するときは
ヘッダに string.h を追加
#include <string.h>
を追加
15.2 文字列処理用ライブラリ関数
15.2.1 文字列のコピー
プログラム例 15.2.1 より抜粋
文字型の配列変数 a,b を宣言
(30 は特に意味なし。
十分なサイズにすれば良い)
char a[30], b[30];
char c[30] = {"University"};
strcpy(&a[0], "Japan ");
strcpy(&b[0], &c[0]);
文字型配列変数 c の初期値は
"University" とする
文字列定数 "Japan" を配列
変数 a にコピー(=代入)
文字列 c を文字列 b に
コピー(=代入)
後ろから前へ
strcpy(string1, string2);
15.2 文字列処理用ライブラリ関数
15.2.1 文字列のコピー
後ろから前へ
strcpy(string1, string2);
文字型配列 string1 の
先頭アドレス(ポインタ)
ほとんどのテキストで
下記のように記述
例 strcpy(d,s);
文字型配列 string2 の
先頭アドレス(ポインタ)
または“文字列定数”
プログラム例 15.2.1 のように
strcpy(&string1[0], &string2[0]);
と書いても同じこと。この方が 先頭アドレス を指しているのが実感
できるが、短い方がスマートなので、上のように書くことが多い。
15.2 文字列処理用ライブラリ関数
15.2.1 文字列のコピー
プログラム例15.2.1をスマートに書くと → プログラム例15.2.2
#include <stdio.h>
#include <string.h>
int main(void)
{
char a[30], b[30];
char c[] = "University";
strcpy(a, "Japan ");
printf("%s\n", a);
strcpy(b, c);
printf("%s\n", b);
strcat(a, b);
printf("%s\n", a);
return 0;
}
文字型配列変数 a, b を宣言
(30 は特に意味なし。
十分なサイズにすれば良い)
文字型配列変数 c の初期値は
"University" とする(30 はなくて
も適正サイズを確保してくれる)
文字列定数 "Japan" を
配列変数 a にコピー(=代入)
文字列 c を文字列 b にコピー
(=代入)
15.2 文字列処理用ライブラリ関数
15.2.1 文字列のコピー

関数 strcpy は以下のように定義されている(p.146)
char *strcpy(char *ptr1, char *ptr2);
コピー(代入)先の
文字型配列の先頭
要素のアドレスを指す
ポインタ (=配列名)
コピー(代入)元の
文字型配列の先頭
要素のアドレスを指す
ポインタ (=配列名)
関数だから戻り値がある。
strcpy の戻り値は ptr1 (ポインタ) = ptr1[0] のアドレス
= 文字列 ptr1
15.2 文字列処理用ライブラリ関数
15.2.1 文字列の連結
Catenate means "to connect in a series."
1の後ろに2をつなげる
strcat(string1, string2);
15.2 文字列処理用ライブラリ関数
15.2.1 文字列の連結
プログラム例 15.2.2
#include <stdio.h>
#include <string.h>
int main(void)
{
char a[30], b[30];
char c[] = "University";
strcpy(a, "Japan ");
printf("%s\n", a);
strcpy(b, c);
printf("%s\n", b);
strcat(a, b);
printf("%s\n", a);
return 0;
}
1次元文字配列のときは{ }は省略可能
1の後ろに2をつなげる
strcat(string1, string2);
文字列 a に文字列 b を連結
文字列 a は Japan University となる
15.2 文字列処理用ライブラリ関数
15.2.1 文字列の連結

関数 strcat は以下のように定義されている(p.146)
char *strcat(char *ptr1, char *ptr2);
連結先(前半部)の
文字型配列の先頭
要素のアドレスを指す
ポインタ (=配列名)
連結する(後半部の)
文字型配列の先頭
要素のアドレスを指す
ポインタ (=配列名)
関数 だから 戻り値 がある。
strcat の 戻り値 は ptr1 (ポインタ) = ptr1[0] のアドレス
= 文字列 ptr1
15.2 文字列処理用ライブラリ関数
15.2.1 文字列の部分コピー
プログラム例 15.2.4 改
#include <stdio.h>
#include <string.h>
int main(void)
文字列を初期化すると、残りの要素に '\0' が入る
{
int i;
char a[30] = "", b[30] = "Japan";
char c[] = "Kyoto University";
for (i = 0; i < 30; i++) printf("%d ", a[i]);
printf("\n");
for (i = 0; i < 30; i++) printf("%d ", b[i]);
printf("\n");
文字列 a に文字列 b の
printf("%s\n", strcpy(a, c));
5 文字分をコピー
printf("%s\n", strncpy(a, b, 5));
return 0;
文字列 a は "Japan University" となる
}
15.2 文字列処理用ライブラリ関数
15.2.1 文字列の部分コピー

関数 strncpy は以下のように定義されている(p.184)
char *strncpy(char *ptr1, char *ptr2, int n);
コピー(代入)先の
文字型配列の先頭
要素のアドレスを指す
ポインタ (=配列名)
コピー(代入)元の
文字型配列の先頭
要素のアドレスを指す
ポインタ (=配列名)
コピー元から
コピーする
バイト数
文字列 a ( ptr1 が指す)に b ( ptr2 が指す)の n 文字分を上書き
関数 だから 戻り値 がある。
strncpy の 戻り値 は ptr1 (ポインタ) ⇔ ptr1[0] のアドレス)
15.2 文字列処理用ライブラリ関数
15.2.2 その他の関数
strlen(a);
文字列 a の長さを整数値( int 型)で返す。
使い方の例:
char a[] = "Hello, Goodbye";
int length;
length = strlen(a);
printf("文章 %s は %d 個の文字から成ります.¥n", a, length);
出力結果:
文章 Hello, Goodbye は 14 個の文字から成ります.
15.2 文字列処理用ライブラリ関数
15.2.2 その他の関数
strcmp(a, b);
使い方の例:
文字列 a と b を比較し、a < b なら負、
等しいなら 0、 a > b なら正の整数値
( int 型)を返す。
a-b
と同じ符号
char a[] = "Hello", b[] = "Goodbye";
int comp;
辞書に載っている順 ≒ アルファベット順
comp = strcmp(a, b);
if (comp < 0) printf("辞書式順序は文字列 %s が前です.¥n", a);
if (comp == 0) printf("辞書式順序は等しいです.¥n", a);
if (comp > 0) printf("辞書式順序は文字列 %s が前です.¥n", b);
出力結果:
辞書式順序は文字列 Goodbye が前です.
15.2 文字列処理用ライブラリ関数
15.2.2 その他の関数
strchr(a,'o');
文字列 a の中の文字 o の位置の
ポインタ(アドレス)を返す。
見つからなければ NULL を返す。
文字は何でも良い。
探したい文字を指定する
a_p
使い方の例:
見かけはポインタ
実体は数字のゼロ
"Department of Computer Science"
a_p = strchr(a_p, ' ');
ポインタ a_p から始まる文字列から空白を見つけ、その位置にポインタをセット
15.2 文字列処理用ライブラリ関数
15.2.2 その他の関数
プログラム例 15.2.5 : strlen、strchr の使い方の例
#include <stdio.h>
#include <string.h>
int main(void)
{
char a[] = "Department of Computer Science";
char *a_p = a;
int length, count;
空白の位置を探し、それが 0 でない間は以下を繰り返す
length = strlen(a);
printf("文章 %s は %d 個の文字から成ります.¥n", a, length);
count = 0;
while (a_p = strchr(a_p, ' ')) {
count++; a_p++;
}
空白の数 + 1 = 単語数
count++;
printf("また、文章に含まれる単語の数は %d 個です.¥n", count);
return 0;
}
15.2 文字列処理用ライブラリ関数
15.2.2 その他の関数
プログラム例 15.2.5 改: strlen、strchr の使い方の例
#include <stdio.h>
#include <string.h>
int main(void)
{
char a[] = "Department of Computer Science";
char *a_p = a;
int length, count, position;
length = strlen(a);
printf("文章 %s は %d 個の文字から成ります.¥n", a, length);
count = 0;
(空白の先頭アドレス) - (文章の先頭アドレス) + 1
while (a_p = strchr(a_p, ' ')) {
で、何文字目かがわかる。
position = a_p - a + 1;
printf("第 %d 番目の空白は %d 文字目です.¥n", count + 1, position);
count++; a_p++;
}
count++;
printf("また、文章に含まれる単語の数は %d 個です.¥n", count);
return 0;
}
15.2 文字列処理用ライブラリ関数
15.2.2 その他の関数
関数 strlen、strcmp の定義(p.149)
int strlen(char *ptr1);
文字列の長さを int 型で返す.
int strcmp(char *ptr1, char *ptr2);
文字列 a ( ptr1 が指す)と b ( ptr2 が指す)の辞書式順序を比較し、
a < b なら負、等しいなら 0、 a > b なら正の整数値( int 型)を返す.
char *strncpy(char *ptr1, char *ptr2, int n);
文字列 a ( ptr1 が指す)に b ( ptr2 が指す)の n 文字分を上書き.
(p.184)
15.2 文字列処理用ライブラリ関数
15.2.2 その他の関数
関数 strchr、strstr の定義(pp.148〜149)
char *strchr(char *ptr, char c);
文字列中から文字 c を探し、指定文字の位置の ポインタ を返す.
なければ NULL を返す.
char *strstr(char *ptr1, char *ptr2);
文字列 1 から文字列 2 を探し、文字列 2 の位置の ポインタ を返す.
なければ NULL を返す.
スキルアップタイム 1
プログラム例 15.2.1〜15.2.4 を参考に、以下の動作
をするプログラムを作成せよ

1.
適当な長さの文字型配列変数 a, b, c, d を 宣言
2.
日本語の文章1と文章2を適当に決め、おのおの a と b に
代入 (例えば、"宇都宮大学 ", "情報工学科 " など)
3.
c に a を、d に b をおのおの コピー
4.
c に b を、d に a をおのおの 連結
5.
a 〜 d をディスプレイに 表示
(表示書式は自分の好みで良い)
PAD
ヘッダファイルの取り込み
文字型配列a~dの宣言
文章1をaに代入
文章2をbに代入
main
= cにaをコピー
dにbをコピー
cにbを連結
dにaを連結
a~dを表示
スキルアップタイム 2
プログラム例 15.2.5 改 を作成・実行する
2. プログラム例 15.2.4 改 を作成・実行する
1.
配列 a[30] の初期化(= "")を省略するとどうなるか
 配列 b[30] の 30 を省略するとどうなるか
 strncpy の第3引数の 5 を増減するとどうなるか

3.
演習問題 15.1 1) 〜 3) を解く
本日のパズル
次のプログラムは何を出力するか
#include <stdio.h>
#define PRINT(format,x) printf("%"#format"\n",x)
int integer = 5;
char character = '5';
char *string = "5";
main()
{
PRINT(d,string); PRINT(d,character); PRINT(d,integer);
PRINT(s,string); PRINT(c,character);
PRINT(c,integer=53);
PRINT(d,( '5'>5 ));
}
1 2 3
4
6
7
5