C/C++ - 言語仕様編 第6回 〜ファイル入出力〜

文字列リテラルと C 文字列

前回の復習であるが、文字列リテラルは、"と"で囲まれたものを表し、 const char *型変数で受け取ることが可能である。

char *型は、見ての通りchar *型ポインタ変数strである。 参照子strから連続する領域が「C文字列」であり、その終端は'\0'、すなわちNULL文字である。

char *型ポインタ変数による参照子strから、'\0'の位置までを「C文字列」として扱うことを考える。

str単独では、char *型ポインタ変数である以上、char *型ポインタ変数としての振る舞い以上の 振る舞いは出来ない。

文字列リテラルは、const char *型変数内で、C文字列の形式で記録される。

実際に、char *型ポインタ変数をC文字列として使用するためには、

#include <string.h>

として、char *型の変数をC文字列として取り扱うライブラリ関数を用いるべきである。

C 文字列の整形

sprintf 関数

int sprintf(char *dest, const char *format, ...)

は、formatで指定された文字列リテラルを、C文字列destに出力する可変長引数の関数である。

当たり前ではあるが、destから記録するバイト数の、 スタック領域、ヒープ領域、あるいは静的領域が確保されている必要がある。

変換の指示と変換指示子

sprintf()関数において、第2引数文字列リテラル内にあるn番目の '%' は、 続く変換指示子にしたがって第n+2引数を文字列リテラル内に変換する。

"%d"は、第2引数にある整数リテラル、または整数型変数をその位置に文字列として置換する。

一般に変換の指示は、"%-0w.nl変換指示子" という形式をもち、%と変換指示子は必ずセットで用いる。

-  :wで指定される桁数内で左詰に整形する
0  :フィールド先頭の空白を'0'に整形する
w.n:フィールド幅wと小数点以下桁数に整形する
l  :変換するデータ型がlong長であることを表す

変換指示子には、

d :10進整数リテラル、または10進数に整形される整数型変数
x :16進整数リテラル、または16進数に整形される整数型変数
o :8進整数リテラル、または8進数に整形される整数型変数
u :符号なし10進整数リテラル、または符号なし10進整数型変数
c :文字リテラル、または文字型変数
s :文字列リテラル、またはC文字列
e :浮動小数点数リテラル、または浮動小数点形式に
    整形される浮動小数点数型変数
f :固定小数点数リテラル、または固定小数点形式に
    整形される浮動小数点数型変数

などがある。x、eは大文字X,Eを用いることで、16進数、指数部を表すアルファベットが大文字になる。

sscanf 関数

int sscanf(const char *src, const char *format,...);

は、文字リテラルsrcからformatで指定された文字リテラルに基づいて、第3引数以降の 変数のポインタ、あるいはポインタ変数に値を代入する。sprintf()関数の逆の動作を行う。

C 文字列を返す関数

文字列のコピー

char *型はポインタであり、そのまま=演算子を使うと、初期化ならば参照子、代入ならば反復子となってしまい、 また、*オペレータをつかったところで、char型変数として取り扱われてしまうため、C文字列にはならない。

char *strncpy(char *dest, const char *source, size_t count);

strncpy()関数を用いると、第3引数で指定したバイト長の第2引数の文字列リテラルを 第1引数のC文字列に、コピーする。関数は、第1引数のC文字列を返す。

destは、スタック・ヒープ、あるいは静的領域のいずれかで、記録可能な記録領域を確保している必要がある。

文字列の連結

char *strncat(char *dest, const char *source, size_t count);

strncat()関数は、第3引数で指定したバイト長の文字列リテラルsourceを、 C文字列destの後ろにそのまま連結する。要するに、sourceの先頭の文字が、destの終端'\0'の位置に記録される。

strncatもまた、destが連結後のC文字列を格納可能な十分な記録領域が必要となる。

文字列の検索

const char *strstr(const char *str, const char *substr);

第1引数の文字列リテラルから第2引数の文字列リテラルを検索し、char *型ポインタ変数を返す。 見つからなければNULLが返る。

文字群の検索

const char *strpbrk(const char *str, const char *control);

第1引数の文字列リテラルから第2引数の文字列リテラル内に含まれる文字リテラルを検索し、char *型ポインタ変数を返す。 見つからなければNULLが返る。

文字列の分割

char *strtok(char *str, const char *delim);

第1引数のC文字列から第2引数で指定される文字列内に含まれる文字リテラルを検索し、 存在すればその文字を'\0'で置き換え、その位置を終端とするようなC文字列を返す。存在しなければNULLを返す。

第1引数がC文字列でなくNULLである場合は、前回実行した位置からスタートし、第2引数に 含まれる文字リテラルを同様に検索し、その位置が存在すれば同様にC文字列を返す。

C 文字列を引数にとる関数

文字列長

size_t strlen(const char *str);

引数に指定した文字列リテラルの長さを返す。

文字列比較

int strncmp(const char *str1, const char *str2, size_t maxCount);

maxCount以上の長さを持つ第1引数と第2引数の文字列リテラルを比較し、 第1引数>第2引数ならば正の値、第1引数<第2引数ならば負の値、等しければ0を返す。

文字リテラルと文字列リテラル

C言語において、文字リテラルは、int型変数で受ける。 文字リテラル自身は、8ビットで表現できるため、char型変数で受けることも可能であるが、 基本的に、どちらも4バイト、32ビットである。

繰り返すようだが、文字リテラルは「4バイト」であり、char型変数は「1バイト」である。

"a"と'a'はそれぞれ、文字列リテラルと文字リテラルであるが、この2つは全く異なるものである。 まず、後者はchar *型で受けることはできない。したがって、C文字列を引数として必要とする関数に、 文字リテラルは指定できない。

文字列リテラルは、strlen()が返す文字列長+1バイトで、最後の終端文字'\0'を記録する。

文字列リテラルは、char *型ポインタ変数であるがゆえに、*オペレータを用いれば、char型変数となり、 []オペレータを用いればchar型変数をC文字列のn文字目の文字リテラルをchar型変数として返すこととなる。

最後のまとめであるが、次のstr1とstr2は全く違うものである。

char *str1="string";
char str2[]="string";

前者は、文字列リテラルへのポインタを格納するポインタ変数であり、 後者は、char型配列を文字列リテラルで初期化している。もちろん、配列の要素の長さはstrlen("string")+1である。


文章作成 : yukki-ts (-+-twilight serenade-+- [stage])