C言語で文字列を扱う方法を説明します。
文字列
C言語では、文字が複数集まったものを文字列と呼んでいます。
文字列を扱うには、配列の知識が必要なので配列の知識を思い出しておく必要があります。
文字列を扱うために使う配列は、char型の配列です。char型は、int型と同じように整数を扱う変数の型ですが、int型とは違い、主に文字を扱うために使われる整数の型です。
コンピュータで文字は、数字として表現されます。どういうことかというと、ひとつひとつの文字がそれぞれ異なる数字と対応しているということです。
実際に、いくつかの文字を数字として表示してみましょう。
#include <stdio.h>
int main(void)
{
char c1;
char c2;
c1 = 'A';
c2 = 66;
printf("c1の数字: %d\n", c1);
printf("c2の文字: %c\n", c2);
return 0;
}
これを実行すると、「c1の数字: 65」と「c2の文字: B」と表示されるはずです。
数字を表示する際には今まで通り、%d を使いますが、数字から文字を表示する時には %c を使います。
文字を代入する際には、その文字をシングルクォート(’ ‘)で囲む必要があります。
このように、数字と文字、文字と数字が対応していることがわかります。
注意として、C言語のchar型では、英数字と一部の記号を扱うことを前提としているので、ひらがなや漢字などを代入して使うことは難しいです。
では、数字と文字が対応していることがわかったと思うので、文字の集合である文字列について説明していきます。
入力と出力
文字列を入力として受け取って、文字列を扱うための char型の配列に代入して、表示してみましょう。
#include <stdio.h>
int main(void)
{
char str[20];
scanf("%s", str);
printf("入力した文字列: %s\n", str);
return 0;
}
実行すると、19文字以内の文字列を受け取って、そのまま表示します。
最初に、char型の配列である str という変数を用意します。後で説明しますが、要素数が20ということなので、20から1を引いて、最大19文字の文字列を代入することが可能です。
入力には「scanf("%s", str);」のように、scanf関数を使用し、%d や %lf などの代わりに、文字列を入力として受け取るための %s を書き、配列の変数名を書きます。
出力にも「printf(“入力した文字列: %s\n”, str);」のように、%s を書きます。
しかし、この入力には欠点があります。
空白を含む文字列を入力した場合に、空白の前までは入力できるのですが、空白の後の文字列は入力されません。
これはscanf関数を使うのであれば避けては通れないものです。
なので、空白を含めた文字列を入力したい場合は、別の方法を使います。
次の方法では、空白を含めた文字列を入力することが可能です。
#include <stdio.h>
int main(void)
{
char str[20];
fgets(str, 20, stdin);
printf("%s\n", str);
return 0;
}
「fgets(str, 20, stdin);」のように、fgets関数を使うことで空白を含めた文字列を入力することができます。
fgets関数は、かっこ内にカンマで区切って、3つの情報を書きます。
ひとつめは、入力を受け取るchar型の配列です。
ふたつめは、入力の最大文字数です。
みっつめは、stdin です。これは、こういうものだということで、fgets関数を使うときは、最後に stdin を書くというように覚えておきましょう。
fgets関数を使った方法にも、欠点があり、空白だけでなく入力の最後の改行まで入力に含まれます。そのため、表示しようと、改行も入ってしまい、printf関数で \n を使用していると2回改行することになります。
このように、入力に関してつまずきやすい点があるので、気をつけましょう。
文字列の終端
char型の配列で文字列を扱うわけですが、ただ配列を使っているだけでは文字列の終了がどこなのか区別がつきません。
例えば、要素数20の char型の配列に3文字の文字列が代入されていた際に、その文字列が何文字なのかは、客観的には分かりません。
そのため、文字列の最後には、終端文字(別名 Null文字)という文字があります。
終端文字は「\0」のように表現され、今までの改行を表す「\n」と同じように、特殊な文字です。
上のソースコードで要素数が20なのに、最大19文字の文字列しか扱うことができないというのは、文字列の最後には必ず終端文字が一文字入るので、最大19文字ということになっています。
代入と初期化
char型の配列に文字列を代入するには、一文字ずつ文字として代入する必要があります。
#include <stdio.h>
int main(void)
{
char str[20];
str[0] = 'H';
str[1] = 'e';
str[2] = 'l';
str[3] = 'l';
str[4] = 'o';
str[5] = '\0';
printf("%s\n" str);
return 0;
}
最後に終端文字を代入するのを忘れないようにしましょう。
さらに、char型の配列で初期化をする場合はこのようにします。
#include <stdio.h>
int main(void)
{
char str[] = "Hello";
printf("%s\n", str);
return 0;
}
文字列は、ダブルクォーテーション(" “)で囲って表します。
「str = “Hello”;」のようにして、文字列の場合、配列を用意するところで代入することが可能です。
他の配列と違い、中かっこで囲む必要はありません。
操作
文字列を扱っていると、その文字列をコピー、比較、連結、さらに文字列の長さを知りたいということがあります。
それらの方法について説明します。
#include <string.h>
これから説明することを行いたい場合は、必ずソースコードの上の方に、「#include <string.h>」を追加して、このようにする必要があります。
#include <stdio.h>
#include <string.h>
int main(void)
{
return 0;
}
これを書いていないと、コンパイルエラーとなり、実行ファイルが作成されません。
なぜこれが必要なのかは、ここでは説明しません。
コピー
文字列をコピーするには、strcpy関数というものを使用します。
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[20] = "Hello";
char str2[20];
strcpy(str2, str1);
printf("%s\n", str2);
return 0;
}
「strcpy(str2, str1);」の部分で文字列のコピーをしています。
strcpy関数は、かっこの中にカンマで区切って2つの情報を書きます。
ひとつめは、コピー先の配列です。こちらにコピーされた文字列が代入されます。
ふたつめは、コピー元の配列です。こちらの文字列がコピーされてコピー先の配列に代入されます。
「strcpy(str2, “Hello”);」のようにして、直接文字列を指定することもでき、文字列を代入したいと言う場合は、このように使用します。
比較
文字列の比較は、strcmp関数というものを使用します。
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[20] = "Hello";
char str2[20] = "Thank";
if (strcmp(str1, str2) < 0) {
printf("%sは%sより小さいです\n", str1, str2);
} else if (strcmp(str1, str2) == 0){
printf("%sと%sは同じ文字列です\n", str1, str2);
}
else {
printf("%sは%sより大きいです\n", str1, str2);
}
return 0;
}
「strcmp(str1, str2);」の部分で比較をしています。
strcmp関数は、かっこの中にカンマで区切って2つの情報を書きます。
2つの情報はそれぞれ比較したい文字列の配列です。
比較は、辞書順と呼ばれる方法で行われ、辞書順は辞書で1ページから順に調べて先に出てくる方が小さいというルールで、比較します。なので、abc と bcd を比較すると abc の方が辞書で最初に見つかるため、小さいとなります。さらに、大文字と小文字を比べると、abc と BCD の場合 大文字の方が先になるので、BCD が小さいとなります。
strcmp関数を使って比較をする場合、ひとつめに書いた配列の文字列がふたつめに書いた配列の文字列よりも小さいのであれば 「strcmp(str1, str2) < 0」のように、0 より小さいかを判定します。
等しい場合は「strcmp(str1, str2) == 0」のように、0 と等しいかを判定します。
ひとつめに書いた配列の文字列がふたつめに書いた配列の文字列より大きいのであれば 「strcmp(str1, str2) > 0」のように、0 より大きいかを判定します。
連結
文字列を繋げることを連結といい、連結をするにはstrcat関数を使用します。
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[20] = "Hello";
char str2[20] = "world";
strcat(str1, str2);
printf("%s\n", str1);
return 0;
}
「strcat(str1, str2);」の部分で連結をしています。
strcat関数は、かっこの中にカンマで区切って2つの情報を書きます。
ひとつめは、連結元の文字列の配列です。この文字列の末尾に文字列が連結されます。
ふたつめは、連結する文字列の配列です。この文字列がひとつめの文字列の末尾に連結されます。
文字列の長さ
文字列の長さを調べるには、strlen関数を使用します。
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[20] = "Hello";
int len;
len = strlen(str1);
printf("%d\n", len);
return 0;
}
「strlen(str1);」の部分で文字列の長さを調べています。
strlen関数は、かっこの中に調べたい文字列の配列を指定します。
そして、イコールを使って int 型などの数字を扱う変数などに結果を代入して利用します。
終端文字は、文字列の長さに含まれませんが、fgets関数を使った時の入力に含まれる改行は、文字列の長さに含まれます。
まとめ
文字列は、int 型や double型などの数値と比べて、扱いにくいです。
しかし、一度覚えてしまえばそれほど難しくないと思います。
自分自身で色々と書き換えて、どのような動作をするのか覚えていきましょう。