• 検索結果がありません。

今までの復習 プログラムで最低限必要なもの 入力 ( キーボードから ファイルから ) 出力 ( 画面へ ファイルへ ) 条件分岐 : 条件の成立 不成立により 異なる動作をする 繰り返し : 一定の回数の繰返し 条件成立の間の繰返し 関数の定義 関数の呼び出し C ではそれ以外に ポインタ データ

N/A
N/A
Protected

Academic year: 2021

シェア "今までの復習 プログラムで最低限必要なもの 入力 ( キーボードから ファイルから ) 出力 ( 画面へ ファイルへ ) 条件分岐 : 条件の成立 不成立により 異なる動作をする 繰り返し : 一定の回数の繰返し 条件成立の間の繰返し 関数の定義 関数の呼び出し C ではそれ以外に ポインタ データ"

Copied!
28
0
0

読み込み中.... (全文を見る)

全文

(1)

Cプログラミング演習1(再) 7

講義

では、Cプログラミングの基本を学び

演習

では、実践的なプログラミングを通し

て学ぶ

(2)

今までの復習

プログラムで最低限必要なもの

入力(キーボードから、ファイルから)

出力(画面へ、ファイルへ)

条件分岐 : 条件の成立・不成立により、異なる動作をする

繰り返し: 一定の回数の繰返し、条件成立の間の繰返し

関数の定義、関数の呼び出し

Cではそれ以外に、ポインタ、データ構造(配列や自作の構造)、

ライブラリの利用、(C++ではクラス)が必要

(3)

アルゴリズム

アルゴリズム

とは

料理で言えば

レシピ

要するに、

処理の段取り

どのような処理をどのような順で行うか

アルゴリズムによって処理効率に大きな違いがあ

ることも

(4)

文字列を対象とした「数え上げ」

lang.sist.chukyo-u.ac.jp/Classes/C/animals.txt

は次のような内容のファイルである

どんな動物が何回現れているだろうか?

いぬ ねこ ねこ さる いぬ ねこ ねこ さる ねこ わに ねこ いぬ ねこ ...

(5)

事前知識:文字と文字列

教科書「よくわかるC言語」第6章(p.63-75)

文字 --- 英数字や記号の1文字 ’a’, ’B’,’1’,’¥n’など

文字を記憶する変数の型は

char

---

char

acter(文字)

文字列 --- 文字の並び、文字の配列

例: ”abc”, ”123”, ”tab¥t end¥n”

文字列の最後には必ず

’¥0’ (ナル文字)

が入る(が、表示はされ

ない)-これが文字列の最後を表すキマリ

文字列を記憶する変数の型は

char string[10];

などとする

クイズ: ”a” は文字でしょうか、文字列でしょうか? また ’字’は文字でしょうか、文字列でしょうか? 答: 文字列 どちらでもない

(6)

事前知識:文字列

文字列 --- 文字の並び、文字の配列

ここで質問

abc”, ”123”, ”tab¥t end¥n”

はどんな

でしょうか?

型の例: 1 は

int

1.0 は

float

‘A’ は

char

ここで「文字列」と答えた人、気持ちはわかりますが、そういう名前の

(7)

事前知識:文字列

文字列 --- 文字の並び、

文字の配列

そう、答はここに書いてありました。だから、

例えば

”hello”

は、次の

文字の配列

を表しています:

h e l l o ¥0 文字 文字 ... 文字

だから、

char str[ ] = ”hello” ;

とすると、変数strには、上の配列が記憶されたメモリの場

所がセットされます

(8)

事前知識:文字列

文字列 --- 文字の並び、

文字の配列

このことから 、以下が「同じ意味」であることはわかりま

すね?

char str[ ] = “abc”;

char str[ ] = { ‘a’, ‘b’, ‘c’, ‘¥0’ };

(9)

文字の配列を指すポインタ

char str[ ] = ”hello” ;

とすると、変数strには、上の配列が記憶されたメモリの場所が

セットされます

と書きました。言い換えれば、 str (だけではなく「配列」全部)

は、文字(とか整数)の値を持っているのではなく、

文字の配列の場所(アドレス、

ポインタ

)が値です。

ここで

場所(ポインタ)の値から、その場所にあるデータを読み出す方法

があります。それが

*

です。

(10)

検証

右のプログラム(stringTest1.c)を試

してみましょう。

まず、str を文字列として、初期

値を入れています

その値を printf で文字列として

表示させています。

次に、strが指している場所の文

字、次の場所(次の場所は+1で得

られます)の文字、... を表示させ

ています

#include <stdio.h>

int main(void) {

char str[ ] = "abc";

printf("%s¥n", str);

printf("%x %x %x¥n",

str[0],str[1],str[2]);

printf("%c %c %c¥n",

str[0],str[1],str[2]);

printf("%c+%c+%c+%d¥n",

*str,*(str+1),*(str+2),*(str+3));

return 0;

}

(11)

文字を指すポインタ

このように、* はその変数の値がどのようなものを表してい

るか(char, int, floatなど)を表す記号であることがわかりました。

(この記号は、すでにファイルを扱うときに出ていました)

この知識を用いて、以下を考えてみましょう:

char str[ ] = “abc”;

char *try = “abc”;

クイズ: 変数 try がどのようなものか、説明してみてください。

(12)

検証

右のプログラム(stringTest3.c)を試

してみましょう。

まず、str を文字列とし、tryにも

初期値を入れています

tryの値を printf で文字列として

表示させています。

次に、tryが指している場所の文

字、次の場所(次の場所は+1で得

られます)の文字、... を表示させ

ています

最後にstr と tryが等しいかを調べ

ています

#include <stdio.h> int main(void) { char str[ ] = "abc"; char *try = "abc";

printf("%s¥n", try);

printf(“%c(%c(%c(%d¥n”,

*try,*(try+1),*(try+2),*(try+3)); printf("str == try? ans = %d¥n",

str == try); return 0;

(13)

文字の配列とポインタの関係

右のプログラム(stringTest2.c)を試 してみましょう。 “abc” という文字の配列において、 それぞれの要素(例えば str[1])が どのような値なのか、またその アドレスがどうなっているかを 示すプログラムになっています。 このことから、 (1)str[1] と *(str+1)が同じもので あること、 (2) 文字の配列の要素が, メモリ上 では1番地ずつずれていること がわかります。 #include <stdio.h> int main(void) { char str[ ] = "abc"; printf("%s¥n", str); printf("%x %x %x¥n", str[0],str[1],str[2]); printf("%c-%c-%c-%d¥n", *str,*(str+1),*(str+2),*(str+3)); printf("---¥n"); printf("%x %x %x¥n",

&str[0], &str[1], &str[2]);

printf("%x %x %x¥n", str, str+1, str+2); return 0;

(14)

文字列の配列

#include <stdio.h> int main(void) { char str[ ][5] = {"ab","xyz","漢字"}; printf("%x %x %x¥n", str[0],str[1],str[2]); printf("%s %s %s¥n", str[0],str[1],str[2]); printf("%s-%s-%s¥n", *str,*(str+1),*(str+2)); return 0; }

右のプログラム(stringTest4.c)を試

してみましょう。

ここでは、文字列の配列 str を定

義しています(この場合 5 という

文字の長さ指定が必要です---書

かずにコンパイルしたらどうな

るか、やってみましょう)

なお、

走らせる前に

、どのよう

な表示がなされるか、

推測

して

みましょう

(15)

解説

18ff44 18ff45 18ff46 18ff47 18ff48 18ff49 18ff4a ... 18ff4e 0x8a 18ff4f 0xbf 18ff50 0x8e ... str char str[ ][5] = {"ab","xyz","漢字"}; によって、 メモリ上に「5バイト」×3 の場所が確保され、そこに文字列 が記憶される なお、「漢」は 0x8abf 「字」は 0x8e9a Shift-JISで表現される 参考: http://qpon.quu.cc/pc/sjis.htm 5バイト 5バイト str[0] str[1] str[2] ‘a’ ‘b’ ‘¥0’ ‘x’ ‘y’ 不明 不明

(16)

文字列に関する関数

教科書のp.71 :

string.h

ヘッダファイルにて定義されている

strcpy(char s1[ ], char s2[ ])

strcat(char s1[ ], char s2[ ])

int strcmp (char s1[ ], char s2[ ])

int strlen(char s[ ])

(17)

文字列を対象とした「数え上げ」

lang.sist.chukyo-u.ac.jp/Classes/C/animals.txt

の中にどんな動物が何回現れているかを数えるプログラムをつくろう

ただし、どんな動物が現れるか分からないままではちょっと難しいの

で(そのうち出来るようになるはずだが)、ここでは

「いぬ、ねこ、うさぎ、くま、さる、たぬき、きつね、ぱんだ、ねず

み、わに」だけが出てくる可能性があるものとしよう

(18)

システムの設計

概略、次のようなアルゴリズムを考える

1. ファイル(animals.txt)から一行ずつ読み込み、文字列を

要素とする配列(仮に変数名を

str

とする)にその文字列を

記憶する

2. 候補の動物名の一個ずつに対し、

1.

strの要素それぞれに対して、一致するかどうか調べる。

2.

一致した個数を、動物名とともに表示する

(19)

1.ファイル(animals.txt)から一行ずつ読み込み、文字列

を要素とする配列(仮に変数名を

str

とする)にその文字

列を記憶する

これを具体的にどうするかを考えよう。

必要な物は、

(1)文字列を要素とする配列

(2)ファイル(animals.txt)から一行ずつ読み込んで、配列で記

憶する方法

文字列の長さをLEN、ファイルの行数をLINESとすると char str[LINES][LEN]; // チェック!なぜこの順番? これは今までにもやってきたこと。。。

(20)

1.ファイル(animals.txt)から一行ずつ読み込み、文字列

を要素とする配列(仮に変数名を

str

とする)にその文字

列を記憶する

これを具体的にどうするかを考えよう。

(2)

ファイル(animals.txt)から一行ずつ読み込んで、配列で記

憶する

FILE *fp; int n=0; fp = fopen(“animals.txt”,”r”); // animals.txtを開く

while (fscanf(fp, “%s”, str[n]) != EOF) { // str[n]に読み込んだ文字列を記憶 n++;

} // nには読み込んだ行数が入っている

文字列の長さをLEN、ファイルの行数をLINESとすると

char str[LINES][LEN]; // チェック!なぜこの順番?

(21)

2. 候補の動物名の一個ずつに対し、

strの要素それぞれに対して、一致するかどうか調べる。

一致した個数を、動物名とともに表示する

次に、これを具体的にどうするかを考えよう。

必要な物は、

(1)候補の動物名を記憶する方法

(2) 文字列同士を比較して、一致しているかどうか、調べ

る方法

(22)

(1)候補の動物名を記憶する

教科書に従って、次のようにしてもよい

char Animals[][LEN] = {"いぬ", "ねこ", "うさぎ", "くま",

"さる", "たぬき", "きつね", "ぱんだ", "ねずみ", "わに"};

だから。。。

文字列の配列は

char 変数名[ ][LEN] = { 初期値

}; で宣言

配列 二重配列 初期値となる文字列の並び 候補は:「いぬ、ねこ、うさぎ、くま、さる、たぬき、きつね、ぱんだ、ねずみ、 わに」 だから、要素を文字列とする配列を用意すれば良い。 その配列(変数)の名前を Animals とすると、(LENの値を最初に与えておく)

(23)

(1)候補の動物名を記憶する(別解)

候補は:「

いぬ、ねこ、うさぎ、くま、さる、たぬき、きつ

ね、ぱんだ、ねずみ、わに

だから、要素を文字列とする配列を用意すれば良い。

その配列(変数)の名前を Animals とすると、

char* Animals[] = {"いぬ", "ねこ", "うさぎ", "くま", "さる",

"たぬき", "きつね", "ぱんだ", "ねずみ", "わに"};

だから。。。

文字列の配列は char* 変数名[ ] = { 初期値 }; で宣言

要素は文字列 配列 初期値となる文字列の並び

(24)

#include <stdio.h> // 候補となる動物の個数 #define NUM 10 // 動物名の最大長さ #define LEN 8 int main(void) { // 配列 Animals の宣言 // 他に必要な変数があれば、その宣言 // Animalsの値をprintfを用いて確認 for(i=0; i < NUM; i++) {

printf("%s¥n",Animals[i]); } return 0; } ここまでできたら、 ちゃんと動くか テストしてみよう テスト1. 配列 Animals 右のプログラムを完成させ animalsCheck.c と名前をつけ、 実行してみよう どんな結果が表示されれば 成功といえるか、考えてから 実行しよう 書けるよね?

(25)

#include <stdio.h> // ファイルの行数の最大値を仮に100とする #define LINES 100 // 動物名の最大長さ #define LEN 8 // 読み込み対象のファイル名 #define InFile "animals.txt“ int main(void) { // 配列strなど、必要な変数の宣言 // ファイルから読み込んで配列strに記憶 // その時に読み込んだ行数を変数nに記憶 // ファイルを閉じる // strの値をprintfを用いて確認 for(i=0; i< n; i++) {

printf("%s¥n",str[i]); } return 0; } テスト2. ファイルからの読み込み 右のプログラムを完成させ animalsInput.c と名前をつけ、 実行してみよう どんな結果が表示されれば 成功といえるか、考えてから 実行しよう 書けるよね?

(26)

(2) 文字列同士を比較して、一致しているかどうか、調べる

stringh. ヘッダファイルで定義された

strcmp 関数を使う

これがどんな引数をとり、どういう条件で

どんな値を返すかを確認する

(27)

#include <stdio.h> #define NUM 10 #define LINES 100 #define LEN 8 int main(void) { // 配列 Animals と str 他必要な変数の宣言 // 1. ファイルから読み込んだ文字列を // 配列strに記憶 // ファイルを閉じる // 2.候補の動物名の一個ずつに対し(繰り返し) for(i=0; i<NUM; i++) {

// ① 一致した個数を記憶する変数mに0代入 // ② str の要素それぞれに対して動物名が // 一致すれば、m++ とする // ③ m>0なら、動物名とmの値を表示 } return 0; } 以上ができたら、プログラム を完成させよう(countAnimals.c) 1. ファイル(animals.txt)から一 行ずつ読み込み、文字列を 要素とする配列(仮に変数名 をstrとする)にその文字列を 記憶する 2. 候補の動物名の一個ずつに 対し、 ① strの要素それぞれに対し て、一致するかどうか調 べる。 ②一致した個数を、動物名と ともに表示する

(28)

プログラムがかけたら…

コンパイル(ビルド)して

animals.txt のデータで試してみよう

参照

関連したドキュメント

(16) に現れている「黄色い」と「びっくりした」の 2 つの繰り返しは, 2.1

の変化は空間的に滑らかである」という仮定に基づいて おり,任意の画素と隣接する画素のフローの差分が小さ くなるまで推定を何回も繰り返す必要がある

「文字詞」の定義というわけにはゆかないとこ ろがあるわけである。いま,仮りに上記の如く

この数字は 2021 年末と比較すると約 40%の減少となっています。しかしひと月当たりの攻撃 件数を見てみると、 2022 年 1 月は 149 件であったのが 2022 年 3

このような情念の側面を取り扱わないことには それなりの理由がある。しかし、リードもまた

えて リア 会を設 したのです そして、 リア で 会を開 して、そこに 者を 込 ような仕 けをしました そして 会を必 開 して、オブザーバーにも必 の けをし ます

サンプル 入力列 A、B、C、D のいずれかに指定した値「東京」が含まれている場合、「含む判定」フラグに True を

基準の電力は,原則として次のいずれかを基準として決定するも