01: プログラミング言語とは何か 02: 0から99まで印字するプログラムの解説 03: Pythonで書くと... 04: 変数と関数 05: 条件分岐とループ 06: プリプロセス 07: ポインタと配列1 08: ポインタと配列2 09: ポインタと配列3 0A: 文字列 0B: 多次元配列 0C: ファイル入出力 0D: 構造体 0E: コマンドライン引数 0F: 数値を読み込んで総和と平均を表示するプログラム 10: 数値を読み込んで総和と平均を表示するPythonプログラム 11:【番外編】文章中の単語を出現頻度順に表示するプログラム 12:【番外編】コマンドライン引数を処理するイディオム 13:【番外編】C言語でクロージャを実装する
文字列型はC言語にはない.文字列はcharの配列として扱う.charは1文字を表すのに適当と考えられている型で,必ず1バイトの大きさ(ただし1バイトが何ビットかは処理系に依存する)を持つデータである.
C言語には可変長の配列が無い.配列は,別途配列の長さを記録しておかないといけない.これでは,文字列の場合あまりにも不便であるので,文字列に関しては特殊なルールがある.すなわち,文字列はその終端に終端を表す記号(ターミネータ・シンボル)をつけることで,配列の終わりを示すのである.例えば,いまappleという文字列を配列sに格納したいとしよう.
char s[6] = { 'a', 'p', 'p', 'l', 'e', '\0' };
が文字列の定義方法である.'a' はaを表す文字コードに置き換えられる.ここに '\0' がターミネータ・シンボルである.ターミネータ・シンボルは整数の0と等価なので,
char s[6] = { 'a', 'p', 'p', 'l', 'e', 0 };
としてもよい.もっと簡単な書き方がある.次のコードはこれまでのコードと同じ意味である.
char s[6] = "apple";
ターミネータ・シンボルは自動的に付加される.配列のサイズはコンパイル時に自動的に決められるので,コードは以下のように縮められる.
char s[] = "apple";
普通,配列はそのサイズをどこかに保存しておくものである.文字列の場合は,サイズが必要になる場面は限られていること,変数が二つ(文字配列を表すポインタとそのサイズを表す整数)になると面倒なこと,ターミナル・シンボルで終わる文字列は長さを調べることができることから,サイズを別途保存しておくことは普通しない.次の関数strlenは文字列の長さを調べる.
#include <string.h>
void func(void) {
char s[] = "apple";
int length = strlen(s);
...
}
文字列をコピーしたいときはこうする.
#include <string.h>
void func(void) {
char s[] = "apple";
char *d = calloc(6, sizeof(char));
strcpy(d, s);
...
}
もし d = s としたら,ポインタの値はコピーされるが,文字列の内容はコピーされない.
文字列の比較もまた,関数が必要である.次のプログラムは文字列 s1, s2 を比較している.関数strcmpは文字列s1が文字列s2よりも辞書順で先であれば正の値を,等しければ0を,辞書順で後であれば負の値を返す.
#include <stdio.h>
#include <string.h>
int main(int argc, const char *argv[]) {
char s1[] = "apple";
char s2[] = "orange";
int c = strcmp(s1, s2);
if (c > 0) {
printf("s1 > s2\n");
else {
if (c == 0) {
printf("s1 == s2\n");
}
else {
printf("s1 < s2\n");
}
}
文字列については,ひとまずこの程度知っておけばよかろう.C言語はあまり文字列処理に向いていない.もしテキスト処理が必要になったら,C言語は第一選択肢からは外すべきである.例えばAwk言語は,学習しやすく(数時間で習得できるだろう),かつ十分に強力である.