170 likes | 321 Views
プログラミング演習 Ⅱ 第 9 回 文字列. 情報・知能工学系 山本一公 kyama@tut.jp. 前回の課題の解説・ポイント(1). 課題7-1 “{” “ }” で囲むことによって、ブロックを作る。それによって、変数 tmp のスコープをブロック内に閉じ込める。 gcc の ”-E” オプションで、マクロの展開を実際に確かめることができる。 第 3 の変数を使わずに、変数の値を交換することは可能である (そういう方法がある) 。その場合、 type は不要。.
E N D
プログラミング演習Ⅱ第9回文字列 情報・知能工学系 山本一公 kyama@tut.jp
前回の課題の解説・ポイント(1) • 課題7-1 • “{” “}” で囲むことによって、ブロックを作る。それによって、変数 tmpのスコープをブロック内に閉じ込める。 • gccの ”-E” オプションで、マクロの展開を実際に確かめることができる。 • 第3の変数を使わずに、変数の値を交換することは可能である(そういう方法がある)。その場合、typeは不要。 #define swap(type, x, y) {type tmp = x; x = y; y = tmp;}
前回の課題の解説・ポイント(2) • 課題7-2 • 上記は改行を数えるだけの基本形 • 行の途中で EOF が来た場合にどうするか?を考えると少し複雑になる int main(void) { intch, count = 0; while ((ch = getchar()) != EOF) { if (ch == ’\n’) count++; } printf(”行数 = %d\n”, count); }
今日の内容 • 教科書 pp.207~223 • 文字列の基本 • 文字列リテラル • ナル文字 • 文字列・文字配列 • 文字列の配列 • 文字列の操作
文字列(1) • 文字列リテラル(文字列定数) • ダブルクォートで文字を囲んだもの • 「”ABC”」 • 文字列 • C言語には「文字列型」が存在しないので、文字列の実体は「文字型(char型)の配列」 • 文字列の終端に ’\0’(数字のゼロ。ナル文字)が入っている A B C \0
文字列(2) • 文字列は printf() では ”%s” で表示できる • 最初のナル文字までが表示される • ナル文字が見つからなかったら、配列を定義した範囲を越えて延々と表示され続ける • 文字列操作でよくやるミスなので、注意すること • 初期化 • 宣言時に代入して初期化できる char ss[] = {‘A’, ‘B’, ‘C’, ‘\0’}; // 配列の初期化と同じ char ss[] = “ABC” // 面倒なので普通はこちら
文字列(3) • 代入 • 初期化は文字列リテラルでできる • 文字列リテラルを代入することはできない • 代入は1文字ずつ • すなわち「配列と同じ」です str = {‘A’, ‘B’, ‘C’, ‘\0’}; str = “ABC” // どちらもできない! str[0] = ‘A’; str[1] = ‘B’; str[2] = ‘C’; str[3] = ‘\0’;
文字列(4) • 空文字列 • 内容が空の文字列=先頭がナル文字 • scanf() による文字列の読み込み char name[40]; // 何文字入れられるか分からないので多めに scanf(“%s”, name); 文字列の場合は %s 先頭に”&”はいらない
scanfの危険性 • scanf() で ”%s” 指定子を用いると、何文字でも入力できてしまう!⇒ 用意した文字配列の要素を越えてしまう場合 がある⇒ 「バッファーオーバーラン」 • システムプログラムで起きると、セキュリティホールになる場合がある • “%10s” のように入力できる文字数を制限することで回避できる • gets() にも同じ問題。gets() の場合は回避策がない。 • gets() は使わない!代わりに fgets()を使う。
文字列の配列 • 文字列は文字型の配列 • 2次元配列にすれば、文字列の配列になる • 文字列リテラルが使える点を除けば、2次元配列の初期化と同じ • cs[0][0]が’T’、cs[1][0]が’N’、cs[2][0]が’D’、cs[0][1]が’u’、cs[1][1]が’A’、cs[2][1]が’O’ char cs[][6] = {“Turbo”, “NA”, “DOHC”}; 要素文字列の最大長+1以上必要
文字列の操作(1) • 文字列の長さを数える • p.216, List 9-8 • ナル文字が来るまでwhileを回して文字数を増やしていく • 1文字ずつ扱う • p.218, List 9-9 • ナル文字が来るまでwhileを回してputchar() で1文字ずつ表示する • 普通の配列と同じ
文字列の操作(2) • 文字列の配列の受け渡し • 2次元配列の場合と同じ • p.221, Column 9-1「文字列の初期化」 • これもよくやるミス • 「ナル文字がない」⇒ printf() で ”%s” で表示したときに、文字列の終端がないので、訳の分からない表示になってしまう可能性が高い
文字列の操作(3) • 大文字・小文字の変換 • toupper() / tolower() • 引数は int型であることに注意 • p.260, 11-3節 • 「文字列を扱うライブラリ関数」 • 文字列の長さを数えたり、文字列をコピーする関数が標準で用意されている • 普通はこれらを使う
今週の課題 • p.219、演習9-8のプログラムを作成せよ。main関数等も作成して、完成したプログラムを作成すること。 • 2つの文字列 str1[], str2[] が、英字については大文字・小文字を区別しないで、一致しているかどうか判定する関数 intstricomp(const char str1[], const char str2[]) を作成せよ。返却値は一致していれば1、不一致なら0とすること。また、その関数を利用して2つのテキストファイルの内容が大文字・小文字を区別しないで一致しているかどうか判定するプログラムを作成せよ。ファイル名はキーボードから入力できるようにすること。
課題8-2後半の考え方 • scanf()でファイル名を2つ入力 • 両方のファイルから1行ずつ読み込む • 改行が来るまでfgetc()で1文字ずつ読んで文字列として保存 • fgets()を使って行単位で読む方が簡単 • 1行の長さを適当に(長めに)決めておく • 作成した関数を使って比較 • 一致しない箇所が見つかった時点で、一致しないと表示して終了 • 2.以下を繰り返す。ファイルの最後まで一致しない箇所がなければ一致と見做す。
レポートについて • 電子メールで提出 • 提出先は prog2@slp.cs.tut.ac.jp • Subjectを「プログラミング演習2 課題8提出 学籍番号・氏名 」とすること • C言語ソースファイルを添付する • メールの本文には何も書かなくて良いです • ソースファイルの頭にコメントで以下の情報を入れる • 学籍番号・氏名 • プログラムの説明(どのように動くのか、工夫した点等) • 実行結果(長い場合は一部)を貼る • 提出締切は、1月9日(水) 12:00(次の授業の前)
授業用Webサイト • URL: http://www.slp.cs.tut.ac.jp/~kyama/programming2/ • 課題のpdfファイルが置いてあります。 • 授業で使ったpptファイルを置いていきます。 • 質問メールは、以下のどちらかのアドレスまで • kyama@tut.jp • prog2@slp.cs.tut.ac.jp • C-515へ直接質問しに来ても構いません