第13章 文字の取り扱い方 13.1 13.2 13.3 13.4 13.5 文字と文字型変数 文字列 文字型配列への文字列の代入 キーボードからの文字列の入力 文字型配列と関数 13.1 文字と文字型変数 これまでに扱ったのは数値型変数 整数型 int : -2147483648 〜 2147483647 浮動小数点型 他に、short int, long int, long double, また、unsigned がつくものなどがある。 float : 10-38 〜 1038 詳細はプログラミング演習Ⅰの資料を参照 double : 10-308 〜 10308 プログラミングでは文字も扱う場合が多い 文字型 char を用いる http://www.ced.is.utsunomiya-u.ac.jp/lecture/2010/prog/p1/kadai1/variable.html 文字型変数に文字を代入 プログラム例 13.1.1 より抜粋 int main(void) 文字型変数 x を宣言 { char x; 1文字はシングル 代入文でOK x = 'H'; クォート(')でくくる printf("%c¥n", x); return 0; 1文字用の書式指定子 } 1文字 = 1バイトの数値 8ビット(0~255) p.180, 表A.3 ASCIIコード 文字型変数に文字を代入 プログラム例 13.1.1 の改変 #include <stdio.h> int main(void) { character char x, y, z, u, v, w; x = 'H'; y = 'a'; z = 'p'; %c 文字 u = 'p'; v = 'y'; w = '!'; printf("%c%c%c%c%c%c¥n", x, y, z, u, v, w); printf("%d %d %d %d %d %d¥n", x, y, z, u, v, w); printf("%x %x %x %x %x %x¥n", x, y, z, u, v, w); return 0; %x 16進数 } hexadecimal decimal %d 10進数 13.2 文字列 複数個の文字(文字列、string)は「char 型の配列」として扱う。 文字列はダブルクォート(")でくくること。 null文字 文字列の最終文字の次に、文字列の最後を示す \0 が入る。 プログラム例 13.2.2 より抜粋 文字列 William Shakespeare を配列変数 x に代入 int main(void) { char x[20] = {"William Shakespeare"}; 19字だが、 printf("%s¥n", &x[0]); 20字分用意 return 0; } 文字列用の書式指定子 ここで、配列変数 x の先頭番地を指定すると、 x のすべてを表示する。 ただし最後の ¥O は表示しない 文字列は配列に格納される 1000 1001 1002 ・ ・ ・ x[0] x[1] x[2] x[3] x[4] x[18] x[19] W i l l i e \0 int main(void) { char x[]= {"William Shakespeare"}; printf("%s¥n", x); return 0; } &x[0] は単に x でよい 文字列の終わり 正体は1バイトの数字の0 13.2 文字列 配列の長さ < 文字列の長さ の場合にどうなるか、試してみよう プログラム例 13.2.2 の改変 #include <stdio.h> ここの値を変えて、配列の 長さを1つずつ減らしてみよ int main(void) { char x[??] = {"William Shakespeare"}; printf("%s¥n", x); return 0; } 文字列の正体 プログラム例 13.2.2 の改変 #include <stdio.h> int main(void) { int i; char x[20] = {"William Shakespeare"}; printf("%s¥n", x); for (i = 0; i < 20; i++) printf(" %d", x[i]); printf("\n"); return 0; } この出力結果を p.180、表A.3 のASCIIコード と比べてみよう 13.2 文字列 複数の文字列を扱う場合 → 2次元配列を使う プログラム例 13.2.4 #include <stdio.h> 前の数字が文字列の数 int main(void) 後の数字は「文字数+1」以上に { char name[3][20] = {"William Shakespeare", "William Clinton", "William Henry"}; int i; for (i = 0; i < 3; i++) printf("%s¥n", name[i]); printf("\n"); return 0; } 13.3 文字列の代入 配列(文字列)に代入文は使えない 文字列処理関数 (string.h を include) strcpy(char *dst, char *src) string copy (ストリング・コピー)の略 引数の順序は代入文 dst ← src に対応 引数はポインタ(文字型配列の名前) 13.3 文字列の代入 プログラム例 13.3.2 #include <stdio.h> #include <string.h> 入れ物は2つ用意 int main(void) { a ← "William Shakespeare" char a[31], b[31]; strcpy(a, "William Shakespeare"); printf("%s\n", a); strcpy(b, a); 文字列の代入 b ← a printf("%s¥n", b); return 0; } a William Shakespeare b William Shakespeare 実際にコピー 13.3 文字列の代入(もどき) プログラム例 13.3.2 の改変 #include <stdio.h> int main(void) 入れ物は1つ a ← "William Shakespeare" { char a[] = "William Shakespeare", *b; 文字型ポインタを用意 printf("%s\n", a); b = a; b ← a アドレスデータの代入 printf("%s¥n", b); データは共用 return 0; } a b William Shakespeare 13.4 キーボードからの文字列の入力 プログラム例 13.4.2 101 は文章を読み込むのに 十分と考えられる適当な数。 特別な意味はない #include <stdio.h> int main(void) { char sentence[101]; printf("文章を入力して下さい"); gets(sentence); キーボードから文字列を受け取り、 puts(sentence); の配列変数 sentence に代入する return 0; } ディスプレイに表示 gets は get string、puts は put string と覚えれば良い ゲットエス プットエス 参考: C言語の読み方サイト http://bubuzuke.s7.xrea.com/ISO10646/c_reading.html 失敗例 プログラム例 13.4.1 と 13.4.2 の混合 #include <stdio.h> int main(void) { char surname[51], sentence[101]; printf("姓を入力してください :"); scanf("%s", surname); printf("姓は %s です.\n", surname); printf("文章を入力してください "); gets(sentence); puts(sentence); return 0; } gets, getc, getchar があるときは scanf は使わない 製品開発には挙動不審な scanf は使われない 解決例 プログラム例 13.4.1 と 13.4.2 の混合 #include <stdio.h> int main(void) { char s[101], surname[51], sentence[101]; printf("姓を入力してください :"); gets(s); sscanf(s, "%s", surname); printf("姓は %s です.\n", surname); printf("文章を入力してください "); gets(sentence); puts(sentence); return 0; } gets + sscanf なら OK 13.5 文字型配列と関数 関数に文字列を渡す → ポインタ変数(配列名)を引数に プログラム例 13.5.2 2次元配列のまま渡す場合 #include <stdio.h> 1行あたり40文字で3行分 #define NSIZE 40 の2次元配列を宣言 #define N_Mem 3 void input_name(int n, char name[][NSIZE]); ポインタ(その配列 void print_name(int n, char name[][NSIZE]); の先頭番地を指す) を引数とする int main(void) { char f_and_g[N_Mem][NSIZE]; input_name(N_Mem, f_and_g); print_name(N_Mem, f_and_g); return 0; } 文字列を 読込む関数 文字列を 表示する関数 13.5 文字型配列と関数 プログラム例 13.5.2 (つづき) void input_name(int n, char name[][NSIZE]) { int i; for (i = 0; i < n; i++) { printf("苗字と名前を入力してください :"); gets(name[i]); } } void print_name(int n, char name[][NSIZE]) { int i; for (i = 0; i < n; i++) printf("あなたの苗字と名前は %s です.\n", name[i]); } 13.5 文字型配列と関数 プログラム例 13.5.3 ポインタ配列として渡す場合 #include <stdio.h> NSIZEが不要に #define NSIZE 40 #define N_Mem 3 void input_name(int n, char *name[]); void print_name(int n, char *name[]); int main(void) 文字型ポインタ配列を用意 { int i; char f_and_g[N_Mem][NSIZE], *name[N_Mem]; for (i = 0; i < N_Mem; i++) name[i] = f_and_g[i]; 行ごとに2次元配列を input_name(N_Mem, name); 文字型ポインタ配列にすり替え print_name(N_Mem, name); return 0; } 13.5 文字型配列と関数 プログラム例 13.5.3 (つづき) void input_name(int n, char *name[]) { int i; for (i = 0; i < n; i++) { printf("苗字と名前を入力してください :"); gets(name[i]); } } NSIZEが不要に void print_name(int n, char *name[]) { int i; for (i = 0; i < n; i++) printf("あなたの苗字と名前は %s です.\n", name[i]); } スキルアップタイム 1 以下の動作をするプログラムを作成せよ。 1. ディスプレイに「文章を入力して下さい」と表示 2. キーボードから入力された適当な英語の文章 (例えば Boys be ambitious! など)を読み取る 3. その文章をディスプレイに表示 4. これを3回繰り返す (1、2、3回目は各々違う文章を入力してみる) プログラム例 13.4.2 を参照 スキルアップタイム 1 のプログラムの流れ ヘッダファイル、関数、記号定数の宣言 変数宣言(必要な変数と そのデータ構造を決める) 3つの文章を記憶せず、読み込んで 表示するだけなら、1つの文章用1次 元配列で OK printf で“文章を入力して下さい” main = i = 1...3 gets で文章を読み取り、変数に入れる puts で文章を表示 終了 文字型配列 sentence[] スキルアップタイム 2 作成したプログラムを以下のように変更せよ 1. 最初にディスプレイに「3つの文章を入力して下さ い」と表示 2. ディスプレイに「文章 i:」(i = 1,2,3)と表示し、 キーボードから入力される英語の文章を読み取る。 これを3回繰り返す(この時点では表示はしない) 3. 3個の文章をまとめてディスプレイに表示 3個の文章を記憶する必要有り → 文字型の2次元配列が必要 スキルアップタイム 2 のプログラムの流れ (その1) ヘッダファイル、関数、記号定数の宣言 変数宣言(必要な変数と そのデータ構造を決める) main で全ての作業を行うタイプ (この程度の課題ならこれでも十分) printf で“文章を入力して下さい” main = i = 1...3 gets で文章を読み取り、配列変数に入れる i = 1...3 終 了 puts or printf で配列変数に入った文章を表示 スキルアップタイム 2 の プログラムの流れ (その2) プログラム例 13.5.2 を参照 ヘッダファイル、関数などの宣言 変数宣言(必要な変数と そのデータ構造を決める) main = 文章を読み取る関数 関数名、変数名は 自分の好きなように決める 文章を読み取る関数 input_sentence i = 1...3 文章を表示する関数 これは一例 printf で “文章を入力して下さい” gets で文章を読み取る 終了 文字列配列(ポインタ)を引数 としてデータをやりとりする 文章を表示する関数 = i = 1...3 print_sentence printf or puts で文章を表示 スキルアップタイム3 すべてできた人は、演習問題の問題13.3、 問題13.5 をやってみよう。 問題13.3 用のデータを考えるのが面倒な人は以下の データを使ってください。 学籍番号 氏 名 科目Aの得点 1001 Akanishi Hideo 55 1005 Ishihara Satoshi 64 1013 Kitano Keiko 71 1024 Sakaguchi Erika 85 1030 Tanaka Kazuya 68 本日のパズル 次のプログラムは何を出力するか #define PRINT(x) printf(#x"=%d\n",(x)) int i=0; main() { auto int i=1; PRINT(i); 1 { int i=2; PRINT(i); 2 { i += 1; 3 PRINT(i); } 4 PRINT(i); } 5 PRINT(i); }
© Copyright 2025 ExpyDoc