今日の課題です。
・文字列を一定のバイト数に分割する
・文字列に一定のバイト数毎に文字列を挿入する。
StringDivider
文字列分割処理クラス
文字列を1文字ずつ抽出してバイト数を検知する。
検知したらIStringDivideProcessを呼び出して、任意の処理を行う。
IStringDivideProcessでのコールバックのような呼び出しではなく、StringDividerを継承してProcessメソッドをオーバーライドするような設計もありだけどね。
というか、そっちが普通なんだろうけど、あくまで課題ということでw
IStringDivideProcess
バイト数毎に行う処理のインターフェース
StringDivideCreateList
バイト数で分割した文字列のリストを作成するクラス
IStringDivideProcessの実装。
StringDivideInsertText
バイト数毎に文字列を挿入するクラス
IStringDivideProcessを実装。
ソース
プロパティのsetを省略したり、privateを付けて、読み取り専用みたいなこととか。
using System; namespace TrialProject.Jp.Saku { /// <summary> /// 文字列分割処理クラス<br /> /// </summary> public class StringDivider { [STAThread] public static void Main() { string text = "1234567890abcefghigjklmnopqrstuvwxyz"; // 分割した文字列をListにする System.Diagnostics.Debug.WriteLine("【分割した文字列をListにする】"); StringDivideCreateList list = new StringDivideCreateList(); StringDivider divList = new StringDivider(text, 5, list); divList.Divide(); foreach (string str in list.List) { // 分割された文字列のリストを出力 System.Diagnostics.Debug.WriteLine(str + "[" + str.Length + "]"); } // 分割した文字列に文字列を挿入する System.Diagnostics.Debug.WriteLine("【分割した文字列に<hoge>を挿入する】"); StringDivideInsertText ins = new StringDivideInsertText("<hoge>"); StringDivider divIns = new StringDivider(text, 3, ins); divIns.Divide(); // 挿入された文字列を出力 System.Diagnostics.Debug.WriteLine(ins.ResultText.ToString()); } /// <summary> /// バイト列変換<br /> /// </summary> private System.Text.Encoding SJIS_ENC = System.Text.Encoding.GetEncoding(932); /// <summary> /// 分割する文字列<br /> /// </summary> private string _text; public string Text { get { return this._text; } private set { this._text = value; } } /// <summary> /// 分割するバイト数<br /> /// </summary> private int _length; public int Length { get { return this._length; } private set { this._length = value; } } /// <summary> /// 文字列分割処理<br /> /// </summary> private IStringDivideProcess _divideProcess; public IStringDivideProcess DivideProcess { get { return this._divideProcess; } private set { this._divideProcess = value; } } /// <summary> /// 分割中の文字列<br /> /// </summary> private System.Text.StringBuilder _divideText = new System.Text.StringBuilder(); public System.Text.StringBuilder DivideText { get { return this._divideText; } } /// <summary> /// コンストラクタ<br /> /// </summary> /// <param name="text"> /// 分割する文字列<br /> /// </param> /// <param name="length"> /// 分割するバイト数<br /> /// </param> /// <param name="proc"> /// 文字列分割処理<br /> /// </param> public StringDivider(string text, int length, IStringDivideProcess proc) { this.Text = text; this.Length = length; this.DivideProcess = proc; this.DivideText.Clear(); } /// <summary> /// 文字列を分割する<br /> /// </summary> public void Divide() { // 1文字づつバイト数を検査 int i = 0; while(i < this.Text.Length) { // 1文字ずつ抽出 string c = this.Text.Substring(i, 1); // バイト数に一致するか? if (SJIS_ENC.GetByteCount(this.DivideText + c) == this.Length) { // 抽出した文字を追加 this.DivideText.Append(c); // 分割処理 this.DivideProcess.Process(this); // 次の処理用にクリア this.DivideText.Clear(); } // バイト数を超えるか? else if (SJIS_ENC.GetByteCount(this.DivideText + c) > this.Length) { // 分割処理 this.DivideProcess.Process(this); // 次の処理用にクリア this.DivideText.Clear(); // 抽出した文字を追加 this.DivideText.Append(c); } // バイト数未満 else { // 抽出した文字を追加 this.DivideText.Append(c); } // 次の文字の処理 i++; } // 残りの文字列を処理 if (this.DivideText.Length > 0) { this.DivideProcess.Process(this); } } } /// <summary> /// 文字列分割処理インターフェース<br /> /// </summary> public interface IStringDivideProcess { /// <summary> /// 文字列を分割する。<br /> /// </summary> /// <param name="divider"> /// 文字列分割処理オブジェクト<br /> /// </param> void Process(StringDivider divider); } /// <summary> /// 文字列分割処理(分割文字列のリストを作成)<br /> /// </summary> public class StringDivideCreateList : IStringDivideProcess { /// <summary> /// 分割した文字列を格納したリスト<br /> /// </summary> private System.Collections.Generic.IList<string> _list = new System.Collections.Generic.List<string>(); public System.Collections.Generic.IList<string> List { get { return this._list; } } /// <summary> /// 文字列を分割する。<br /> /// </summary> /// <param name="divider"> /// 文字列分割処理オブジェクト<br /> /// </param> public void Process(StringDivider divider) { this.List.Add(divider.DivideText.ToString()); } } /// <summary> /// 文字列分割処理(文字列を挿入)<br /> /// </summary> public class StringDivideInsertText : IStringDivideProcess { /// <summary> /// 挿入する文字列<br /> /// </summary> private string _InsertText; public string InsertText { get { return this._InsertText; } private set { this._InsertText = value; } } /// <summary> /// 文字を挿入した文字列<br /> /// </summary> private System.Text.StringBuilder _ResultText = new System.Text.StringBuilder(); public System.Text.StringBuilder ResultText { get { return this._ResultText; } } /// <summary> /// コンストラクタ<br /> /// </summary> /// <param name="insertText"> /// 挿入する文字列<br /> /// </param> public StringDivideInsertText(string insertText) { this.InsertText = insertText; } /// <summary> /// 文字列を分割する。<br /> /// </summary> /// <param name="divider"> /// 文字列分割処理オブジェクト<br /> /// </param> public void Process(StringDivider divider) { // 分割された文字列の前に挿入(2つ目以降) if (this.ResultText.Length > 0) { this.ResultText.Append(this.InsertText); } // 分割された文字列を結合 this.ResultText.Append(divider.DivideText.ToString()); } } }
処理結果(textの10文字目の0のみ全角文字)
【分割した文字列をListにする】 12345[5] 6789[4] 0abc[4] efghi[5] gjklm[5] nopqr[5] stuvw[5] xyz[3] 【分割した文字列に<hoge>を挿入する】 123<hoge>456<hoge>789<hoge>0a<hoge>bce<hoge>fgh<hoge>igj<hoge>klm<hoge>nop<hoge>qrs<hoge>tuv<hoge>wxy<hoge>z