こんにちは! フリーエンジニアの長瀬です。
今回は文字列を比較する方法についていっしょに学んでいきましょう。文字列の比較にはstrcmpやstrncmpという関数を使います。ストリングコンペアーと読みます。
strはstring(文字列)、cmpはcompare(比べる)の省略でnはnumber(数)です。つまり、strcmpは文字列を比べるという意味で、strncompはn文字分だけ文字列を比べるという意味です。
この記事では、文字列を比較する方法について1文字だけを比較する方法という基本的な内容から、
- strcmpで文字列を比較する方法
- strncmpで範囲を指定して文字列を比較する方法
といった応用的な内容についても解説していきます。
1文字だけを比較する方法
通常、文字列を比較する場合、strcmpやstrncmp関数を使います。なので、等価演算子(==)を使用して比較をすることはないです。
ですが、文字列の中の特定の1文字を比較する場合は、後述するstrncmp関数で1文字分だけ比較するよりも等価演算子を使って比較した方がよりシンプルな記述ができます。つまり、1文字比較するだけなら、わざわざstrncmp関数を使うまでもないということです。
また、等価演算子だけではなく、文字の比較では文字に割り当てられた文字コードという整数値を使って、文字が等しいかどうかを判別します。文字コードとは文字に割り当てられたある整数値のことです。(例 k=107,s=115)
それでは、サンプルコードで確認していきましょう。
#include<stdio.h> int main(void) { char s[] = "samurai"; //uが文字の配列s[]の3番目の要素uと一致するかどうか printf("uの文字コードは%d\n",'u'); printf("s[3](u)の文字コードは%d\n",s[3] ); if('u' == s[3]){ printf("uはs[3]と一致します。\n"); } else{ printf("uはs[3]と一致しません。\n"); } //sが文字の配列s[]の3番目の要素uと一致するかどうか printf("sの文字コードは%d\n",'s'); printf("s[3](u)の文字コードは%d\n",s[3] ); if('s' == s[3]){ printf("sはs[3]と一致します。\n"); } else{ printf("sはs[3]と一致しません。\n"); } return 0; }
uの文字コードは117 s[3](u)の文字コードは117 uはs[3]と一致します。 sの文字コードは115 s[3](u)の文字コードは117 sはs[3]と一致しません。
1文字だけの比較の場合は等価演算子を使うことでシンプルに比較することができます。また、このように文字を比較する場合はすべて文字コードの整数値を使って比較しています。strncmp関数を使って、1文字比較する場合も後述するので、このコードと比較してみてください。
strcmpで文字列を比較する方法
それではstrcmp関数での文字列の比較を説明します。strcmp関数は第1引数と第2引数に、それぞれ比較したい文字列のchar型オブジェクトのポインタの定数値をとります。ポインタの値をとるので、引数にはポインタの値を渡してください。
ポインタではない値を渡してしまうことがよくあります。C言語では文字列は文字の配列になっているので、比較の過程では文字列の先頭から順番に文字コードの整数値を使って比較していきます。
そして、最後まで値が等しいなら0。途中で文字コードの値が違っていたなら、その時点でそれぞれの文字コードを比較してプラスかマイナスの値を返します。
返す値は実行環境の文字コードの値によって
- 第1引数 < 第2引数 の場合はマイナスの値
- 第1引数 > 第2引数 の場合はプラスの値
- 第1引数 = 第2引数 の場合は0
を返します。文字コードの値は大文字と小文字で違い、小文字のほうが大文字よりも大きな値をとります。(例 A=65 < a=97)
なので、文字コードの大小によって大文字か小文字かの区別ができます。文字列が一致していた場合はどの実行環境でも等しく0で問題ないですが、一致しなかった場合の値は実行環境によって異なるので、文字がどれだけ離れているかの判定には使いません。
というのも、実行環境によって異なっていては、動作もそれぞれで異なってしまうからです。なので、文字列が等しいかどうか判定する場合、等しければ0を返すという性質を使います。また、strcmp関数は文字列全体を比較するので、文字列の何番目かを指定して比較はできません。
それではstrcmp関数の使い方をサンプルコードで確認していきましょう。
#include<stdio.h> #include<string.h> //strcmp、strncmp関数を使うために必要 int main(void) { char *s1 = "SAMURAI"; char *s2 = "samurai"; char *s3 = "samurai"; char *s4 = "samurao"; //s1(SAMURAI)とs2(samurai)が同じ値かどうか if(strcmp(s1,s2)==0){ printf("s1(=SAMURAI)とs2(=samurai)は同じ値です。\n"); }else{ printf("s1(=SAMURAI)とs2(=samurai)は同じ値ではありません。\n"); } //s2(samurai)とs3(samurai)が同じ値かどうか if(strcmp(s2,s3)==0){ printf("s2(=samurai)とs3(=samurai)は同じ値です。\n"); }else{ printf("s2(=samurai)とs3(=samurai)は同じ値ではありません。\n"); } //s3(samurai)とs4(samurao)が同じ値かどうか if(strcmp(s3,s4)==0){ printf("s3(=samurai)とs4(=samurao)は同じ値です。\n"); }else{ printf("s3(=samurai)とs4(=samurao)は同じ値ではありません。\n"); } //s3(samurai)とs4(samurao)の比較 printf("第1引数 < 第2引数の場合 %d\n",strcmp(s3, s4)); printf("第1引数 > 第2引数の場合 %d\n",strcmp(s4, s3)); printf("第1引数 = 第2引数の場合 %d\n",strcmp(s3, s3)); return 0; }
s1(=SAMURAI)とs2(=samurai)は同じ値ではありません。 s2(=samurai)とs3(=samurai)は同じ値です。 s3(=samurai)とs4(=samurao)は同じ値ではありません。 第1引数 < 第2引数の場合 -6 第1引数 > 第2引数の場合 6 第1引数 = 第2引数の場合 0
このように文字列全体の比較をする場合にはstrcmp関数を使って返り値が0かどうかで文字列が等しいかどうかを判定します。また、それぞれ異なっていた場合、異なっていた時点の文字コードの大小によってマイナスかプラスの値を返します。
このサンプルコードではsamuraiとsamuraoの最後の文字iとoの文字コードが比較されました。
strncmpの使い方
strncmpで範囲を指定して文字列を比較する方法
次はstrncmp関数の説明です。strcmp関数とnが違うだけなので見間違えないようにしてください。strncmp関数の第1引数と第2引数は前述したstrcmp関数と同じです。
つまり、それぞれ比較したい文字列のchar型オブジェクトのポインタの定数値をとります。strncmp関数はそれに加えて、第3引数に比べる文字の数を指定することができます。それでは、数を指定して文字列を比較する方法をサンプルコードで確認していきましょう。
#include<stdio.h> #include<string.h> //strcmp、strncmp関数を使うために必要 int main(void) { char *s1 = "likes"; char *s2 = "liked"; //s1とs2の4番目までの文字が同じ値かどうか if(strncmp(s1,s2,4)==0){ printf("s1とs2の4番目までの文字は同じ値です。\n"); }else{ printf("s1とs2の4番目までの文字は同じ値ではありません。\n"); } //s1とs2の5番目までの文字が同じ値かどうか if(strncmp(s1,s2,5)==0){ printf("s1とs2の5番目までの文字は同じ値です。\n"); }else{ printf("s1とs2の5番目までの文字は同じ値ではありません。\n"); } return 0; }
s1とs2の4番目までの文字は同じ値です。 s1とs2の5番目までの文字は同じ値ではありません。
このようにstrncmp関数を使えば、4番目までの文字likeは同じで、likesとlikedは違うということを判定することができます。
strncmpで1文字だけを比較する方法
次に前述した1文字だけ比較する場合をあえて等価演算子を使わずにstrncmp関数の第3引数を1にして計算してみます。サンプルコードは以下の通りです。
#include<stdio.h> #include<string.h> //strcmp、strncmp関数を使うために必要 int main(void) { char *s = "samurai"; //uが配列s[]の3番目の要素uと一致するかどうか if(strncmp("u",&s[3],1)==0){ printf("uはs[3]と一致します。\n"); } else{ printf("uはs[3]と一致しません。\n"); } //sが配列s[]の3番目の要素uと一致するかどうか if(strncmp("s",&s[3],1)==0){ printf("sはs[3]と一致します。\n"); } else{ printf("sはs[3]と一致しません。\n"); } return 0; }
uはs[3]と一致します。 sはs[3]と一致しません。
このように等価演算子を使った場合と比較してみると、コードが冗長なことがわかります。なので、特定の1文字だけを比較する場合は等価演算子を使います。
文字列の使い方総まとめ
この記事では紹介しきれなかった文字列のいろいろな使い方を次の記事にまとめているので、ぜひ確認してください!
まとめ
いかがでしたでしょうか?この記事では、文字列を比較する方法を解説しました。文字列の比較はstrcmpとstrncmp関数を使えば、簡単にできます。
文字コードの整数値を巧みに使って比較していることを忘れないでください。実際は割り当てられた整数値を使って比較しています。ユーザーが入力した値と一致しているかどうかという場合によく文字の比較は使われます。
もし、文字列の比較について忘れてしまったらこの記事を確認してくださいね!