物理情報処理基礎実習II 第10回

http://www.phys.ynu.ac.jp/labs/cosmic/shibata/jisshu/
物理情報処理基礎実習II
第10回
文字と配列
~char型変数・文字列~
柴田 [email protected]
(原 [email protected])
石川 [email protected]
§課題8 方程式の根解答例
aplsrvky01% cat exercise8.c
#include <stdio.h>
#include <math.h>
#define f(x) ((x)*(x)-sin((x)))
main()
{
double x1,x2,eps;
double f1,fm,xm;
int i,n=10000;
printf("input xmin,xmax(xmin<xmax),eps=");
scanf("%lf %lf %lf",&x1,&x2,&eps);
for(i=0;i<n;i++){
xm=(x1+x2)/2;
f1=f(x1);
/* f1=x1*x1-sin(x1); */
fm=f(xm); /* fm=xm*xm-sin(xm); */
if(fabs(f1)<=eps||fabs(fm)<=eps)break;
if(f1*fm<0.0){
x2=xm;
}
if(f1*fm>0.0){
x1=xm;
}
}
printf("%d)x1,f1:x2,f2=%15.10lf,%15.10lf:
%15.10lf,%15.10lf\n",i,x1,f1,xm,fm);
}
aplsrvky01% cc exercise8.c –lm
-o exercise8;./exercise8
input xmin,xmax(xmin<xmax),eps=0.1 1.0 1.0e-6
16)x1,f1:x2,f2= 0.8767196655, -0.0000072951:
0.8767265320, 0.0000003526
input xmin,xmax(xmin<xmax),eps=0.5 2.0 1.0e-6
19)x1,f1:x2,f2= 0.8767251968, -0.0000011344:
0.8767266273, 0.0000004588
aplsrvky01% exit
※16回,19回で収束している。
※解はそれぞれ
0.8767196655<x< 0.8767265320
0.8767251968 <x< 0.8767266273
にある。
§課題9 フローチャート
(大文字・小文字変換)
1文字入力
C
EOF
?
No
Yes
大文字
?
Yes
No
C=C+32
Cを出力
EXIT
小文字
?
Yes
C=C-32
No
§char型変数
“文字”は、
アスキーコードの0~127に対応している。
整数型のメモリサイズは4バイト(注)、
しかし、英数字1文字を表すには1バイトで十分。
char型変数
変数 に1バイトの領域を割り当てる。
宣言方法
char 変数名;
※1バイト(byte)=8ビット(bit)
2進数なので、 28 =256通りの表現が可能。
§文字列(char型配列)
文字列
char型の変数を多数ならべたもの。
配列
メモリ空間で連続な変数の並び
char型変数の配列なら、char型配列、と呼ぶ。
宣言方法と初期値
配列の型 配列名[ 要素数 ]= { 初期値の並び } ;
※初期値を書く場合、要素数は省略可能
ex.)
char str[8] = {‘Y’,’o’,’k’,’o’,’h’,’a’,’m’,’a’};
※str[0] = ‘Y’ 等と書くのと同じことになる。
§文字列 -例- -I 配列の要素を出力
※ cf. ex313.c。for文や関数putcharを使用。
#include <stdio.h>
2. main()
3. {
4.
char str[8] = {‘Y’,’o’,’k’,’o’,’h’,’a’,’m’,’a’};
5.
int i;
6.
for( i=0 ; i<8 ; i++ ){
※iが0から7のとき次を実行
7.
putchar(str[i]);
※1文字を出力する関数
8.
}
9.
putchar(‘\n’);
※最後に改行を出力
10. }
1.
 実行結果
Yokohama
§文字と文字列
表記の仕方
文字(1文字)は、‘
’(シングルクォート)で囲む。
文字列は、“ ”(ダブルクォート)で囲む。
配列の初期値は次のようにも書ける。
char str[9] = “Yokohama”;
※8文字を表せばいいのに、
何故配列要素数を9にしたか?
文字列の約束ごと
文字列の終わりには、自動的に、
“終わり”を意味するNULL(=‘\0’)が付加される。
※上記例でstrの要素数が9である理由!
§文字列 -例- -II 先ほどの例を文字列を用いて書きかえる。
→非常に簡単に!
1.
2.
3.
4.
5.
6.
#include <stdio.h>
main()
{
char str[9] = “Yokohama” ;
printf(“%s\n”, str);
※%sは文字列出力の書式
}
 実行結果
Yokohama
§文字列入力関数
C言語には様々な入力関数が用意されており、
目的に応じて使い分ける。
scanf
 scanf(“%s”,格納文字配列)
 格納文字配列はchar型配列で宣言されたもの。
 scanfの今までの使い方と違い、“&”を付けない。
※この理由はポインタの章で
fgets
指定長さ, stdin)
 標準入力(stdin = standard input)から、
指定長さ未満の文字列を取り込み、
格納文字配列に格納する。
※改行コードも取込むので注意すること。
 使う前に、次の様に格納文字配列を宣言する。
char 格納文字配列名[BUFFERSIZE]
 fgets(格納文字配列,
§文字列入出力関数 -例- fgets
 cf. 教科書p.137 ex324.c
1.
2.
3.
4.
5.
6.
7.
8.
#include <stdio.h>
#define BUFFERSIZE 1024
main()
{
char buffer[BUFFERSIZE];
fgets(buffer, BUFFERSIZE, stdin);※1行入力
printf(“input string : %s\n”, buffer);
※\nは省略可(文字列の最後に改行があ
る)
}
§文字列操作関数 -I文字列代入 strcpy (strings copy)
代入元文字配列)
代入元文字配列から代入先文字配列へ
文字配列の内容を複製する。
※このとき、2つの配列の大きさに注意すること。
※直接 = を用いた代入はできない!
strcpy(代入先文字配列,
文字列の長さ strlen (strings length)
strlen(文字配列)
文字配列の長さを返す。
※文字配列の最後にあるNULLは含まない。
§文字列操作関数 -II文字列の比較 strcmp (strings compare)
比較文字配列2)
比較文字配列を比較して以下の様な値を返す。
strcmp(比較文字配列1,
0 : 一致
 正数 :比較文字配列1 > 比較文字配列2
 負数 :比較文字配列1 < 比較文字配列2

※1文字ごとにアスキーコードを比較する。
※一致以外には使わない方が無難!
strcpy、strlen、strcmpを使うときには、以下が
必要。
#include <string.h>
§文字列操作関数 -例- とftp
ftpサーバから以下のようにして、
password.cというファイルをダウンロードせよ。
ファイルをダウンロードする方法
aplsrvky01% ncftp ftp.phys.ynu.ac.jp
※サーバーに接続
接続に成功すると ncftp> というプロンプトに変わる。
ncftp> cd pub/jisshu/primer ※目的のdirectoryに移る
ncftp> ls
※ファイル名一覧表示
ncftp> get password.c
※ダウンロード
ncftp> quit
※終了
§password.c -I1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
#include <stdio.h>
#include <string.h>
main()
{
char str1[80]; ※最大79文字を格納する(+NULL文字)
char str2[80];
int n1,n2,i,match=0;
system(“stty -echo”);
※echo off
while(match==0){
printf("Password:");
fgets(str1,80,stdin); ※文字列入力
n1=strlen(str1);
※文字列str1の長さ
putchar(10);
※改行
printf("Enter again:");
fgets(str2,80,stdin);
n2=strlen(str2);
§password.c -II19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
putchar(10);
if(n2<n1){
printf("2nd input is shorter than 1st one, n1=%d, n2=%d\n",n1,n2);
}else if(n2>n1){
printf("2nd input is longer than 1st one, n1=%d, n2=%d\n",n1,n2);
}else{
i=strcmp(str1,str2);
※文字列比較
if(i==0){
printf("matching ok.\n");
match=1;
}else{
printf("unmatching, do it again.\n");
}
}
}
system(“stty echo”);
}
※echo on
§文字列操作関数 -例- 解説
password.c の内容
 パスワードを二度入力して比較し、
入力ミスがあると再度入力を促す。※string.hを使用
 system(“stty –echo”)
キー入力の内容を画面に再表示するのを抑制するために
使われている(入力文字が画面に表示されなくなる)。
 fgetsを用いて、80の大きさを持つ
文字配列str1とstr2に入力文字列を格納する。
 strlenで入力文字列の長さを調べ、不一致なら長さを表示。
 長さが一致している場合、strcmpで文字列を比較。
 while文で、2つの入力文字列が一致するまで繰り返す。
 matchという変数は、一致が得られていないとき0(初期値)、
一致が得られたら1となるように使われている。
※フラグと呼ぶ使い方、フラグを立てる、等と言う。
 最後に入力文字表示をするように戻して終了。(エコーバック)
§課題10 今回の内容に関する課題
はなし。ただし、試験問題の問い4をレ
ポート課題とする。
ある実験でn個の有効数字7桁の実数値データを得た。そのデータを
順次入力したのち、平均値、最大値、最小値を求め表示するプログラム
を作成せよ。ただし、実数値は0から10の間の値をとるものとし、倍精度
で扱うこと。nは未定で、ユーザーが指定した個数とする。その指定の
しかたは工夫せよ。簡単なフローチャートも書け。