digirakuda ようこそ!  コンピュータの世界へ!

第8回 いろいろな文字列処理

このドキュメントは http://icrus.org/c_language_beginers_course/ 上にあります.

[課題8-1] 関数を使って文字列を自在に出力しよう.(関数printf())

[プログラム例8-1]


01: #include <stdio.h>
02: void main(void){
03:     int  i;
04:     char s[12]="Programing";
05:
06:     for( i=0; i<12; i++ )
07:         printf( "s[%d]=%d ", i, s[i] );
08:     putchar( '\n' );
09:
10:     printf( "%s %s %s %s %s\n\n", s, s, s, s, s );
11:
12:     s[4]='\0';
13:     for( i=0; i<12; i++ )
14:         printf( "s[%d]=%d ", i, s[i] );
15:     putchar( '\n' );
16:
17:     printf( "%s %s %s %s %s\n", s, s, s, s, s );
18:     getchar();
19: }

行説明
04行目→配列名sをchar型の要素数12に宣言し,文字配列"Programing"に初期化する.
06~08行目→文字配列sの要素のデータ(アスキーコード)を全て整数として表示させる.
10行目→文字配列sを5回表示させる.
12行目→文字配列sの4番目に終了文字の'\0'を代入する.
13~15行目→文字配列sの要素のデータ(アスキーコード)を全て整数として表示させる.
17行目→文字配列sを5回表示させる.

[結果8-1]

コンパイル・実行すると次のよう表示されます.
s[0]=80 s[1]=114 s[2]=111 s[3]=103 s[4]=114 s[5]=97 s[6]=109 s[7]=105 s[8]=110 s[9]=103 s[10]=0 s[11]=0
Programing Programing Programing Programing Programing

s[0]=80 s[1]=114 s[2]=111 s[3]=103 s[4]=0 s[5]=97 s[6]=109 s[7]=105 s[8]=110 s[9]=103 s[10]=0 s[11]=0
Prog Prog Prog Prog Prog

リターンキーを押すとプログラムは終了します.

ここで文字配列について説明します.
通常,char s[12];で文字配列sを宣言します.宣言すると12個の文字の入れものが確保されます.確保のみで入れものの中身は不定(どんな値が入っているか判らない)です.下図のような入れものが確保されます.

値 配列の要素の値は不定
0番 1番 2番 3番 4番 5番 6番 7番 8番 9番 10番 11番

このプログラムでは4行目でchar s[12]="Programing";として宣言と同時に初期化を行って,文字配列sに文字列"Programing"をコピーしています.コピー後の配列は下図のようになります.

文字P r o g r a m n i g \0
値 80 114 111 103 114 97 109 105 110 103 0  不定
0番 1番 2番 3番 4番 5番 6番 7番 8番 9番 10番 11番

ここで,10番目の要素の値は0になっています.これは自動的に文字列"Programing"の終わりに付けられる文字'\0'で,それが文字配列sにもコピーされました.
これはヌル文字とよばれ文字列の終了を表します.

次に,12行目では強制的にs[4]='\0';として,文字配列sの4番目要素をヌル文字を代入しています.代入後の配列の様子を下図に示します.

文字P r o g \0 a m n i g \0
値 80 114 111 103  0 97 109 105 110 103 0  不定
0番 1番 2番 3番 4番 5番 6番 7番 8番 9番 10番 11番

関数printf()などの文字配列を扱う関数はヌル文字'\0'を文字列の終わりと判断しますので,'\0'の代入後は,Prog Prog Prog Prog Progと表示されます.
したがって,文字配列sの5番目以降の要素は,ヌル文字の後にあるため無視され表示されません.

[課題8-2]文字列の長さを計ろう.(関数strlen())

[プログラム例8-2]


01: #include <stdio.h>
02: void main(void){
03:     int  n;
04:     char s[12]="abcdefg";
05:
06:     n = strlen( s );
07:     printf( "文字列%sの長さは%dです.", s, n );
08:
09:     s[5] = '\0';
10:     n = strlen( s );
11:     printf( "文字列%sの長さは%dです.", s, n );
12:
13:     getchar();
14: }

行説明
04行目→配列名sをchar型の要素数12に宣言し,文字配列"abcdefg"に初期化します.
06行目→文字配列名sの長さ(ヌル文字の前までの文字数)を算出しnに代入します.
07行目→文字配列sと文字配列sの長さを画面に出力します.
09行目→文字配列sの5番目の要素に'\0'(ヌル文字)を代入します.

[結果8-2]

コンパイル・実行すると次のよう表示されます.
文字列abcdefgの長さは7です.
文字列abcdeの長さは5です.

リターンキーを押すとプログラムは終了します.

文字配列(文字列)の長さはヌル文字('\0')の前までの文字数です.

文字a b c d e f g \0
値 97 98 99 100 101 102 103 0 不定 不定 不定 不定
0番 1番 2番 3番 4番 5番 6番 7番 8番 9番 10番 11番

上図のように,7番目のヌル文字の前までですから,文字数は0番目~6番目の7文字となります.
9行目のs[5]='\0';で強制的にヌル文字を5番目の要素に代入すると下図のようになり,文字数は0番目~4番目の5文字になります.文字配列を含め配列は全て0番目から始まることに注意して下さい.

文字a b c d e \0 g \0
値 97 98 99 100 101 0 103 0 不定 不定 不定 不定
0番 1番 2番 3番 4番 5番 6番 7番 8番 9番 10番 11番

[課題8-3]直接文字配列に好きな文字を代入しよう

[プログラム例8-3]


01: #include <stdio.h>
02: void main(void){
03:   int  i;
04:   char s[12]="Pro*ram+ng";
05:
06:  puts( s );
07:
08:  s[3]='g';
09:  s[7]='i';
10:
11:  puts( s );
12:
13:  getchar();
14: }

行説明
04行目→配列名sをchar型の要素数12に宣言し,文字配列"Programing"に初期化する.
06行目→文字配列sを画面に出力する.
08行目→文字配列sの3番目の要素に直接,文字gを代入します.
09行目→文字配列sの7番目の要素に直接,文字iを代入します.

[結果8-3]

コンパイル・実行すると次のよう表示されます.
Pro*ram+ng
Programing

リターンキーを押すとプログラムは終了します.

 今までは,ヌル文字'\0'の代入を説明していましたが,このように任意の文字を任意の文字配列の要素に直接1つ代入することができます.
 はじめは,Pro*ram+ngと間違っていた文字列が,直接正しい文字を3番目と7番目の要素に代入することによって,正しくProgramingと修正されたことがわかります.

[課題8-4]関数を使って文字列をつけ加えよう.(関数strcat())

[プログラム例8-4]


01: #include <stdio.h>
02: #include <string.h>
03: void main(void){
04:     char s1[80]="\0", s2[80]="\0";
05:
06:     strcpy( s2, "[結合後の文字列]>" );
07:     while(1){
08:         gets( s1 );
09:         if( strlen( s1 )+ strlen( s2 )>60 )
10:             break;
11:         strcat( s2, s1 );
12:         puts( s2 );
13      }
14:     printf( "文字列s1とs2の長さの合計が40を越えました.\n" );
15:     getchar();
16: }

行説明
02行目→関数strcat()など文字列に関する関数を使用するときに必要なインクルードファイルです.
04行目→配列名s1,s2を要素数80の文字配列と宣言します.同時に"\0"で初期化します.(0番目の文字がヌル文字.つまり長さ0文字の文字列.)
06行目→関数strcpy()で文字配列s2に文字列"[結合後の文字列]>"をコピーします.
07~13行目→9行目の文字配列s1とs2の長さの合計が40文字を越えると終了するwhile文です.
08行目→キーボードからリターンキーが押されるまでの1行入力をs1に格納します.
11行目→関数strcat()を使って,文字配列s2の後ろにs1をつけ加えます.
12行目→つけ加えられた結果の文字配列s2を画面に出力します.

[結果8-4]

コンパイル・実行すると次のよう表示されます.

感[リターン印]
[結合後の文字列]>感
ピュータは[リターン印]
[結合後の文字列]>感ピュータは
コンピュータを[リターン印]
[結合後の文字列]>感ピュータはコンピュータを
こえられるか[リターン印]
[結合後の文字列]>感ピュータはコンピュータをこえられるか
????[リターン印]
文字列s1とs2の長さの合計が40を越えました.

リターキーを押すとプログラムは終了します.

キーボードから入力した文字がつけ加えられ出力されることが判ります.
関数strlen()で文字列の長さを判断しながら進め60文字を越えると終了します.日本語(全角文字)は,1つで2文字に数えられます.

[文法9]

1.関数strcpy()


①strcpy( str, "文字列" );
②strcpy( str1, str2 );
str, str1, str2 は文字配列名(char型の配列名)
(1)文字配列をコピーします.(コピー元→コピー先)
①では"文字列"→str,②ではstr2→str1.
(2)コピー先のstr,str1にはコピー後,最後尾にヌル文字'\0'が付けられます.
(3)コピー先のstr,str1はコピー元の"文字列",str2の要素数以上に,配列を宣言しなければなりません (2)コピー先のstr,str1にはコピー後,最後尾にヌル文字'\0'が付けられます..
誤りの例 char str1[5], str2[50]; (str1の方が要素数が少ない)

2.関数strcat()


①strcat( str, "文字列" );
②strcat( str1, str2 );
str,str1,str1はchar型配列
(1)文字配列をコピー先の最後尾につけ加えます.
①では"文字列"→str,②ではstr2→str1.
(2)コピー先のstr,str1にはコピー後,最後尾にヌル文字'\0'が付けられます.
(3)コピー先のstr,str1はコピー元の"文字列",str2の文字数以上に,十分な要素を持つ配列を宣言しなければなりません.

3.関数strlen()

① i = strlen( "文字列" );
② i = strlen( str );
str,str1,str2はchar型配列名
iはint型変数
(1)文字列の長さをカウントして,戻り値をして返します.
(2)カウントはヌル文字'\0'で終了します.(ヌル文字'\0'はカウントしない.)
(3)漢字(全角文字)は2文字とカウントします.
(4)スペース(空白)もカウントします.

4.ヌル文字'\0'について

(1)文字列の終了にはヌル文字'\0'を入れます(文字列が自動的に入ります).
(2)""で囲まれた"文字列"の最後尾にはヌル文字'\0'が自動的に入ります.
(3)文字列に関係する標準関数は,ヌル文字'\0'を文字列の終わりとして利用しています.

このドキュメントは http://icrus.org/c_language_beginers_course/ 上にあります.

2017,1 ssatoh@ 足立工科大学 工学部 情報通信工学科