いままで、数字の変数を使って計算したり、表示したりすることをやってきましたが、ここでいよいよ文字の表示、入力についてやっていきます。
文字変数の型にはchar型を使用します。char型は1バイトの型です。具体的な使用例を見てみましょう
#include <stdio.h> int main(){ char a; a = 'A'; /* aに'A'を代入 */ printf("%c\n",&a); return 0; }
一文字、「A」が表示されたと思います。
a = 'A'
この部分で、aに「A」の一文字を代入しています(正確には「A」の文字コードが代入される)。aには1文字しか代入できません。また、'A'の「'」はシングルクォーテーションです(シフトキーを押しながら7で入力できます。たぶん)。ダブルクォーテーションにするとエラーになりますので注意してください。
printf("%c\n",&a);
%cでaを表示します。数字の表示の時のように%dや%fでないことに注意してください。
代入の時と同じく、シングルクォーテーションで囲んだ文字を用いて判定できます。
#include <stdio.h> int main(){ char a; a = 'A'; if(a == 'A'){ a = 'B'; } printf("%c\n",&a); return 0; }
#include <stdio.h> int main(){ char a; a = 'A'; switch(a){ case 'A': a = 'B'; break; case 'B': a = 'A'; break; default: break; } printf("%c\n",&a); return 0; }
「B」が表示される、用途不明なプログラムですが、文字に対して、代入や比較が数字に対してするのと同じように容易にできることが確認できたと思います。一方、後述する文字列に対しては、このように簡単にはできません。
「char a;」ではaに1文字しか格納できません。文字列にするには、char配列にする必要があります。
#include <stdio.h> int main(){ char a[4]; a[0] = 'A'; a[1] = 'B'; a[2] = 'C'; a[3] = '\0' printf("%s\n",a); return 0; }
これで「ABC」と表示されます。
a[0] = 'A'; a[1] = 'B'; a[2] = 'C'; a[3] = '\0'
A,B,Cを代入しています。a[3] = '\0'は、終端文字をセットしているもので、NULL止めなどと表現されます。'\0'は文字コード0(NULL)のことです。
printfで文字列を出力するときには、'\0'までが表示されますので、文字列の最後は'\0'にしないと思った通りの出力がされません(エラーの原因にもなります)。
printf("%s\n",a);
%sで文字列が表示されます。aは文字列の先頭アドレスですので、次のように表現もできます。
printf("%s\n",&a[0]);
上の例では一文字ずつ代入していましたが、文字列型が標準サポートされていないC言語では、文字列の代入は単純にはできません。一文字ずつ代入する代わりに
a = 'ABC' a = "ABC"
と書きたいところですが、できません。シングルクォーテーションは一文字に対して使用できるので、文字列の代入は無理です。下のダブルクォーテーションもだめですが、ただ一度だけ、文字列を初期化するときのみ、この代入の記述が許可されます。
#include <stdio.h> int main(){ char a[4] = "ABC"; printf("%s\n",a); return 0; }
a[3]は自動的に'\0'になります。また、配列のサイズを省略した表記にすれば、最初に文字数をカウントする必要がありません。
#include <stdio.h> int main(){ char a[] = "ABC"; printf("%s\n",a); return 0; }
さて、プログラムの途中で文字列を代入したい場合は、文字列代入関数を使用することになります。文字列操作の関数はたくさんありますが、よく使われるものを紹介します。
文字列をコピーする関数です。string.hをインクルードする必要があります。
char* strcpy(char* コピー先, const char* コピー元) char* strcat(char* コピー先, const char* コピー元)
strcat(a, "ABC")と書けば、ABCを代入できます。ただし、コピーサイズを決められないので、バッファオーバーフローの原因となることがあります。コピーサイズを指定できる、strncpy()やstrncat()を使用した方がいいでしょう。
char* strncpy(char* コピー先, const char* コピー元, size_t コピーサイズ) char* strncat(char* コピー先, const char* コピー元, size_t コピーサイズ)
size_tはintのことです。
文字列の長さを返す関数です。NULL文字の前までの文字数をカウントします。string.hをインクルードする必要があります。
size_t strlen(const char 文字列)
strlen("ABC")だと、3になります。
文字列に対するprintf関数です。stdio.hのインクルードが必要です。画面ではなく、文字列に対して出力されます。
int sprintf(char* 出力先文字列, const char* フォーマット, ...)
フォーマットはprintfでこれまで記述してきたような内容です。例えば、sprintf(a, "Zero = %d",0)とすれば、aの文字列には「Zero = 0」が代入されます。こちらも、サイズが指定できるsnprintf()の使用が推奨されます。
int snprintf(char* 出力先文字列, size_t サイズ, const char* フォーマット, ...)
指定された数だけ、同じ文字をセットする関数です。string.hのインクルードが必要です。初期化や文字列のクリアなどで0をセットするのが一般的です。
void* memset(void* 文字列など, int セットする文字(unsigned charに変換される), size_t サイズ)
この関数は文字列に限定されないので、int配列の初期化などにも使用できます。
#include <stdio.h> #include <string.h> int main(){ char a[20]; memset(a, 0, sizeof(a)); strncpy(a, "Nice boat.", sizeof(a)); printf("%s\n",a); return 0; }
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(){ char *a; a = (char *)malloc(100); if(a == NULL){ exit(1); } memset(a, 0, 100); snprintf(a, 100, "Nice boat."); printf("%s\n",a); return 0; }
(※ポインタに対してsizeofを使うとポインタのサイズが返ってきてしまうので、使えないのです。)
文字列の比較を行う場合も、関数を使用します。
文字列の比較を行う関数です。string.hをインクルードする必要があります。
int strcmp(const char* 文字列1, const char* 文字列2);
「文字列1」と「文字列2」を比較し、同じであれば0を返します。これもサイズ指定ができるstrncmpの使用が推奨されます。
int strncmp(const char* 文字列1, const char* 文字列2, size_t サイズ)
#include <stdio.h> #include <string.h> int main(){ char a[20]; int b; memset(a, 0, sizeof(a)); strncpy(a, "Nice boat!", sizeof(a)); b = strncmp(a, "Nice boat!", sizeof(a)); if(b == 0){ printf("%s\n",a); } return 0; }
Nice boat!
ところで、char型は1バイトの変数ですので、-127から+127までの範囲の数字の変数としても使えます。計算もできます。
#include <stdio.h> int main(){ char a; a = 1; /* aに1を代入 */ a ++; printf("%d\n",a); return 0; }
「2」と表示されるはずです。サイズはint型の1/4ですので、それほど大きな値を使用しない場合に、文字としてでなく数字として扱うことがあります。