文字列リテラルを評価すると、その文字列リテラルの先頭文字へのポインタになる (List 11-1)。
/* どちらも可能 */ char str[] = "ABC"; /* 配列… */ char *ptr = "123"; /* ポインタ… */ /* 読み出すだけならどちらも同等 */ printf("str = \"%s\"\n", str); printf("ptr = \"%s\"\n", ptr);
添字を使って読み出すときも、違いはない(List 11-2)。
for (i = 0; str[i]; i++) { putchar(str[i]); /* str[i]は、先頭からi個後ろの要素 */ } putchar('\n'); for (i = 0; ptr[i]; i++) { putchar(ptr[i]); /* ptr[i]は、先頭からi個後ろの要素 */ } putchar('\n');
str = "DEF"; /* コンパイル時エラーになる ← 配列は直接代入できない */ ptr = "456"; /* エラーにならない */
str[0] = 'A'; /* エラーにならない、配列の各要素は書き込み可 */ ptr[0] = '4'; /* 間違い: 結果は処理系により異なるができないと思った方がよい */
char st[3][6] = {"Turbo", "NA", "DOHC"}; char *pt[3] = {"12345", "12", "1234"};どちらも可能だがメモリ中の配置が異なる(Fig.11-5参照)。
プログラムを起動する時にコマンドラインパラメータを渡すことができる。
コマンドラインパラメータは Cプログラムの中では “ポインタで実現する文字列の配列” (char *[]型、あるいは char **型)として表現されている (argvexample.c)。
/* ↓の行は int main(int argc, char **argv) と書いても同じ */ int main(int argc, char *argv[]) { int i; for (i = 0; i < argc; i++) { printf("%s\n", argv[i]); } return 0; }
argv[0]に“プログラムを起動したコマンド名”が入る。 argcにはコマンドラインパラメータの個数(argv[0]も含む)が入る。
実行例: (…の部分は実行環境により異なる。)
> argvexample hello! 1 2
…\argvexample.exe
hello!
1
2
int str_length(const char *s) { int len = 0; while (*s++) { len++; } return len; }
char *str_copy(char *d, const char *s) {
char *t = d;
while (*d++ = *s++) /* ==ではない */
;
return t;
}
(復習)代入式は代入後の左オペランドの値になる(教科書 p.98)。
while (d[i] = s[i]) { /* ==ではない */
i++;
}
と書いても効率が極端に悪くなるようなことはない。
しかし、前者のようなポインタを使った書き方が簡潔なため好まれる傾向がある。
文字列リテラルを書き換えてはいけない (List 11-8)。 文字列リテラルを書き換えた時の振る舞いは処理系に依存する。
str_copy関数がchar *を返しているのは、 この関数を利用する部分を簡潔に書けるようにするため。
str_copy(s2, s1); printf("s2 = %s\n", s2);を
printf("s2 = %s\n", str_copy(s2, s1));と書くことができる。
いくつかの文字列操作関数がstring.hヘッダーに宣言されている。
名前と型 | 説明 | 実現例 |
---|---|---|
size_t strlen(const char *s) | 文字列の長さ | List 11-9 |
char *strchr(const char *str, int c) | 文字列中の文字の出現位置 | strchr.c |
char *strcpy(char *s1, const char * s2) | 文字列のコピー | List 11-10 |
char *strncpy(char *s1, const char * s2, size_t n) | 文字列のコピー* | List 11-10 |
char *strcat(char *s1, const char *s2) | 文字列の連結 | List 11-11 |
char *strncat(char *s1, const char *s2, size_t n) | 文字列の連結* | List 11-11 |
int strcmp(const char *s1, const char * s2) | 文字列の比較 | List 11-12 |
int strncmp(const char *s1, const char * s2, size_t n) | 文字列の比較* | List 11-12 |
“何も指さない”ポインタ定数として NULLというマクロが用意されている。 NULLはエラーや例外的な状況を表現するのに利用される。 NULLは実は定数 0なので、if文や while文の 条件式として使用すると偽(false)を意味する。 (NULL以外のポインタは必ず0以外、つまり真(true)になる。)
NULLはstddef.hに定義されている。 (stdio.h, stdlib.h, string.h, time.hのいずれかをインクルードしても良い。)
"144"や"3.14"などの文字列を数値に変換する関数が、 stdlib.hに宣言されている。 (使用例: List 11-13)
名前と型 | 説明 |
---|---|
int atoi(const char *nptr) | int型に変換する |
long atol(const char *nptr) | long型に変換する |
double atof(const char *nptr) | double型に変換する |