第6章 配列

第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);
}