[C#] 35. 文字列クラス、StringとStringBuilderを使い方
こんにちは。明月です。
この投稿はC#で使う文字列クラス、StringとStringBuilderを使い方に関する説明です。
プログラム上で使う原始データタイプは整数と実数タイプが多いですが、文字列はStringタイプで一つです。
正確にはStringタイプは原始データタイプではなく、charの配列タイプになっているクラスタイプです。
つまり、文字はasciiコートになっている整数タイプでそのデータタイプはcharです。
改めて説明するとStringはcharの配列タイプで定義しているし、プログラム内ではStringタイプにデータを格納すると文字列で出力されます。
using System;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// 文字列データタイプ
string data = "Hello world";
// stringをchar[]配列に変換
char[] binary = data.ToCharArray();
// 各の配列の値を
foreach(var b in binary)
{
// コンソール出力に16進数で出力
// byteはunsigned char
Console.Write("0x{0:X2} ", (byte)b);
}
// 改行
Console.WriteLine();
// charの配列を生成
// 0x48 0x65 0x6C 0x6C 0x6F
// Hello
char[] binary1 = new char[]
{
// byteタイプをcharに変換、unsignedの差異なので強制キャストが可能
(char)0x48,(char)0x65,(char)0x6C,(char)0x6C,(char)0x6F
};
// char[]をstringに変換
var data1 = new String(binary1);
// コンソール出力
Console.WriteLine(data1);
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
上の例をみればstringタイプをchar[]配列タイプに変換になり、char[]配列タイプがstringタイプに変換することができることを確認でいます。
link - アスキーコード
ここまで整理すると、Stringはchar[]の配列タイプになっているし、その整数の値はアスキーコードになっていることに説明しました。
ここで詳しく考えることはcharのデータサイズは1byteで2^8になっているし、その値の範囲は0~255(unsigned char)になっています。つまり、サイズが256ですが、世界のすべての文字を256のサイズで表現できません。
日本語だけ見ても漢字が256個以上にありますが、そのため、文字列エンコードのUTF-8があります。
実はこのエンコードタイプに関しても内容が複雑だし、説明する部分が多いですが、今の標準のエンコードタイプはUTF-8で統一になっているし、今はほぼエンコードタイプがUTF-8だと思えば良いです。
このUTF-8のエンコードタイプは可変長さ文字列で最小1byteから4byteまで使って文字列を表現します。つまり、2^32になるので、役42億個の文字を表現できます。
詳細な部分はbyteとエンコード部分で詳細に説明します。
また、Stringの説明に戻って、C#でStringのデータ構成はchar[]配列だし、構造はクラスタイプになっています。
Stringクラスには文字列を扱うための関数があります。
IsNullOrEmpty、IsNullOrWhiteSpace
Stringはクラスなので、nullがあります。なのでnullの値は比較演算子で値の可否を確認できますが、nullではない文字列がないstringもあります。
using System;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// string文字列にnullを宣言
string data = null;
// dataがnullなら
if (data == null)
{
// コンソール出力
Console.WriteLine("Null");
}
// dataにnullではないが、文字列がない。
data = "";
// dataがnullなら
if (data == null)
{
// コンソール出力
Console.WriteLine("Null");
}
// nullか、dataの値がなければtrue
if (string.IsNullOrEmpty(data))
{
// コンソール出力
Console.WriteLine("IsNullOrEmpty");
}
// dataにspaceだけ格納
data = " ";
// dataでnullではないが、文字列にspaceだけあればtrue
if (string.IsNullOrWhiteSpace(data))
{
// コンソール出力
Console.WriteLine("IsNullOrWhiteSpace");
}
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
文字列関係の関数の中でよく使うことがIsNullOrEmpty、IsNullOrWhiteSpace関数です。
IsNullOrEmptyの場合はnullあるいは文字列がない場合はtrueをリターンするし、IsNullOrWhiteSpaceの場合は空白だけあればtrueをリターンする文字確認関数です。
Substring、Trim、Remove、Replace、Split
上の関数は文字列を分離するか取り除く関数です。
using System;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// 文字列データ
string data = " Hello,world ";
// 文字列データから5番目から5個抽出
Console.WriteLine("Substring = " + data.Substring(5, 5));
// 文字列の前、後の空白を取り除く。
Console.WriteLine("Trim = " + data.Trim());
// 文字列データから5番目から5個を空白に変換
Console.WriteLine("Remove = " + data.Remove(5, 5));
// 文字列からoをaに変換
Console.WriteLine("Replace = " + data.Replace('o', 'a'));
// 文字列を,の基準で分割
foreach(var d in data.Split(','))
{
// コンソール出力
Console.WriteLine("Split = " + d);
}
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
Substringは文字列を分離して取得する関数だし、Trimは空白を取り除く、Removeは文字を取り除く、Replaceは文字変換です。
Splitは文字列を分ける関数です。
IndexOf、LastIndexOf
文字列の位置を取得する関数です。
using System;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// 文字列データ
string data = " Hello,world ";
// 文字列前からoの文字がある位置
Console.WriteLine("IndexOf = " + data.IndexOf('o'));
// 文字列の前の10番目からoの文字がある位置
Console.WriteLine("IndexOf = " + data.IndexOf('o', 10));
// 文字列の後からoの文字がある位置
Console.WriteLine("LastIndexOf = " + data.LastIndexOf('o'));
// 文字列の後の10番目からoの文字がある位置
Console.WriteLine("LastIndexOf = " + data.LastIndexOf('o', 10));
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
文字列を位置を計算する関数です。もし、文字列で検索しようと文字が無ければ-1をリターンします。
ToUpper、ToLower
ToUpperとToLowerは英語文字列だけ処理できる関数です。
ToUpperは文字列のすべて文字を大文字で、ToLowerは文字列のすべての文字を小文字に変換する関数です。
using System;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// 文字列データ
string data = "hello WORLD";
// すべての文字を大文字に変換
Console.WriteLine("ToUpper = " + data.ToUpper());
// すべての文字を小文字に変換
Console.WriteLine("ToLower = " + data.ToLower());
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
Compare、Equals
文字列の比較関数です。
using System;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// 文字列データ
string data1 = "hello WORLD";
string data2 = "hello world";
// 文字列比較関数、同じなら0、違うなら-1
Console.WriteLine("Compare = " + string.Compare(data1, data2));
// 文字列比較関数の最後パラメータにboolの値を入れてtrueなら大小文字関係せずに比較falseなら大小文字を区分する。
// 結果は大小文字関係せずに同じなら0、違うなら-1
Console.WriteLine("Compare true = " + string.Compare(data1, data2, true));
// 文字列比較関数、同じならtrue、違うならfalse
Console.WriteLine("Equals = " + string.Equals(data1, data2));
// 文字列比較関数の最後パラメータにStringComparison.OrdinalIgnoreCaseを入れると大小文字関係せずに比較
/ 結果は大小文字関係せずに同じならtrue、違うならfalse
Console.WriteLine("Equals OrdinalIgnoreCase = " + string.Equals(data1, data2, StringComparison.OrdinalIgnoreCase));
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
Concat, Join
文字列を合併する関数です。
using System;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// 文字列データ
string data1 = "hello";
string data2 = "world";
// 文字列を合併
Console.WriteLine("Concat = " + string.Concat(data1, data2));
// 文字列を合併(始めのパラメータは合併する文字列間の区分子)
Console.WriteLine("Concat = " + string.Join(",", data1, data2));
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
Format
String内でフォーマットする機能です。
フォーマットとはintの値をstringに変換する時に、小数点の2桁までの表現などのフォーマットを決定する機能です。
using System;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// 文字フォーマット
Console.WriteLine("{0:yyyy/MM/dd}, {1:0.00}", DateTime.Now, 10.5555d);
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
数字フォーマット | |||
文字タイプ | 説明 | 使い方 | 例 |
---|---|---|---|
c | お金表示 | {0:c} | $ 55,674.74 |
e | 指数表示 | {0:e} | 5.567474e+004 |
f | 固定小数点 | {0:f} | 55674.74 |
g | 標準 | {0:g} | 55674.73789621 |
n | 1000単位でコンマ表示 | {0:n} | 55,674.74 |
フォーマット | |||
0 | 0プレースホルダ | {0:00.00} | 55674.74 |
# | 数字のプレースホルダ | {0:(#).##} | (55674).74 |
. | 小数点 | {0:0.000} | 55674.738 |
, | 千単位の区切り記号 | {0:0,0} | 55,675 |
% | パーセント | {0:0%} | 5567474% |
ここでよく使うStringの関数を整理しました。
String.Formatの場合は以前によく使う方法で、最近は補間式(interpolation)で簡単に使います。
link - [C#] Stringの補間式(interpolation)
上の例でも文字列を合併することでConcatを使うという説明しましたが、実は演算記号でも文字列を合併することができます。
using System;
namespace Example
{
class Program
{
static void Main(string[] args)
{
// 文字列データ
string data1 = "hello";
string data2 = "world";
// 文字列を合併
Console.WriteLine(data1 + " " + data2);
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
でも、この方法の文字列の合併はdata1と空白が一つあるStringが合併する時に他のStringインスタンスが生成されます。
また、そのインスタンスでdata2のデータが合併して、他のStringのインスタンスが生成されます。
つまり、Concatや演算子を使ってStringの文字列合併は合併するたびに新しいインスタンスを生成することです。
参考でこのインスタンスを生成するリソースはずいぶん遅いです。
それでインスタンスを生成せずに、連続的にメモリに付けたらどうでしょう。インスタンスを生成する時間を節約することができるのでプログラム性能が良くなります。
using System;
using System.Text;
using System.Diagnostics;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// 時間を測るクラス
Stopwatch sw = new Stopwatch();
// ルーフ変数
const int loop_count = 100000;
String test = null;
// 測る開始
sw.Start();
// 文字列合併
for (int i = 0; i < loop_count; i++)
{
test += "Data \n";
}
// 測る終了
sw.Stop();
// コンソール出力 - 処理時間
Console.WriteLine("Control time - " + sw.ElapsedMilliseconds);
// 測るクラスリセット
sw.Reset();
//StringBuilderを利用して文字列を付ける。
StringBuilder test2 = new StringBuilder();
// 測る開始
sw.Start();
// 文字列合併
for (int i = 0; i < loop_count; i++)
{
test2.Append("Data \n");
}
// 測る終了
sw.Stop();
// コンソール出力 - 処理時間
Console.WriteLine("Control time - " + sw.ElapsedMilliseconds);
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
結果を見るとStringBuilderから文字列を合併するのが圧倒的に早いです。
文字列のデータを処理することではStringクラスの関数を利用してString値を計算するのが速いですが、文字列を合併するか削除、取り除くの時はStringBuilderを使う方が良いです。
ここまでC#で使う文字列クラス、StringとStringBuilderを使い方に関する説明でした。
ご不明なところや間違いところがあればコメントしてください。
- [C#] 42. ファイルを扱い(IO)とファイルメタデータ(FileInfo)を使い方2021/10/01 20:10:21
- [C#] 41. Taskクラスとasync、awaitを使い方2021/10/01 18:59:14
- [C#] 40. Linqを利用した並列処理(Parallel)を使い方2020/05/13 17:37:13
- [C#] 39. lockキーワードとdeadlock(デッドロック)2019/07/24 00:57:35
- [C#] 38. ThreadPoolの使い方2019/07/23 00:05:40
- [C#] 37. スレッド(Thread)を使い方、Thread.Sleep関数を使い方2019/07/22 23:45:05
- [C#] 36. 拡張メソッドを使い方2019/07/22 23:30:17
- [C#] 35. 文字列クラス、StringとStringBuilderを使い方2019/07/22 23:15:42
- [C#] 34. 最上位クラス(Object クラス)2019/07/20 02:27:23
- [C#] 33. 匿名形式(Anonymous Types)を使い方2019/07/20 02:22:03
- [C#] 32. ジェネリックタイプ(Generic Type)を使い方2019/07/18 22:50:16
- [C#] 31. アトリビュート(Attribute)を使い方2019/07/18 20:22:16
- [C#] 30. Linq関数式を使う方法2019/07/17 23:06:42
- [C#] 29. Linqクエリ式を使い方2019/07/17 20:57:00
- [C#] 28. リスト(List)とディクショナリ(Dictionary)、そしてLinq式を使い方2019/07/16 22:40:03
- check2024/04/10 19:03:53
- [Java] 64.Spring bootとReactを連結する方法(Buildする方法)2022/03/25 21:02:18
- [Javascript] Node.jsをインストールしてReactを使う方法2022/03/23 18:01:34
- [Java] 63. Spring bootでcronスケジューラとComponentアノテーション2022/03/16 18:57:30
- [Java] 62. Spring bootでWeb-Filterを設定する方法(Spring Security)2022/03/15 22:16:37
- [Java] JWT(Json Web Token)を発行、確認する方法2022/03/14 19:12:58
- [Java] 61. Spring bootでRedisデータベースを利用してセッションクラスタリング設定する方法2022/03/01 18:20:52
- [Java] 60. Spring bootでApacheの連結とロードバランシングを設定する方法2022/02/28 18:45:48
- [Java] 59. Spring bootのJPAでEntityManagerを使い方2022/02/25 18:27:48
- [Java] 58. EclipseでSpring bootのJPAを設定する方法2022/02/23 18:11:10
- [Java] 57. EclipseでSpring bootを設定する方法2022/02/22 19:04:49
- [Python] Redisデータベースに接続して使い方2022/02/21 18:23:49
- [Java] Redisデータベースを接続して使い方(Jedisライブラリ)2022/02/16 18:13:17
- [C#] Redisのデータベースを接続して使い方2022/02/15 18:46:09
- [CentOS] Redisデータベースをインストールする方法とコマンドを使い方2022/02/14 18:33:07