C言語 プログラミング

C言語でプログラミング基礎編(5)【文字列のあつかい】

C言語講座5回目、C言語は文字列を文字の配列としてあつかいます。

文字列型を言語としてもたないことで、軽量でコンパクトにまとまった言語となっていますが、バグをつくりこんだり、難易度をあげてしまう原因にもなっています。

※C++では、クラスを使うことで、文字列を扱うことができるようになります。

とはいえ、機械などへの組込み系で純粋なC言語で開発する場合とか、過去に開発されたC++ではない純粋なC言語で開発された資産を修正する必要も世の中にはあふれていそうです。

今回は、C言語で文字列をどうあつかうかについて、まとめました。

C言語でプログラミング:文字列

C言語文字列

文字列の使い方

C言語以外のプログラミング言語は、たいてい文字列をひとつの基本的な型として用意しています。

Pythonだろうと、Rubyだろうと、JavaだろうとPascal、Basicだろうと、文字列は型になっています。

他の言語の文字列の扱いは例えば、


Python:
s = "Hello"
if s == "Hello":
   print(s)

Basic:
Dim s As String
s = 'Hello '
If s = 'Hello' Then
    print s
End If

このように、文字列を型としてあつかうことが可能です。

あわせて、文字列を文字列として代入や比較ができるようになっています。

一方、C言語は、文字列がプログラミング言語として用意されているわけではなく、キャラクタ型の配列(または、ポインタ)を利用するようになっています。

あわせて、文字列の最後をヌル文字'\0' にするというC言語の標準関数の考え方になっているルールもあるため、より文字列の操作に気を配る必要があります。

気をつけるポイントは、3つ。

・文字列は、文字型の配列で定義
・文字列の操作は、文字列操作のために関数を利用
・文字列の終端は、ヌル文字'\0'が入るのが標準関数のルール

逆にいうとこのような特徴が、コンパイラを軽くし、システムプログラミング言語たらしめているのかも知れません。

しかし、プログラミングする側は、それを理解した上で文字列を操作する関数を使う必要があります。

それらを扱う関数群を定義しているのが、string.h です。

strlen, strcpy, strcat, strchr, strstr strcmp

等は、頻繁に利用される関数です。

文字列の扱いは、注意する必要があります、ということの簡単なサンプルです。


#include 
#include 

int main()
{
    char  s[128];
    char* p;
    
    strcpy(s, "hello, world");
    if (strcmp(s, "hello, world") == 0) {
	   /* 一致したら */
	   printf("%s\n", s);
    }
    p = strchr(s, 'w');
    if (p != NULL) {
	    /* w が見つかったらそこから先を表示 */
        printf("%s\n", p);
    }
    return 0;
}

文字列の中身の値の比較には、strcmp関数で比較します。

さて、文字列の最後は、ヌル文字('\0'つまりゼロ)で終わる。というのが、C言語の文字列の扱い方の一般的なルールであると述べました。
つまり、5バイトの文字列を扱うなら、6バイト分の領域が必要になります。
文字列を扱うときは、これだけは十分に注意しなければなりません。

たとえば、10バイトの名前を扱う場合。


#define NAME_LEN  10

char szName[NAME_LEN + 1]; /* ここは、+1 が必須 */

......

szName[NAME_LEN] = '\0';
strncpy(szName, szBigBuffer, NAME_LEN);

宣言時の+1を忘れて、アプリケーションエラーに悩んでいる姿をよく目にします。

参考までに、ヌル文字終端のルールをC言語のライブラリでは、どのように実装しているかです。

例えば、文字列の長さを調べるのは。


int strlen(char* s)
{
    int i, iLen;
    iLen = 0;
    for (i = 0; s[i] != '\0'; i++) {
       ++iLen;
    }
    return iLen;
}

文字列のコピーを例にとってみます。


/* src から dst にコピー */
char* strcpy(char* dst, char* src)
{  
   int i;
   for (i = 0; src[i] != '\0'; i++) {
	dst[i] = src[i];
   }
   dst[i] = '\0';
   return dst;
}

ポインタで扱ってみます。

char* strcpy(char* dst, char* src)
{
   while (*src != '\0') {
	*dst++ = *src++;
   }
   *dst = '\0';
   return dst;
}

※日本語などの2バイト文字を扱う場合、型を変えたり、その為の処理を記述する必要はあります。

今回、C言語の文字列操作について書いてみました。

他の言語と違い文字列型はありませんが、他の言語でも文字列が実際の値を参照しているだけなのか、値を保持しているものなのかを意識する必要はでてきます。

そういう意味では、C言語は、配列に値を保持、参照はポインタで行う、という明確に分かれているので、最初はとっつきにくくても、プログラムの仕組みまで理解するためには、ひもといてみるのもいいと思います。

 

今回はここまで。
C言語の話は、この後も何回かに分けて投稿しますので、興味のある方は引き続きよろしくお願いします。

-C言語, プログラミング

Copyright© SIMPLEONESOFT (BLOG) , 2022 All Rights Reserved.