【独学C言語入門⑪】文字列について学ぼう

今回は《文字列について学ぼう》というテーマで記事をまとめます。

「文字列」は、多くのC言語プログラムで必須の知識・技術なのでしっかり習得しておきましょう!

尚、現在執筆中のC言語入門記事は以下の人を対象としています。

  • プログラミング未経験の人
  • C言語プログラミングの学習をこれから始めたい人
  • C言語プログラミングの学習を始めたばかりの人

文字列について学ぼう

文字列について学ぼう

文字列とは

C言語における文字列とは『char型の配列』です。「文字の配列」なので「文字列」と呼ばれます。

C言語における文字列は通常の配列と違い、「最後に終端文字(ヌル文字)である'¥0'を設定する」という約束が義務付けられています。つまり、実際には格納したいテキストの文字数に1を加えたサイズ分の配列が必要となるワケです。

また、文字列操作に特化した関数がいくつか用意されているので、それも併せて解説したいと思います。

変数定義と使用・表示方法

『文字列』の変数定義と使用方法は基本的に配列と同じです。

char 変数名[文字数];
変数名[添字] = '文字';

文字列の表示(printf関数)

文字列の表示は、通常の配列と違ってループ制御文と組み合わせる必要はありません。

printf関数に『%s』を指定して表示することができます。

printf( "str = \"%s\"", str );

サンプルを用意したので実行してみてください。

#include <stdio.h>

void main() {
    char str[4];

    str[0] = 'a';
    str[1] = 'b';
    str[2] = 'c';
    str[3] = '\0';

    printf( "str = \"%s\"\n", str );
}

文字列の初期化

文字列の初期化は通常の配列と同じ方法に加えて、専用の初期化方法が実装されています。書式は次のようになります。

char str[4] = "abc";

また、文字列はあくまで「文字の配列」なので、配列と同じ方法でも初期化できます。

char str[4] = { 'a', 'b', 'c', '\0' };

要素数を省略して初期化

文字列も配列同様、要素数を省略して初期化することができます。

char str[] = "abc";

この場合、strの要素数は4個(3文字+終端文字)となります。

要素数より少ない数の初期値を指定

文字列も配列同様、定義されている要素数よりも少ない数の初期値を指定することもできます。例えば、次のような場合です。

char str[6] = "abc";

上記サンプルの場合、strの0~2番目は各初期値、3番目は終端文字が代入され、4~5番目は初期化されていない状態となります。(開発環境によっては、初期化されていない変数は『どんな値が格納されているかわからない状態』となるので注意してください。)

文字列操作の標準関数

C言語には、次のような機能を持つ文字列操作用の標準関数が用意されています。

  • 文字列のコピー【strcpy】
  • 文字列長の取得【strlen】
  • 文字列の比較【strcmp】
  • 文字列の連結【strcat】

ここでは、これらの標準関数の使い方について解説します。

関数を使用する為に

文字列操作の標準関数を使う際には「string.h」をインクルードする必要があります。

具体的にはCソースファイルの冒頭に以下を記述します。

#include <string.h>

文字列のコピー【strcpy】

文字や数値などの通常の変数は「=」で値を代入してコピーできますが、文字列は「=」でコピーすることができません。

文字列をコピーしたい場合はstrcpy関数を使用します。関数定義は次のようになります。

char *strcpy(char *strDest, const char *strSrc);

strSrc変数の値をstrDest変数にコピーします。

尚、strcpy関数を使用するにあたって注意点が1つあります。strSrc変数の文字数(終端文字含む)がstrDest変数の要素数を超えないようにしなければなりません。超えるように指定した場合、プログラムが異常動作したり、クラッシュしたりする危険性があります。

サンプルを用意しました。実行してみてください。

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

void main(){
    char str1[10] = "aaa";
    char str2[10] = "bbb";
    char str3[10] = "ccc";

    strcpy( str1, str2 );
    strcpy( str3, "abc" );

    printf( "str1 = \"%s\"\n", str1 );
    printf( "str2 = \"%s\"\n", str2 );
    printf( "str3 = \"%s\"\n", str3 );
}

※補足※ 1行目のコードについて

実はstrcpy関数は古い関数で、この関数のセキュリティ強化版(strcpy_s関数)が実装されています。最新のVisualStudioでは、デフォルト設定で危険な関数を使用することを禁止していて、コンパイルエラーとなります。

1行目の『#define _CRT_SECURE_NO_WARNINGS』は「セキュリティ面の問題を理解した上で古い関数を使用します」という宣言であり、これを記述することでコンパイルエラーが発生しなくなります。

文字列の比較【strcmp】

文字や数値などの通常の変数は比較演算子(==, <, >等)を用いて値を比較できますが、文字列では同様の方法で比較することができません。

文字列を比較したい場合はstrcmp関数を使用します。関数定義は次のようになります。

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

s1変数とs2変数を比較し、その結果を戻り値として返します。その比較結果と戻り値のパターンは次のようになります。

比較結果戻り値
s1がs2より小さい場合負の整数(-1)
s1とs2が等しい場合0
s1がs2より大きい場合正の整数(1)

文字列の一致判定プログラムのサンプルを用意しました。実行してみてください。

#include <stdio.h>
#include <string.h>

void main(){
    char str1[] = "abc";
    char str2[] = "abc";
    char str3[] = "xyz";

    if( strcmp( str1, str2 ) == 0 ){
        printf( "str1 と str2 は同じ文字列です。\n" );
    }
    else{
        printf( "str1 と str2 は異なる文字列です。\n" );
    }

    if( strcmp( str1, str3 ) == 0 ){
        printf( "str1 と str3 は同じ文字列です。\n" );
    }
    else{
        printf( "str1 と str3 は異なる文字列です。\n" );
    }

    if( strcmp( str1, "abc" ) == 0 ){
        printf( "str1 と \"abc\" は同じ文字列です。\n" );
    }
    else{
        printf( "str1 と \"abc\" は異なる文字列です。\n" );
    }

}

文字列の連結【strcat】

複数の文字列を連結するにはstrcat関数を使用します。関数定義は次のようになります。

char *strcat(char *s1, const char *s2);

s1変数の後ろにs2変数を連結します。

尚、strcat関数もstrcpy関数同様、使用するにあたっての注意点が1つあります。連結後の文字数(終端文字含む)がs1変数の要素数を超えないようにしなければなりません。超えるように指定した場合、プログラムが異常動作したり、クラッシュしたりする危険性があります。

それでは、サンプルを用意したので実行してみてください。

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

void main(){
    char str1[10] = "aaa";
    char str2[10] = "bbb";
    char str3[10] = "ccc";

    printf( "## 結合前\n" );
    printf( "str1 = \"%s\"\n", str1 );
    printf( "str2 = \"%s\"\n", str2 );
    printf( "str3 = \"%s\"\n", str3 );

    strcat( str1, str2 );
    strcat( str3, "xxx" );

    printf( "## 結合後\n" );
    printf( "str1 = \"%s\"\n", str1 );
    printf( "str2 = \"%s\"\n", str2 );
    printf( "str3 = \"%s\"\n", str3 );
}

文字列長の取得【strlen】

文字列長の取得にはstrlen関数を使用します。関数定義は次のようになります。

size_t strlen(const char *s);

引数に指定した文字列の長さを戻り値として返します。取得できる値は終端文字を除いた文字列長となります。

さて、『size_t』という見知らぬ型が出てきましたね。C言語では「サイズを示す変数の型」として定義されています。環境によって一概には言えないのですが、基本的には『unsigned int』と考えてもらっても良いです。

それでは、サンプルを用意したので実行してみてください。

#include <stdio.h>
#include <string.h>

void main(){
    char str[10] = "abcde";

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

次回は「構造体」について

今回は「文字列」について学んでもらいました。

次回は「構造体」について解説したいと思います。構造体を学ぶと、更にバリエーションに富んだプログラムが書けるようになります。

ご期待ください。

タイトルとURLをコピーしました