今回の目標
文字列について理解し、扱えるようになること。
文字と文字列
C言語では、文字 (1文字) と文字列 (複数文字) は厳密に区別されます。
そのため、両者を同じものと考えて、以下の文章を読むことはやめてください。
また、ここで言う1文字はアルファベットのことを指します *1。
日本語はたとえ1文字であっても文字列です。
文字定数と文字列定数
プログラム中に、直接文字や文字列を書く場合には、文字定数や文字列定数と呼ばれる形式を使用します。
文字定数は ' (一重引用符、シングルクォーテーション) で囲みます。
文字列定数は " (二重引用符、ダブルクォーテーション) で囲みます。
putchar('A'); // putchar 関数は文字を出力する
putchar('\n'); // 改行
printf("ABC\n");
文字とは何か
私たちはコンピューター上で文字を扱っています。
この文字の実態はただの整数です。
たとえば、アルファベットであれば以下のように定義されます。
- ASCII文字コード
http://e-words.jp/p/r-ascii.html
このように、文字を整数で定義したものを文字コードといいます。
文字が整数で表されているというのが、信じられないというのであれば、以下のプログラムを実行してみてください。
putchar(65); // A
putchar(66); // B
putchar(67); // C
putchar(10); // \n
ABCと画面に出力されたのではないでしょうか。
このように、文字をコンピューターは数値として認識しているのです。
文字定数で書いたものは、内部的にこのような数値に変換されています。
なお、putchar 関数は printf 関数で代替できます。
整数を文字として表示する場合、%cを用います。
以下の例は、上の例と同じです。
printf("%c%c%c%c", 65, 66, 67, 10);
文字の型
文字は、一般的に char 型を用います。
char が character (文字) の略であることから分かる通り、文字を扱うことを目的とした型です。
char 型は次のように使用します。
char a, b, c;
a = 88; // X
b = 'Y';
c = 'Z';
printf("%c%c%c\n", a, b, c); // XYZ
char 型には文字は入りません。
文字列の型
C言語に文字列の型はありません。
文字列は文字の配列という形で表します。
たとえば、"ABC"という文字列定数は、以下のような配列として表されています。
最後の '\0' という文字はヌル文字 *2*3 と言って、文字列の終端を表す特別な文字です。
C言語の文字列には、必ずヌル文字を最後に付けなくてはいけません。
上の画像の文字列を格納するには、サイズ 4 の char 型の配列が必要です。
コードで表すと、以下のようになります。
char s[4];
s[0] = 'A';
s[1] = 'B';
s[2] = 'C';
s[3] = '\0';
上のコードは次のようにも書けます。
char s[4] = "ABC";
さらに、宣言時に初期化する場合に限り、配列のサイズを省略できます。
char s[] = "ABC";
このように、宣言時の初期化に限り、上のように文字列定数が代入ができます*4。
以下のようにして文字列を代入することはできません。
char s[4];
s = "ABC"; // コンパイルエラー
途中で文字列を代入したい場合、別の方法をとる必要があります。
文字の入力
文字を読み込むには、次のようにします。
char a;
scanf("%c", &a);
ただし、上のようにすると空白や改行も文字として読み込んでしまいます。
それを防ぐためには、次のようにします。
char a;
scanf(" %c", &a);
上のように、%c の前に空白を置くと、改行や空白などを読み飛ばせという意味になります。
もちろん、読み飛ばす改行や空白などが無い場合でも、正常に動作します。
printf 関数での文字列の出力
printf 関数で文字列を出力するには、%s を使用します。
例
char a[] = "ABC";
printf("a = %s\n", a);
文字列の入力
文字列を読み込むには次のようにします。
char s[11];
scanf("%s", s);
文字列を読み込む際には & をつけません。
これは間違えやすいので、気をつけてください。
また、配列のサイズは、読み込みたい文字数 + 1 が必要です。
文字列の末尾には、必ずヌル文字を付けなければいけないからです。
上の例では、最大 10 文字まで読み込めます。
scanf で読み込んだ場合、ヌル文字は自動で付けられます。
文字列操作関数
文字列を操作するために、専用の関数が string.h に用意されています。
なお、string とは、文字列のことを指します。
string.h には数多くの関数があるため、すべてをここで紹介することはできません。
代表的なもののみを紹介しますので、詳細は以下のサイトなどをご覧ください。
- C言語関数辞典 string.h
http://www.c-tipsref.com/reference/string.html
strcmp 関数
strcmp 関数は文字列を比較する際に使用します。
形式
strcmp(比較したい文字列1, 比較した文字列2);
例
int result = strcmp(a, b);
if(result == 0){
printf("%s と %s は等しいです。\n", a, b);
}
else if(result < 0){
printf("%s のほうが %s より辞書順で先です。\n", a, b);
}
else {
printf("%s のほうが %s より辞書順で後です。\n", a, b);
}
strcpy 関数
strcpy 関数は、文字列の配列へ文字列をコピーします。
形式
strcpy(コピー先, コピー元);
例
char s[10];
strcpy(s, "ABC"); // s = "ABC" とはできない
strlen 関数
strlen 関数は、文字列の長さを求めます。
形式
strlen(長さを求めたい文字列);
例
char s[10];
scanf("%s", s); // & は付けない!!
printf("%s は %d 文字です。\n", s, (int)strlen(s));
課題
課題1
入力された文字をそのまま表示するプログラムを作成しなさい。
ただし、入力される文字は半角英数字とする。
実行例
./a.out a a
./a.out 1 1
課題2
入力された文字列をそのまま表示するプログラムを作りなさい。
ただし、文字列は最大 10 文字までとする。
実行例
./a.out qwerty qwerty
./a.out 1234567890 1234567890
./a.out X X
課題3
文字列が1つ入力されます。
文字列の文字数を出力しなさい。
ただし、文字列は 10 文字以下とします。
実行例
./a.out abc 3
./a.out a 1
./a.out abcdefghij 10
課題4
文字列が2つ入力されます。
辞書順で出力しなさい。
ただし、文字列は 10 文字以下とし、各文字列に空白は含まないものとします。
実行例
./a.out melon apple apple melon
./a.out cherry grape cherry grape
./a.out 1234567890 0123456789 0123456789 1234567890
./a.out orange orange orange orange
挑戦課題
- AOJ 10018: Toggling Cases 易
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=10018
ヒント: ASCII文字コード
- AOJ 10020: Counting Characters
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=10020
ヒント: 入力の最後かは、scanf の戻り値を調べます。char a; if(scanf("%c", &a) == EOF){ // 入力の最後です }
- AOJ 10021: Finding Minimum String 易
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=10021
- AOJ 10022: Finding a Word
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=10022
- AOJ 10023: Shuffle 難
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=10023
- AOJ 0006: Reverse Sequence 易
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0006&lang=jp