C/C++ ポインタ入門 > 文字列クラス 演習問題
Nobuhide Tsuda
Oct-2013
演習問題
String は char 文字列を持つ文字列クラスです。
operator[](ix), at(ix) で文字を参照でき、insert(ix), erase(ix) 等で文字を挿入・削除することが出来ます。
文字挿入時に文字列領域が足りなくなると、文字列領域が自動的に拡張されます。
上記以外にも、isEmpty(), size() などオブジェクトの状態を返すメンバ関数や、
resize(sz, ch), reserve(sz) などでオブジェクトの状態を変えるメンバ関数を持ちます。
std::string と概ね同一ですが、文字型が char型固定という点が異なります。
String は文字列を格納する領域を動的に確保し、m_data がそこを指します。
確保した文字列領域のサイズが m_allocSize に格納されます。
文字列領域の頻繁な再確保を避けるために、領域は実際のサイズよりも余分に確保されます。
m_size に文字列領域に実際に保存されている文字数('\0'はカウントしない)が格納されます。
※ 動的配列とほとんど同じですが、文字列の末尾には '\0' が格納されている点が異なります。
※ そのため、再アロケート無しに格納できる文字数上限(キャパシティ)は allocSize - 1 となります。
文字が追加され文字列領域が足りなくなった場合、領域サイズは2倍されてメモリが確保され、
古い領域から新しい領域に文字列がコピーされ、古い領域のメモリは解放されます。
- ★下記のクラスを定義するコードを書き、ビルドしてみなさい。
class String {
private:
char *m_data; // 文字列を格納するエリア、'\0' ターミネイトされている
int m_size; // 文字数、'\0' は数に含まない
int m_allocSize; // アロケートされた m_data のサイズ
};
- ★ String クラスにコンストラクタ String() を追加し、サイズを 0 に、アロケートサイズを 8 に,
m_data がアロケートしたメモリ領域を指すよう初期化しなさい。
- String オブジェクトを生成し、メンバ変数が全て正常に初期化されていることをデバッガで確認しなさい。
- テストコード、
解答例
- ★ String クラスにデストラクタ ~String() を追加し、m_data を delete するようにしなさい。
- String オブジェクトを生成・破棄し、文字列領域が正しく解放されることをデバッガで確認しなさい。
- 解答例
- ★ コンストラクタ String(int sz, char c) を追加し、サイズ、キャパシティを sz に、
m_data がアロケートしたメモリ領域を指すようにし、文字列にすべて c を格納しなさい。
- String str(3, 'a') でオブジェクトを生成し、メンバ変数が全て正常に初期化されていることをデバッガで確認しなさい。
- テストコード、
解答例
- ★ コンストラクタ String(const char *src) を追加し、
引数で指定された文字列(終端文字有り)と同じ文字列をオブジェクトに設定しなさい。
- String str("abxyz") でオブジェクトを生成し、メンバ変数が全て正常に初期化されていることをデバッガで確認しなさい。
- テストコード、
解答例
- ★ コンストラクタ String(const char *first, const char *last) を追加し、
引数で指定された範囲の文字(終端文字無し)と同じ文字列をオブジェクトに設定しなさい。
- const char *s = "xyz987"; String str(s, s + strlen(s)) でオブジェクトを生成し、メンバ変数が全て正常に初期化されていることをデバッガで確認しなさい。
- String str2(s, s + 3) でオブジェクトを生成し、str2 の文字列が "xyz" に初期化されていることをデバッガで確認しなさい。
- テストコード、
解答例
- ★★
コピーコンストラクタ String(const String &str) を追加(実装)しなさい。
文字列 str がアロケートしているメモリと同じサイズのメモリを new でアロケートし m_data がそこを指すようにし、
str が指すデータを m_data の部分にコピーしなさい。
m_size は str の指す文字列サイズを設定するようにしなさい。
- String s1("abxyz"); String s2(s1) でオブジェクトを生成し、s2 の文字列が s1 と同じになっていることを確認しなさい。
- テストコード、
解答例
- ★bool isEmpty() const 文字列が空かどうかを判定するメンバ関数を実装しなさい。
- String クラスのオブジェクト s を生成し、s.isEmpty() が true を返すことを確認しなさい。
- String s2(3, 'a') を生成し、s2.isEmpty() が false を返すことを確認しなさい。
- テストコード、
解答例
- ★int size() const String オブジェクトの文字数を返すメンバ関数を実装しなさい。
- String クラスのオブジェクト s を生成し、s.size() が 0 を返すことを確認しなさい。
- String s2(3, 'a') を生成し、s2.size() が 3 を返すことを確認しなさい。
- テストコード、
解答例
- ★int capacity() const String オブジェクトのキャパシティ(再アロケートせずに格納できる最大文字数)を返すメンバ関数を実装しなさい。
- String クラスのオブジェクト s を生成し、s.capacity() が 7 を返すことを確認しなさい。
- String s2(10, 'a') を生成し、s2.capacity() が 10 以上を返すことを確認しなさい。
- テストコード、
解答例
- ★char front() const 先頭の1文字を返すメンバ関数を実装しなさい。文字列が空の場合は '\0' を返しなさい。
- String s; を生成し、s.front() が '\0' を返すことを確認しなさい。
- String s2("abc987"); を生成し、s2.front() が 'a' を返すことを確認しなさい。
- テストコード、
解答例
- ★char back() const 末尾の1文字を返すメンバ関数を実装しなさい。文字列が空の場合は '\0' を返しなさい。
- String s; を生成し、s.back() が '\0' を返すことを確認しなさい。
- String s2("abc987"); を生成し、s2.back() が '7' を返すことを確認しなさい。
- テストコード、
解答例
- ★char operator[](int ix) const 文字列の ix 番目の文字を返すメンバ関数を実装しなさい。
ix が範囲外の場合は '\0' を返しなさい。
- String s("abc987"); を生成し、s[0] ~ s[5] が "abc987" の各文字を返すことを確認しなさい。
- テストコード、
解答例
- ★const char *c_str() const String オブジェクトが保持する文字列を返すメンバ関数を実装しなさい。
- String s("abc987"); を生成し、s.c_str() がオブジェクトが保持する "abc987" のアドレスを返すことを確認しなさい。
- テストコード、
解答例
- ★★int find(char ch) const
文字列を検索し最初の ch の位置を返すメンバ関数を実装しなさい。文字を含んでいない場合は -1 を返しなさい。
- String s1; に対して s1.find('a') が -1 を返すことを確認しなさい。
- String s2("xyz"); に対して s2.find('a') が -1 を返すことを確認しなさい。
- String s2("xyz"); に対して s2.find('y') が 1 を返すことを確認しなさい。
- String s3("xyzzzy"); に対して s3.find('z') が 2 を返すことを確認しなさい。
- テストコード、
解答例
- ★★int find(const String &str) const
文字列から str を検索し、最初にマッチする位置を返すメンバ関数を実装しなさい。文字列を含んでいない場合は -1 を返しなさい。
※ 文字列検索には strstr() を使用してよいものとする。
- String s1; に対して s1.find(String("a")) が -1 を返すことを確認しなさい。
- String s2("xyzyz"); に対して s2.find(String("a")) が -1 を返すことを確認しなさい。
- String s2("xyzyz"); に対して s2.find(String("yz")) が 1 を返すことを確認しなさい。
- String s3("xyzzzyzaa"); に対して s3.find(String("yza")) が 5 を返すことを確認しなさい。
- テストコード、
解答例
- ★★ostream &operator<<(ostream &, const String &)
出力ストリームに文字列を出力する operator<<() 関数をオーバライドしなさい。
※ メンバ関数ではないので注意
- String s("hello, world."); で文字列オブジェクトを生成し、それを cout << s << "\n"; で画面に表示しなさい。
- 解答例
- ★void clear() 文字列を空にするメンバ関数を実装しなさい。
- String s("abc"); s.clear(); を実行し、s が空文字列になっていることを確認しなさい。
- テストコード、
解答例
- ★★void reserve(int sz) String オブジェクトのキャパシティを指定するメンバ関数を実装しなさい。
- String str; str.reserve(15); を実行し、キャパシティが 15 になっていることを確認しなさい。
- ついで、str.reserve(10); を実行し、キャパシティが 15 のままであることを確認しなさい。
- ついで、str.reserve(20); を実行し、キャパシティが 31 になっていることを確認しなさい。
- テストコード、
解答例
- ★★void resize(int sz, char ch = ' ') String オブジェクトの文字数を指定するメンバ関数を実装しなさい。
文字数が増える場合は、第2引数の文字を追加するようにしなさい。
- String str; str.resize(3); を実行し、size() が 3, str[0] ~ str[2] が ' ' に設定されていることを確認しなさい。
- ついで、str.resize(5, 'a'); を実行し、size() が 5, str[0] ~ str[2] が ' ' のまま、str[3], str[4] が 'a' に設定されていることを確認しなさい。
- テストコード、
解答例
- ★★void pop_back()
文字列最後の文字を削除するメンバ関数を実装しなさい。文字列が空の場合は何も処理を行わないものとする
- String s; s.pop_back(); を実行し、s が空のままで正常であることを確認しなさい。
- String s2("abc"); s2.pop_back(); を実行し、s2 が "ab" になることを確認しなさい。
-
解答例
- ★★void push_back(char ch)
文字列末尾に文字 ch を追加するメンバ関数を実装しなさい。
- String s; s.push_back('a'); を実行し、s が "a" であることを確認しなさい。
- 続けて s.push_back('b'); を実行し、s が "ab" であることを確認しなさい。
- 続けて s.push_back('c'); を実行し、s が "abc" であることを確認しなさい。
-
解答例
- ★★String &operator+=(char ch)
- ★★String &operator+=(const String &str)
- ★★void insert(int ix, char ch)
- ★★void erase(int ix)
- ★★void replace(int ix, int len, const String &str)
- ★★void swap(String &)
- ★★Strign &assign(const String &)
- ★★String &operator=(const String &str)
- ★★String operator+(const String &lhs, const String &rhs)
前:
|上:C/C++ ポインタ入門
|次: