スライド9

プログラミング演習Ⅱ
第9回
文字列
情報・知能工学系
山本一公
[email protected]
前回の課題の解説・ポイント(1)
• 課題7-1
#define
swap(type, x, y)
{type tmp = x; x = y; y = tmp;}
– “{” “}” で囲むことによって、ブロックを作る。それ
によって、変数 tmp のスコープをブロック内に閉じ
込める。
– gcc の ”-E” オプションで、マクロの展開を実際に確
かめることができる。
– 第3の変数を使わずに、変数の値を交換することは可
能である(そういう方法がある)。その場合、typeは
不要。
前回の課題の解説・ポイント(2)
• 課題7-2
int main(void)
{
int ch, count = 0;
while ((ch = getchar()) != EOF) {
if (ch == ’\n’) count++;
}
printf(”行数 = %d\n”, count);
}
– 上記は改行を数えるだけの基本形
– 行の途中で EOF が来た場合にどうするか?を考える
と
少し複雑になる
今日の内容
• 教科書 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)
• 代入
– 初期化は文字列リテラルでできる
– 文字列リテラルを代入することはできない
str = {‘A’, ‘B’, ‘C’, ‘\0’};
str = “ABC”
// どちらもできない!
– 代入は1文字ずつ
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次元配列にすれば、文字列の配列になる
char cs[][6] = {“Turbo”, “NA”, “DOHC”};
要素文字列の最大長+1以上必要
– 文字列リテラルが使える点を除けば、
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’
文字列の操作(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節
– 「文字列を扱うライブラリ関数」
– 文字列の長さを数えたり、文字列をコピーす
る関数が標準で用意されている
– 普通はこれらを使う
今週の課題
1. p.219、演習9-8のプログラムを作成せよ。main関数等も
作成して、完成したプログラムを作成すること。
2. 2つの文字列 str1[], str2[] が、英字については大文字・
小文字を区別しないで、一致しているかどうか判定す
る関数 int stricomp(const char str1[], const char str2[]) を作
成せよ。返却値は一致していれば1、不一致なら0とす
ること。
また、その関数を利用して2つのテキストファイルの
内容が大文字・小文字を区別しないで一致しているか
どうか判定するプログラムを作成せよ。ファイル名は
キーボードから入力できるようにすること。
課題8-2後半の考え方
1. scanf()でファイル名を2つ入力
2. 両方のファイルから1行ずつ読み込む
–
改行が来るまでfgetc()で1文字ずつ読んで文字列と
して保存
•
–
fgets()を使って行単位で読む方が簡単
1行の長さを適当に(長めに)決めておく
3. 作成した関数を使って比較
–
一致しない箇所が見つかった時点で、一致しないと
表示して終了
4. 2.以下を繰り返す。ファイルの最後まで一致し
ない箇所がなければ一致と見做す。
レポートについて
• 電子メールで提出
– 提出先は [email protected]
– Subjectを「プログラミング演習2 課題8提出
番号・氏名 」とすること
– C言語ソースファイルを添付する
学籍
• メールの本文には何も書かなくて良いです
– ソースファイルの頭にコメントで以下の情報を入れる
• 学籍番号・氏名
• プログラムの説明(どのように動くのか、工夫した点等)
• 実行結果(長い場合は一部)を貼る
– 提出締切は、1月9日(水) 12:00 (次の授業の前)
授業用Webサイト
• URL:
http://www.slp.cs.tut.ac.jp/~kyama/programming2/
– 課題のpdfファイルが置いてあります。
– 授業で使ったpptファイルを置いていきます。
• 質問メールは、以下のどちらかのアドレスまで
– [email protected][email protected]
• C-515へ直接質問しに来ても構いません