C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[9]: StringBuilder について


(過去ログ 176 を表示中)

[トピック内 13 記事 (1 - 13 表示)]  << 0 >>

■101160 / inTopicNo.1)  StringBuilder について
  
□投稿者/ 星は昴 (1回)-(2023/01/13(Fri) 15:36:28)

分類:[C#] 

//半角空白削除 その1
private string DelHalfSpace(string str)
{
    char[] Res = new char[str.Length + 1];
    int k = 0;
    foreach (char c in str)
    {
        if (c != ' ')
            Res[k++] = c;
    }
    Res[k] = '\0';
    string Result = new string(Res); //char型配列⇒string
    return Result;
}

//半角空白削除 その2
private string DelHalfSpace2(string str)
{
    char[] Res = new char[str.Length + 1];
    int i = 0;
    int k = 0;
    while (i < str.Length)
    {
        if (str[i] != ' ')
            Res[k++] = str[i];
        i++;
    }
    Res[k] = '\0';
    string Result = new string(Res);
    return Result;
}

//StringBuilder の実験
private void BtnTBoxAppend_Click(object sender, EventArgs e)
{
    string mdstr = "注意!   C#の string の末尾には終端文字 '\\0' は存在しない。";
    var sb = new StringBuilder();
    sb.Append("\r\n"+mdstr + "元の文字列\r\n");
    sb.Append(DelHalfSpace(mdstr) + "DelHalfSpace\r\n\r\n");
    sb.Append(DelHalfSpace2(mdstr) + "DelHalfSpace2");

    textBoxOut.Text = sb.ToString();
}

結果
---------------------------
注意!   C#の string の末尾には終端文字 '\0' は存在しない。元の文字列
注意!C#のstringの末尾には終端文字'\0'は存在しない。
---------------------------
元の文字列 mdstr は正常に表示される。
DelHalfSpace の削除結果は末尾の DelHalfSpace が表示されず、\r\n\r\n も出力されない。
DelHalfSpace2 の削除結果はまったく表示されない。
DelHalfSpace と DelHalfSpace2 の実行順を入れ替えると今度は DelHalfSpace2 の結果だけが表示される。

 なぜこんな症状が起きるのでしょうか? 2つの関数に渡す文字列 mdstr は変化しないと思うのですけど。

引用返信 編集キー/
■101161 / inTopicNo.2)  Re[1]: StringBuilder について
□投稿者/ 伝説のカレー (60回)-(2023/01/13(Fri) 15:51:06)
ヌル文字のあとの文字列が表示されないと仮定すると事象に説明はつくような気がします
ヌル文字を入れるのをやめて配列の長さを縮小する処理を入れるのが良い気がします
引用返信 編集キー/
■101162 / inTopicNo.3)  Re[2]: StringBuilder について
□投稿者/ 伝説のカレー (61回)-(2023/01/13(Fri) 15:53:51)
長さを指定できるコンストラクタがありました、これでも良いです
String(Char[], Int32, Int32)

引用返信 編集キー/
■101163 / inTopicNo.4)  Re[3]: StringBuilder について
□投稿者/ Hongliang (1265回)-(2023/01/13(Fri) 16:08:20)
伝説のカレーさんが仰っていますが、WinFormsのTexBoxは\0以降を表示できません。
一方string型は\0を含むことができます。
// \0を含むことができるのは、"a\0b".Lengthが3になることなどで確認できます。
DelHalfSpace/DelHalfSpace2で定義しているchar[]の後ろの方はnew以後触れられず0が格納されたままなので、new stringしたときに文字列に\0が含まれることになります。

空白を除くのであれば
・単純に x = x.Replace(" ", "") する
・char[]を直接使うのではなくStringBuilderにAppend(char)していく
と言った方法が考えられます。
引用返信 編集キー/
■101164 / inTopicNo.5)  Re[1]: StringBuilder について
□投稿者/ 魔界の仮面弁士 (3534回)-(2023/01/13(Fri) 16:54:49)
No101160 (星は昴 さん) に返信
> string mdstr = "注意! C#の string の末尾には終端文字 '\\0' は存在しない。";

下記は true を返しますね。結果に差は無いようです。

bool b = DelHalfSpace(mdstr) == DelHalfSpace2(mdstr);


>  なぜこんな症状が起きるのでしょうか?
TextBox (というか、Win32 の EDITBOX) は、
`\0` 以降の文字を切り捨てる仕様だからです。

string s = "abc\0xyz";
listBox1.Items.Add("s.Length=" + s.Length);
textBox1.Text = s;
listBox1.Items.Add("TextLength=" + textBox1.TextLength);
listBox1.Items.Add("Text.Length=" + textBox1.Text.Length);
引用返信 編集キー/
■101165 / inTopicNo.6)  Re[4]: StringBuilder について
□投稿者/ 星は昴 (2回)-(2023/01/13(Fri) 17:01:57)
 皆さん回答ありがとうございました。知識不足を痛感しております。

> char[]を直接使うのではなくStringBuilderにAppend(char)していく

がお手軽そうなので以下のようにコーディングしましたが、その2は単独で使っても暴走します。なぜでしょうか。

//半角空白削除 その1 こっちはOK
private string DelHalfSpace(string str)
{
var sb = new StringBuilder();
foreach (char c in str) {
if (c != ' ')
sb.Append(c);
}
return sb.ToString();
}

//半角空白削除 その2 こっちは暴走します。
private string DelHalfSpace2(string str)
{
var sb = new StringBuilder();
int i = 0;
while (i < str.Length) {
if (str[i] != ' ')
sb.Append(str[i]);
}
return sb.ToString();
}

引用返信 編集キー/
■101166 / inTopicNo.7)  Re[2]: StringBuilder について
□投稿者/ 魔界の仮面弁士 (3535回)-(2023/01/13(Fri) 17:09:02)
No101164 (魔界の仮面弁士) に追記
>> なぜこんな症状が起きるのでしょうか?
> TextBox (というか、Win32 の EDITBOX) は、
> `\0` 以降の文字を切り捨てる仕様だからです。

WPF の TextBox であれば '\0' を含められます。
画面上はゼロ幅文字として扱われていますね。

private void Button_Click(object sender, RoutedEventArgs e)
{
 string s = "abc\0xyz";
 textBlock1.Text = "s.Length=" + s.Length + "\r\n";
 textBox1.Text = s;
 textBlock1.Text += "Text.Length=" + textBox1.Text.Length ;
}


WFP の TextBox に表示された内容をクリップボードにコピーしたところ
クリップボード内には \0 を含む文字列が保持されていることを確認できました。

CF_TEXT(1) =>
 61 62 63 00 78 79 7a 00

CF_UNICODETEXT(13) =>
 61 00 62 00 63 00 00 00 78 00 79 00 7a 00 00 00

"System.String" =>
 96 a7 9e fd 13 3b 70 43 a6 79 56 10 6b b2 88 fb
 00 01 00 00 00 ff ff ff ff 01 00 00 00 00 00 00
 00 06 01 00 00 00 07 61 62 63 00 78 79 7a 0b

CF_OEMTEXT(7) =>
 61 62 63 00 78 79 7a 00


ただしクリップボードから取り出す際に、文字列の '\0' 以降を
取得できるソフトウェアは殆ど無いと思います。
引用返信 編集キー/
■101167 / inTopicNo.8)  Re[5]: StringBuilder について
□投稿者/ 魔界の仮面弁士 (3536回)-(2023/01/13(Fri) 17:14:58)
No101165 (星は昴 さん) に返信
> //半角空白削除 その1 こっちはOK

Hongliang さん案の Replace で十分な気が…。

private string DelHalfSpace0(string str) => str?.Replace(" ", "");

private string DelHalfSpace1(string str) => new string(str.Where(c => c != ' ').ToArray());


> //半角空白削除 その2 こっちは暴走します。
変数 i を 0 固定のまま、変化させていないからでは。
引用返信 編集キー/
■101168 / inTopicNo.9)  Re[5]: StringBuilder について
□投稿者/ 星は昴 (3回)-(2023/01/13(Fri) 17:15:13)
> //半角空白削除 その2 こっちは暴走します。
i++;
を忘れていました。
いろいろありがとうございました。
解決済み
引用返信 編集キー/
■101169 / inTopicNo.10)  Re[6]: StringBuilder について
□投稿者/ 星は昴 (4回)-(2023/01/13(Fri) 17:23:50)
No101167 (魔界の仮面弁士 さん) に返信
>
> Hongliang さん案の Replace で十分な気が…。
 ま、そうなのですけど。

 Replace で全角空白も簡単に""に置き換えられますか?
引用返信 編集キー/
■101170 / inTopicNo.11)  Re[7]: StringBuilder について
□投稿者/ 魔界の仮面弁士 (3537回)-(2023/01/13(Fri) 17:28:14)
No101169 (星は昴 さん) に返信
>  Replace で全角空白も簡単に""に置き換えられますか?

Regex.Replace(str, " | ", "")
引用返信 編集キー/
■101171 / inTopicNo.12)  Re[8]: StringBuilder について
□投稿者/ 魔界の仮面弁士 (3538回)-(2023/01/13(Fri) 18:11:34)
No101170 (魔界の仮面弁士) に追記
>> Replace で全角空白も簡単に""に置き換えられますか?
> Regex.Replace(str, " | ", "")

あるいは単純につなげてみる手も。
 return str?.Replace(" ", "")?.Replace(" ", "");


過去ログに、Replace で置換する方法と
ループして StringBulder で Append していく方法の
速度差を検証されているものがありました。参考までに。
http://bbs.wankuma.com/index.cgi?mode=al2&namber=89879&KLOG=155
引用返信 編集キー/
■101172 / inTopicNo.13)  Re[9]: StringBuilder について
□投稿者/ 星は昴 (5回)-(2023/01/13(Fri) 18:32:04)
No101171 (魔界の仮面弁士 さん) に返信
 いろいろ丁寧な回答ありがとうございました。
 全角文字の処理についていろいろわからないところがあるので、そのときはまたよろしくお願いいたします。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -