【C++Builder Starter チュートリアルシリーズ】シーズン2 第6回 ‟文字列とオブジェクト„ [JAPAN]
【C++Builder Starter チュートリアルシリーズ】シーズン2 第6回 ‟文字列とオブジェクト„ [JAPAN]
C++Builder Starter Edition シーズン2 第6回 ‟文字列とオブジェクト„
2017年1月23日より 「Delphi / C++Builder Starter チュートリアルシリーズ」 シーズン2、全9回、3月27日まで、毎週月曜日、Delphiパートが 17時00分~17時20分、 リアルタイム放送スペシャルコンテンツが5分~10分、C++Builderパートは 17時30分~17時50分の時間割でお送りしています。
無料でダウンロード&利用できる開発環境のDelphi / C++Builder Starter エディションを使用して、プログラミング言語のDelphi (Object Pascal ), C++の基礎を学ぶオンラインセッションです。
https://community.embarcadero.com/blogs/entry/2-japan
サマリ
アジェンダ
- 今日のねらい
- 文字列を知る
- 文字列の操作
- クラスとオブジェクトの概略を知る
- 実施内容
- 文字列の型
- 文字列の代入とヘルパーについて
- クラスとオブジェクトの意味を知る
- クラスの定義とオブジェクトの宣言
スライド資料
https://www.slideshare.net/ssuser8bd3f7/cbuilder-starter-2-cbuilder-6
開発環境のインストール
開発環境のインストールについては、[Delphi / C++Builder Starter チュートリアルシリーズ] 第1回 ‟無料で始めよう アプリ作成„ にて丁寧な説明がありますので、そちらをご視聴の上でインストールを進めてください。
https://community.embarcadero.com/blogs?view=entry&id=9038
実施内容
文字列の前に、文字の話
- コンピュータで扱う「文字」には、識別用の番号(=文字コード)が割り振られている
- 同じ文字でも、割り振り方のルール(=符号化)によって割り当てられる番号が違う
- 文字の集まりを文字集合という
- コンピュータの日本語環境では、日本語の文字集合としてJIS漢字やUnicodeが用いられる
- 文字コードには Shift_JIS, UTF-8, UTF-16 が用いられる
文字集合/文字コード | JIS/Shift_JIS | Unicode/UTF-8 | Unicode/UTF-16 |
---|---|---|---|
A | 0x41 | 0x41 | 0x0041 |
あ | 0x82A0 | 0xE38182 | 0x3042 |
⌘ | (未対応) | 0xE28C98 | 0x2318 |
Unicode, Shift_JIS, ANSI, ASCII ??
- Unicode
- 世界中のすべての文字を統一的に扱う目的で策定された文字集合
- 英語、日本語だけではなく、韓国語、中国語などの多言語の文字集合を含む
- Shift_JIS
- Windows以前のパソコン/マイコンでJISの漢字を扱うための文字コードの一種
- Windows95までの日本語OSではShift_JISが標準的に用いられている
- ANSI
- Unicode以前の Windows で多言語を扱うための方法
- 「ASCII + 言語ごとの符号化」をコードページとして規定している(CP932 = Shift_JIS, CP949 = 韓国語、など)
- 各国語版WindowsでANSIという場合は、それぞれの初期言語のことを指す
- ASCII
- ASCIIは数値、アルファベット、記号を表現できる文字集合
- Shift_JISはASCIIをベースに拡張されている
Unicodeのコードの種類
- UTF-8
- ASCIIとの互換性を重視した可変長コードであり、アルファベットを1バイトで表す
- HTMLなどの文書はUTF-8を用いる(基本の制御構造がASCIIをベースとするため)
- ラテン文字は2バイト、日本語、中国語、韓国語などは3バイト 、使用頻度の低い文字は4バイト
- UTF-16
- 世界中のすべての文字は2バイト = 65536個に収まると考えて設計された
- しかし実際には2バイトで収まらなかったので、使用頻度の低い文字は4バイトで表すことにした
- Windows API ではUTF-16が用いられるため、一部のアプリは UTF-16を Unicode と表記している
- UTF-16を用いると日本語を多用する文書では平均的にデータ量が少なくなる
- UTF-32
- すべての文字を4バイトで表す
- 固定長なので高速処理が可能だが、使用するデータ量が最も多くなる
参考: Windows のメモ帳アプリでの文字コード選択
文字列(型)
- String型 ( = UnicodeString型)
- UTF-16 で文字列を格納する型
- 新規に作るアプリケーションの文字列では String またはUnicodeString型を用いる
- AnsiString型
- Shift_JISを取り扱う処理向け
- UTF8String 型
- AnsiString をベースとして UTF-8 を取り扱う型
- UTF-8 での入出力が必要な場合に用いる(ファイル入出力やインターネット経由の通信など)
文字集合と収録文字
- それぞれの文字集合で収録文字が違う
- 収録文字数の多いコードから少ないコードへの変換は文字が失われることも
文字列型の代入(コード例)
- 文字列相互代入によるデータの欠落の例
{
AnsiString strSJIS;
UTF8String strUTF8;
String strUTF16;
strSJIS = L"日本語"; // OK: "日本語"は Shift_JISで表せる文字である
strUTF8 = strSJIS; // OK: UnicodeにはすべてのShift_JISが含まれる
strUTF16 = strSJIS; // OK: UnicodeにはすべてのShift_JISが含まれる
strUTF16 = L"⌘"; // OK: Unicodeを扱う型にUnicode文字を代入している
strUTF8 = strUTF16; // OK: Unicode同士なので常に成功するが、データ形式の変換が生じる
strSJIS = L"?野屋"; // NG: 「? = つちよし」はShift_JISに存在しない文字なので失われる
strSJIS = strUTF8; // NG: strUTF8 ="⌘" のため、Shift_JIS に代入すると失われる
}
文字列型の文字を参照する
- 文字列型[添字]で参照すると、文字列型の1つ1つの文字を参照できる
- C++Builderで使用できる文字列型のうち、Delphiと共通の文字列型の添字は 1 から始める
{
String strUTF16 = L“Hello C++Builder”;
// 文字列の各文字を配列として参照する
for ( int i = 1 ; i <= strUTF16.Length() ; i++ ) {
Memo1->Lines->Add(
Format( "i=%d: %s", ARRAYOFCONST(( i, strUTF16[i] )) ) );
}
}
文字列型の代入と連結
- 文字列の代入には代入演算子 = 使用可能
- 文字列の結合には + が使用可能
{
String str1 = L"Hello";
String str2 = L"C++Builder";
str1 = str1 + L" " + str2;
// "Hello C++Builder" と表示される
Memo1->Lines->Add(str1);
}
文字列型に対する操作
- 文字列型には様々な操作方法が提供されている
- 一例を紹介
操作 | 説明 |
---|---|
= | 文字列をコピーして代入する |
+ | 文字列を連結する |
== | 文字列を比較して等しいかどうかを返す |
IsEmpty | 文字列が空(文字を含んでいない)かどうかを返します。 |
Length | 文字列の長さを返す |
Format, printf | 書式文字列および引数の組み合わせから文字列を生成する |
UpperCase, LowerCase | すべて大文字、または小文字に変換した文字列を返す |
Trim, TrimLeft, TrimRight | 前や後ろのスペースを除いた文字列を返す |
Format関数
- 設定した書式に基づいて、一連の引数を文字列化する関数
// Formatの書式
Format(“文字列および書式”, ARRAYOFCONST((文字列に組みこむデータをカンマで区切って連ねる)) );
{
String strWeather, strOutput;
int iTemparture;
strWeather = L”雨";
iTemparture = 20;
//Formatはこんな感じで使えます
strOutput = Format(
L”明日の天気は %s 、気温は %d 度になるでしょう", ARRAYOFCONST(( strWeather, iTemparture ))
);
Memo1->Lines->Add( strOutput );
}
クラス
クラスとは「ユーザが定義した型」と「型に対する操作」を組み合わせたもの
// クラスを使わない例
// struct は C++ ではメソッドを組み合わせてクラスにすることも可能ですが、
// ここでは C 言語由来の型だけの定義として扱っています
// 本件については第7回 オブジェクト指向の回で別途フォローします
struct SZipCode {
int ZipCode;
String Pref;
String City;
String Area;
};
// 関数宣言部
String getFullAddress( SZipCode zipCode );
// 都道府県名 + 市区町村名 + 町域名を連結して返す処理
String getFullAddress( SZipCode zipCode ) {
return zipCode.Pref + " " + zipCode.City + " " + zipCode.Area;
}
// 構造体の変数を作り、初期化する
SZipCode zipdata = { 1120004, L"東京都", L"文京区", L"後楽" };
// 関数名だけでは SZipCode との関連付けが分かりづらい
getFullAddress( zipdata );
// クラスの例
class TZipCode {
public: // メンバ変数。public宣言でクラス外から操作可能
int ZipCode;
String Pref;
String City;
String Area;
// クラスに紐づく関数(メンバ関数)の宣言
String getFullAddress();
};
// 都道府県名 + 市区町村名 + 町域名を連結して返す処理
String TZipCode::getFullAddress() {
return Pref + " " + City + " " + Area;
}
// クラスの実体(オブジェクト)を作り、メンバを初期化する
TZipCode zipdata = { 1120004, L"東京都", L"文京区", L"後楽" };
// メンバ関数の実行はオブジェクトに対する操作である
zipdata.getFullAddress();
クラスの特徴
-
クラスの特徴
- データと操作が紐付いている
- struct(構造体)の場合はデータ型と操作が紐付いておらず、型が一致する限りは無制限に操作できる
- クラスの場合は操作(メンバ関数)を適切に実装することで安全な操作を提供できる
-
データの隠蔽
- クラスのメンバ変数はクラスの外から参照できない
- クラスの中からは隠蔽されたデータを自由に参照できる
- クラス外から参照させたい場合は public 宣言する
-
クラスの継承(詳細は次回で説明)
- あるクラスを基本の共通の型(親クラス)とし、追加のデータ型や操作をつけた「派生クラス」を定義できる
- 派生クラスは元の型の特徴を引き継ぐ(継承)
- 例: 親クラス = 自動車 = 動力源を内蔵し、レールや架線によらず運転する車(ただし原付を除く)
- この親クラスから、用途の違い(自家用、トラック、バス、タクシー、消防車、救急車など)で派生クラスを定義できる
- ただしいずれの派生クラスも、親クラスの定義を含んでいる(継承している)
クラスの実装の基本形
class クラス名 {
private:
// クラス内だけで使う変数や関数の宣言
public:
// クラス外から利用できる変数や関数の宣言
戻り値の型 何かのメンバ関数( … );
// 特別な意味を持つメンバ関数の宣言
クラス名( … ); // クラスと同名の関数は、オブジェクトを生成する時に実行(コンストラクタ)
~クラス名(); // クラス名に ~ が付く関数はオブジェクトの破棄時に実行(デストラクタ)
};
クラス名::クラス名( int Z, String P, C, A ) {
// オブジェクト生成時の初期化処理を書く
}
クラス名:: ~クラス名() {
// 破棄時の終了処理を書く。クラスの操作に伴って動的生成したオブジェクトは、ここで確実に捨てる
}
戻り値の型 クラス名::何かのメンバ関数() {
…
}
クラスの実装例
class TZipCode {
private: // クラス内だけで使う変数や関数の宣言。変数は特に理由がある場合を除いて private 宣言する。
int ZipCode;
String Pref;
String City;
String Area;
public: // クラス外から利用できる変数や関数の宣言。外部との相互の受け渡しが必要な変数のみ public 宣言する。
String getFullAddress();
// 特別な意味を持つメンバ関数の宣言
// クラスと同名の関数は、オブジェクトの生成時に実行(コンストラクタ)
TZipCode( int ZipcCode, String Prev, String City, String Area );
// クラス名に ~ が付く関数はオブジェクト破棄で実行(デストラクタ)
TZipCode();
};
TZipCode::TZipCode( int Z, String P, String C, String A ) {
// オブジェクト生成時の初期化処理を書く
ZipCode = Z; Pref = P; City = C; Area = A;
}
TZipCode::~TZipCode() {
// 破棄時の終了処理を書く。クラスの操作に伴って動的生成したオブジェクトは、ここで確実に捨てる
}
String TZipCode::getFullAddress() {
return Pref + " " + City + " " + Area;
}
クラスの利用例
{
// クラスのインスタンスを new で確保する例
// データはアプリケーション共通の領域に作られる
TZipCode *zipdata = new TZipCode( 1120004, L“東京都”, L“文京区”, L“後楽” );
// new で確保した場合は、メンバ関数やメンバ変数への参照は -> で行う
Memo1->Lines->Add( zipdata->getFullAddress() );
// new した場合は不要になった時点で必ず delete する。
delete zipdata;
}
{
// 実行中の関数やブロック用の領域に確保する例
TZipCode zipdata2( 1120004, L“東京都”, L“文京区”, L“後楽” );
// メンバ関数やメンバ変数への参照は . で行う
Memo1,Lines.Add(zipdata2.getFullAddress() );
// 確保したインスタンスは関数やブロックを抜けるときに破棄される
}
セミナー動画
チュートリアルセミナー視聴ページにて、シーズン2の放送分を視聴できるようにしています。チュートリアルシリーズに申し込み済みの方はメールてご案内済みの視聴ページよりご視聴ください。まだ申し込んでいない方は下記アドレスよりお申込みいただくと視聴できます。
http://forms.embarcadero.com/starter-tutorial-webinar
また、シーズン1の放送分は youtube の下記ページよりご視聴いただけます。
https://www.youtube.com/playlist?list=PLoQxxVNY10oEmNSjiPdYPV_E9IL9ipico
シーズン1のまとめ記事もございますので、こちらも併せてお読みください。
https://community.embarcadero.com/blogs/entry/delphi-c-builder-starter-japan
■次回のC++Builderパートは2月27日(月) 17:30頃より、“文字列とオブジェクト„をお送りいたします。


Comments
-
Please login first in order for you to submit comments