見出し画像

C言語教室 第8回 - 文字列を扱う標準ライブラリ

C言語で文字列を扱う処理は頻繁に出てくるので、いくつかの処理に対して標準ライブラリに関数が用意されています。これらは言語自身ではないのですが規格として動作が規定されているので、安心して使うことが出来ます。

標準Cライブラリ

今回は「文字列」を対象としたstring.hに含まれる関数を対象とします。

C言語/標準ライブラリ/string.h

  • size_t strlen(const char *s)

最初は文字列の長さを返す strlen です。引き数に文字列の先頭を指すポインタを渡すと、そこから終端文字を見つけるまでの長さを返します。長さに終端文字は含まれないので ”abc” の長さは3になります。

  • char *strcpy(char * restrict s1, const char * restrict s2)

  • char *strncpy(char * restrict s1, const char * restrict s2, size_t n)

最初の引き数で渡した確保した領域の先頭へのポインタの指す先に、次の引き数で渡したポインタで始まる始まる文字列をコピーします。strcpy はコピー元の文字列をすべてコピーしますが、strncpy は最後の引き数で指定した長さまでしかコピーされません。長さを指定するので確保した領域の大きさを超えることがありません。またコピー元が指す文字列が指定した長さより短い場合、コピー先が指す文字列の後ろに、全体で指定した長さになるまでNULL文字を付加します(丁度の場合はNULLが付加されないことに注意)。

  • char *strcat(char * restrict s1, const char * restrict s2)

  • char *strncat(char * restrict s1, const char * restrict s2, size_t n)

最初の引き数で渡した文字列の後ろに、次の引き数で渡した文字列を連結します。最初の引き数で渡した文字列は、連結したサイズまでの領域が確保されている必要があります。strcat はコピー元の文字列をすべて連結しますが、strncat は最後の引き数で指定した長さまでしか連結されません。長さを指定するのでコピー先の領域で確保されている大きさを超えないように出来ます。またコピー元が指す文字列が指定した長さより短い場合、コピー先が指す文字列の後ろに、全体で指定した長さになるまでNULL文字を付加します(丁度の場合はNULLが付加されないことに注意)。

  • int strcmp(const char *s1, const char *s2)

  • int strncmp(const char *s1, const char *s2, size_t n)

最初の引き数で渡した文字列と、次の引き数で渡した文字列に対して、先頭の文字から順に文字コードを比較して、大きい場合は0より大きい整数、等しい場合は0、小さい場合は0より小さい整数を返す。strcmp はすべての文字列を比較しますが、strncmp は最後の引き数で指定した長さまでを比較します。文字列の長さが異なる場合は終端文字との比較で大小が決まるので、短いほうが小さくなります。

ここまでは難しくはないと思います。整数と同じように演算子で比較できれば簡単なのですが、C言語の文字列は型ではなく文字の配列なので、このような関数を呼ぶ必要があるのです。


さて、ここからは少しだけ難しいかもしれませんが、文字列の中から特定の条件で文字や文字列を探す関数があります。何かとお世話になることが多そうなものだけを取り上げます。

  • char *strchr(const char *s, int c)

  • char *strrchr(const char *s, int c)

最初の引き数で渡した文字列に、次の引き数で渡した「文字」が見つかったときに、その位置を示すポインタを返します。strchr は最初に見つかった位置、strrchr は最後に見つかった位置になります。文字が見つからない場合はNULLを返します。ここで文字を渡す時の型が整数なのですが、文字として扱われます。

  • char *strpbrk(const char *s1, const char *s2)

最初の引き数で渡した文字列に、次の引き数で渡した「文字の集合」に含まれるいずれかの文字が見つかったときに、見つかった最初の位置に対するポインタを返します。最後までどの文字も見つからない場合はNULLが返ります。2番めの引き数の型は文字列へのポインタですが、この文字列と一致する場所を探すわけではありません。”abc” から “cd” を探せば3文字目に”c”があるので、ここへのポインタが返ります。

  • char *strstr(const char *s1, const char *s2)

最初の引き数で渡した文字列に、次の引き数で渡した文字列が含まれていれば、最初に見つかった先頭へのポインタを返します。見つからなければNULLが返ってきます。2番めの引き数で渡した文字列の長さが0の場合、先頭の文字で必ず合致することになり、最初の引き数で渡したポインタと同じ値が返ることになります。

他にも str で始まるものがいくつかあります。また終端文字によらず、サイズのみで処理を行う mem で始まる関数もあります。さらに日本語などマルチバイト文字の文字列を扱う場合には、これらとは別の特別な関数が用意されていることもあります。ここで挙げた以外の文字列処理関数も標準化されているものは大丈夫ですが、便利なものを見つけても環境によって使えたり使えなかったり、微妙に仕様が異なることもあるので、リファレンスを確認してから使いましょう。


標準の文字列処理関数で充分かと言えば、微妙に足りないこともあり、必要に応じて、これらを組み合わせて、または全くのオリジナルで関数を作ることもシバシバです。ただ標準ライブラリは良く実装が検討されているので、可能な限りこれらを使うことを薦めます。

ところで、関数の說明の中に const とか restrict という文字が出てきていますが、const char* は、関数の中で、ここで使われたポインタを指す先の文字列が変更「されない」ことを示し(const が無ければ変更されることが前提なわけです)、restrict はポインタの指す先の文字列が重複「していない」ことを示しています。重複とは”abcdef” というひとつの文字列に対してaを指すポインタとcを指すポインタを渡すと、これらはcdefの部分を共有していることになるので重複しているということになります。普通はこういう使い方はしないのですが、そのような使い方をしてはいけないということになります。また size_t は「大きさ」「長さ」といった負にならない整数を意味する型です。

文字列操作と文字操作関数

文字操作・入出力ライブラリの使い方を理解しよう

いろいろな関数を紹介しましたが、自分でコードを書いて実装できるくらいに理解した上で、便利に使ってください。

次回は、說明を後回しにしていた演算子についてです。


課題

・最初の引き数で渡した領域に、2番めと3番めの文字列を連結した文字列を返す関数を書きなさい。なお最初の引き数の領域は呼び出し側で確保しておくものとします。
・2つの引き数で渡した文字列を関数内で動的に確保した領域に連結した文字列として返す関数を書きなさい。

なお、標準ライブラリの関数は必要に応じて使ってください。

ヘッダのイラストは、以下にあるものを使わせて頂きました。
https://www.irasutoya.com/2015/12/blog-post_610.html

この記事が気に入ったらサポートをしてみませんか?