Quantcast
Channel: プログラミング
Viewing all articles
Browse latest Browse all 7950

C言語の文字列操作のライブラリ関数について解説 - 水瓶座列車

$
0
0

 

C言語の文字列操作は、C++と比較すると面倒ですが、

ライブラリ関数を知っているだけでも、かなり楽になります。

 

C言語の入門書には、ライブラリ自体の説明があったとしても、

どのようなライブラリがあるか、ライブラリにどのような関数があるかなど、

詳細については、ほとんど記載されていません。

自分で、ライブラリというキーワードにたどり着いて、初めて学ぶべき事項がわかります。

ここでは、C言語の文字列操作ライブラリのの使用頻度が高い関数について、解説していきます。

 

 

 

 

 

1.文字列操作のライブラリについて

 

ライブラリを使用するには、ヘッダファイルをインクルードする必要があります。

文字列操作関連のライブラリを使用するには、必要に応じて下表のヘッダファイルをインクルードします。

ヘッダファイル名説明
string.h文字列処理やメモリ関連の関数
ctype.h文字の種類チェックや文字変換の関数
stdlib.h文字列変換や少しの数学関連の関数

 

上表のように、以外に、においても、

文字や文字列を扱うライブラリ関数があります。

ここでは、このようなライブラリが存在するということだけ知っておいてください。

 

 

2.文字列操作のライブラリ関数一覧

 

で、よく使用する文字列操作のライブラリ関数を一覧表にしました。

関数名説明
strlen指定した文字列の文字数を数える。
strcpy文字列を別の配列にすべて上書きコピーする。
strncpy文字列の先頭から指定された文字数分を別の配列に上書きコピーする。
strcat文字列の後ろに、別の配列の文字列を結合する。
strncat文字列の後ろに、別の配列の文字列の先頭から指定された文字数分を結合する。
strcmp2つの文字列を比較する。
strncmp文字列と別の配列の先頭から指定された文字数分を比較する。
strchr文字列から指定された文字を探す。
strstr文字列から指定された文字列を探す。

 

 

3.文字列操作のライブラリ関数のプログラム例

 

 

3.1 strlen() の使い方

 

strlen() の仕様は下表です。

書式int strlen( const char* )
関数名strlen第一引数の文字数を数える。( '\0'は文字数に含まない)
戻り値int第一引数の文字数
第一引数char*文字数を数えたい配列ポインタ

 

strlen() を使い方は、下記のような感じです。

#include 
#inlucde #define SIZE 20
void main (){   char str[SIZE] = "original";

  int ret = strlen(str);
  printf("str length = %d\n", ret); }

 

strlen() は、引数の変数のバッファーサイズではなく、格納されている文字数を調べるのに使用します。

注意することは、strlen()で戻り値には、'\0'(ヌル文字)を含みません。

 

 

3.2 strcpy(),  strncpy() の使い方

 

strcpy() の仕様は下表です。

書式char* strcpy( char* , const char* )
関数名strcpy第二引数の文字列を第一引数の配列にコピーする。
(元からある文字列は、完全に上書きされる。)
戻り値char*第一引数の配列ポインタ
第一引数char* コピーされる側の配列ポインタ
第ニ引数const char*コピー元の配列ポインタ

 

strncpy()の仕様は下表です。

書式char* strncpy( char*, const char, size_t )
関数名strncpy第二引数の先頭から第三引数で指定された文字数分を
第一引数の先頭からコピー(上書き)する。
戻り値char*第一引数の配列ポインタ
第一引数char*コピーされる配列ポインタ
第ニ引数const char*コピー元の配列ポインタ
第三引数size_t先頭から数えてコピーする文字数

 

strcny() とstrncpy() を使い方は、下記のような感じです。

#include 
#inlucde #define SIZE 20
void main (){   char str[SIZE] = "original";
  char str2[SIZE] = "second";
  char str3[SIZE] = "third";
  char* ret;
  printf("str = %s\n", str);
  printf("str2 = %s\n", str2);
  printf("str3 = %s\n", str3);

  if( sizeof(str2) >= strlen(str)+1 ) {
   ret = strcpy(str2, str);
   printf("str = %s\n", str);
     printf("str2 = %s\n", str2);
  }
  else {
   printf("error: str2 buffer over flow!\n");
  }

  if( sizeof(str3) >= strlen(str)+1 ) {
    ret = strncpy(str3, str, 3);
    printf("str = %s\n", str);
    printf("str3 = %s\n", str3);
  }
  else {
    printf("error: str3 buffer over flow!\n");
  }

}

 

これらの関数を使用する際に注意することは、

第二引数のバッファーサイズが第一引数と同じか大きくなければなりません。

第二引数のバッファーサイズが第一引数より小さい場合、実行時にエラーにはなりませんが、

バッファーオーバーフローとなり、意図しないメモリ破壊が発生してバグの原因になります。

バッファーオーバーフローとなっても、C言語のエラーが発生しませんので、

バグを発見することが困難になります。プログラムを組む際に気を付ける必要があります。

 

また、各関数の戻り値はありますが、ほぼ使用することはありません。

何故かというと、返却値はコピー先の先頭ポインタなのですが、

関数実行後は、コピー先の先頭ポインタを指す配列名をそのまま使用するからです。

 

 

3.3 strcat(), strncat()の使い方

 

strcat() の仕様は下表です。

書式char* strcat( char* , const char* )
関数名strcat第一引数に第二引数を連結する。
戻り値char*第一引数の配列ポインタ
第一引数char*連結される配列ポインタ
第ニ引数const char*連結する配列ポインタ

 

strncat() の仕様は下表です。

書式char* strncat( char*, const char*, size_t )
関数名strncat第二引数の先頭から第三引数の文字数分を第一引数の後ろに連結する。
戻り値char*第一引数の配列ポインタ
第一引数char*連結される配列ポインタ
第ニ引数const char*連結する配列ポインタ
第三引数size_t先頭から数えて、連結する文字数

 

strcat() とstrncat() を使い方は、下記のような感じです。

#include 
#inlucde #define SIZE 20
void main (){   char str[SIZE] = "original";
  char str2[SIZE] = "second";
  char str3[SIZE] = "third";
  char* ret;
  printf("str = %s\n", str);
  printf("str2 = %s\n", str2);
  printf("str3 = %s\n", str3);

  if( sizeof(str2) > strlen(str2)+strlen(str)+1 ) {
    ret = strcat(str2, str);     printf("str = %s\n", str);
    printf("str2 = %s\n", str2);
  }
  else {
    printf("error: str2 buffer over flow!\n");
  }

  if( sizeof(str3) > strlen(str)+4 ) {
    ret = strncat(str3, str, 3);
    printf("str = %s\n", str);
    printf("str3 = %s\n", str3);
  }
  else {
    printf("error: str3 buffer over flow!\n");
  }
}

 

この関数を使用する場合は、文字連結後の文字数が、第一引数のバッファーサイズを超えないように、

連結前にstrlen() で、文字数を調べておく必要があります。

文字列結後の文字数が第一引数のバッファーサイズを超えるとバッファーオーバーフローとなり、

バグの原因になります。

また、バッファーオーバーフローとなっても、C言語のエラーが発生しませんので、

バグを発見することが困難になります。プログラムを組む際に気を付ける必要があります。

 

 

3.4 strcmp(), strncmp() の使い方

 

strcmp() の仕様は下表です。

書式int strcmp( const char*, const char* )
関数名strcmp第一引数と第二引数の文字列を比較する。
戻り値int2つの文字列が同一の場合は、0を返す。
2つ文字列を比較して異なる場合、
第一引数が第二引数よりアルファベット順で先にくる場合は、負の値、
後にくる場合は正の値を返す。
第一引数const char*比較したい文字列の配列ポインタ
第ニ引数const char*比較したい文字列の配列ポインタ

 

strncmp() の仕様は下表です。

書式char* strncmp( const char*, const char*, size_t )
関数名strncmp第二引数の先頭から第三引数で指定された文字数分と第一引数を比較する。
戻り値char*2つの文字列が同一の場合は、0を返す。
2つ文字列を比較して異なる場合、
第一引数が第二引数よりアルファベット順で先にくる場合は、負の値、
後にくる場合は正の値を返す。
第一引数const char*比較したい文字列の配列ポインタ
第ニ引数const char*比較したい文字列の配列ポインタ
第三引数size_t先頭から数えて、比較する文字数

 

strcmp() とstrncmp() を使い方は、下記のような感じです。

#include 
#inlucde #define SIZE 20
void main (){   char str[SIZE] = "original";
  char str2[SIZE] = "none";
  char str3[SIZE] = "none1234";
  int ret = -999;
  printf("str = %s\n", str);
  printf("str2 = %s\n", str2);
  printf("str3 = %s\n", str3);
  ret = strcmp(str2, str);
  if( !ret ) {
    printf("same word\n");
  }
  else {
    printf("not same word\n");
  }
  printf("str2 = %s\n", str2);
  printf("str3 = %s\n", str3);   ret = strncmp(str3, str2, 3);
  if( !ret ) {
    printf("same word\n");
  }
  else {
    printf("not same word\n");
  }
}

 

よく使用する使い方としては、戻り値が0か0以外かで、判定して分岐処理を行うことが多いです。

戻り値を変数に格納する場合は、変数の初期値は、-999など、

strcmp()/strncmp() が、絶対に返却しないであろう値に設定置くと良いです。

また、下記のように、戻り値を変数に格納せずに、直接判定するやり方の方が良いです。

if( !strcmp( str2, str ) ){
  ・・・・
}

 

 

3.5 strchr(), strstr() の使い方

 

strchr() の仕様は下表です。

書式char* strchr( const char* , int )
関数名strchr文字列の中から指定した文字を検索する。
戻り値char* 指定した文字を発見した場合は、その位置のポインタを返す。
発見できなかった場合は、nullを返す。
第一引数const char* 指定した文字を検索する文字列
第ニ引数int検索したい文字

 

strstr() の仕様は下表です。

書式char* strstr( const char* , const char* )
関数名strstr第一引数の文字列の中から第二引数の文字列を検索する。
戻り値char*指定した文字を発見した場合は、その位置のポインタを返す。
発見できなかった場合は、nullを返す。
第一引数const char* 指定した文字を検索したい文字列
第ニ引数const char*検索したい文字列

 

strchar() とstrstr() を使い方は、下記のような感じです。

#include 
#inlucde #define SIZE 20
void main (){   char str[SIZE] = "original";
  char str2[SIZE] = "second";
  char* ret;
  printf("str = %s\n", str);
  ret = strchr(str, 'g');
  printf("ret = %s\n", ret);

  printf("str2 = %s\n", str2);   ret = strstr(str2, "ne");   printf("ret = %s\n", ret); }

 

 

4.文字列操作関数を使用する場面

 

ライブラリの文字列操作関数を使用する場面は、

・大量のテキストファイルを読み込んで、文字列を処理する。

・名簿アプリで、キーワードでの検索してリスト化する。

・シリアル通信時の文字列データを整形する。

など、様々です。

 

 

5.最後に

 

文字列操作の処理は、自分で関数化することもできますが、

どのようなライブラリ関数があるかを知っておくだけでも、プログラムがやりやすくなります。

また、には、ここでは解説していないライブラリ関数もありますので、

どのような関数があるのか、自分で調べてみると新たな発見があると思います。

 

 

<関連・おすすめ記事>

Linux勉強用の中古パソコンおすすめショップランキング - 水瓶座列車

C言語の始め方と基本構造、コンパイルから実行までを解説 - 水瓶座列車

C言語のデータ型と変数、関数について解説 - 水瓶座列車

C言語の繰り返し構文( while, do while, for )の解説と応用 - 水瓶座列車

C言語の演算子と優先順位の解説 - 水瓶座列車

C言語の構造体について解説 - 水瓶座列車

 

 

 

 


Viewing all articles
Browse latest Browse all 7950

Trending Articles