質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

3回答

12863閲覧

いろんなエスケープ文字を変換して出力結果として表示したい。

paul

総合スコア21

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2018/08/10 02:03

編集2018/08/10 02:43

C#で、エスケープ文字を変換して文字列として可視化したいと考えております。

C#

1string str = "12.5.0\0\0\0\0\0\0\u0002\0\0\u0080"; 2// 便宜上の記述であり、実際は既に変数に値が入っていて直接リテラルは触れません。 3 4Console.WriteLine(str); 5 6// 出力結果 712.5.08 9// 変換処理 10str = str.Replace("\0", "\0"); 11str = str.Replace("\u0002", "\u0002"); 12str = str.Replace("\u0080", "\u0080"); 13Console.WriteLine(str); 14 15// 出力結果 1612.5.0\0\0\0\0\0\0\u0002\0\0\u0080」

上記のように、変換をして出力結果として表示したいと考えていますが、
エスケープ文字全パターンをスマートに変換する方法が思いつきません。
(Console.Write()や、StreamWriter.Write()などを想定しています。)

例えば、"あ\u3042"の場合は "あ\u3042" に変換すれば「\u3042」の部分が出力結果として表示できると考えております。

文字列にエスケープ文字を埋め込むには?[C#/VB/WPF]- @IT atmarkIT
上記の記事を参考にエスケープ文字を確認しました。

ごり押しで、"\u0000" ~ "\uFFFF"を配列に全部入れてループでReplaceなんて考えてやってみましたが
コード自体がとんでもない分量になりIDE自体が重いうえに、一回一回この量のループを走らせるとすさまじく効率の悪い処理でした。
"\U00000000" ~ "\UFFFFFFFF"についてはもう考えたくなくなりました。

正規表現なんかでうまくできないかなぁと思いつつも思いつかない状態です。
良い方法があればお教えいただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2018/08/10 02:05

なにをしようとしてるのか不明ですが
YAmaGNZ

2018/08/10 02:30

例えば、"あ\u3042"の場合はどのように変換するのでしょうか?
paul

2018/08/10 02:33

y_waiwaiさん いろんなエスケープ文字を変換して可視化しようとしております。
paul

2018/08/10 02:34

YAmaGNZさん "あ\u3042"の場合は "あ\\u3042" に変換しようとしております。
y_waiwai

2018/08/10 02:35

その「可視化」がわかりません。¥u3042 というのを表示したいんでしょうか
paul

2018/08/10 02:39

ソースコードにも書きましたが、Console.WriteLine(やStreamWriter.Writeなど)で\u0080など(\u3042含む)を出力結果として表示したいです。
YAmaGNZ

2018/08/10 02:48

私が挙げた例だと、変数には”ああ”と同じ状態になっていると思います。これをどう判断して"あ"とするのか"\u3042"とするのかと聞きたかったのです。
guest

回答3

0

str.Replace("\", "\");

//間違っているけどコメントついてるので残します

-- 修正(エンマークが出るように修正済み)
やりたいことはreplaceでなくて、"制御文字を可視化したい"なので、char.IsControlを使えばいい。
ってことは、Linqが使えるので、例えばこんな感じでどうですかね?

csharp

1var str = "12.5.0\0\0\0\0\0\0\u0002\0\0\u0080"; 2Console.WriteLine(string.Join(string.Empty/*必要に応じて、" "や、", "にすると見易い*/, str.Select(c => char.IsControl(c) ? $@"\U{(int)c:X4}" : c.ToString()))); 3//-> 12.5.0\U0000\U0000\U0000\U0000\U0000\U0000\U0002\U0000\U0000\U0080

-- 追記
ベストアンサ決まってますけど、まあこんな感じのほうがC#っぽいはず

csharp

1static void Main() 2{ 3 var str = "12.5.0\0\0\0\0\0\0\u0002\0\0\u0080\r\n\tあa"; 4 Console.WriteLine(string.Join(string.Empty, str.Select(Converter))); 5 // -> 12.5.0\0\0\0\0\0\0\U0002\0\0\U0080\r\n\tあa 6} 7 8static string Converter(char c) 9{ 10 if (!char.IsControl(c)) // char.IsControlを使えば、"あ"は回避できるはず 11 { 12 return c.ToString(); 13 } 14 var specified = new Dictionary<char, string> { { '\0', "\0" }, { '\r', "\r" }, { '\n', "\n" }, { '\t', "\t" }, }; 15 return specified.Keys.Contains(c) ? specified[c] : $@"\U{(int)c:X4}"; 16}

投稿2018/08/10 02:06

編集2018/08/10 03:30
papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

paul

2018/08/10 02:10

ご回答ありがとうございます。 「\0」などの「\」は便宜上の表現であり「\0」で1文字であるため、その方法だと正しく変換できないように思われます。
papinianus

2018/08/10 02:14 編集

そうかそりゃそうですね。考えて修正します
papinianus

2018/08/10 02:55

$"U{(int)c:X4}"のところは$@"\U{(int)c:X2}"とか適宜出したいように修正してください
papinianus

2018/08/10 03:00

\0が質問のやりたい形式にあってないですが、そこは目をつぶっていただくか、三項演算子を重ねるか、関数作るか(\uではじまらない制御文字の代表例として、\rとか\nとかもありますし、もともと画一的に処理したかったみたいなので、目をつぶっていただければと)
paul

2018/08/10 03:12

ご回答ありがとうございます。 重ね言葉足らずで申し訳ございません。 変数に"12.5.0\0\0\0\0\0\0\u0002\0\0\u0080"として文字列が入っていた場合、 これをそのまま「12.5.0\0\0\0\0\0\0\u0002\0\0\u0080」と表示したい ということでした。 わかりにくくて申し訳ございません。
papinianus

2018/08/10 03:16 編集

確認ですが「\」が必要とおっしゃっています? それと改行文字「\r\n」やタブ文字「\t」はどう出て欲しいとお考えですか?
paul

2018/08/10 03:19

「\r\n」や「\t」はそのまま「\r\n」や「\t」という文字列で出てほしいですね
papinianus

2018/08/10 03:36

'あ'は、char.IsControl('あ')がfalseになるので識別できるはず。「\0」を「\u0000」となるよりも、「あ」を\u3042とするほうが、許容できるというのが、"エスケープ文字を変換して文字列として可視化したい"という目的に合致しているというのが信じられないです。y_waiwaiさんのおっしゃるように何がしたいか不明です。 また、'あ'と'\u3042'はcharとしては同じもので、後者を"エスケープ文字"だと思っておられるとしたら、@ITの記事を再度お読みになることをおすすめします。
guest

0

C#

1string res=""; 2foreach(var a as str){ 3 res+= "\u"+((uint)a).ToString("X4"); 4} 5Console.WriteLine(res);

こういうことかな?

投稿2018/08/10 02:54

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

paul

2018/08/10 03:08

ご回答ありがとうございます。 全ての文字を\uxxxxで表現するプログラムを書いてくださったんですね。 重ね言葉足らず、理解不足で申し訳ございません。 変数に"12.5.0\0\0\0\0\0\0\u0002\0\0\u0080"として文字列が入っていた場合、 これをそのまま「12.5.0\0\0\0\0\0\0\u0002\0\0\u0080」と表示したい ということでした。 わかりにくくて申し訳ございません。
y_waiwai

2018/08/10 03:10

なら、アルファベットやコントロールコードを判定してそういうふうに出力すればいい。
y_waiwai

2018/08/10 03:11

わかりにくいというよりも、質問者自身仕様がはっきりわかっていないってことでは
paul

2018/08/10 03:17

回答いただいてありがたいですが、いちいち言い回しが癇に障るので、控えていただきたいです。 言い方ってあると思います。 あたりまえですが、わからなくて質問してるんです。
y_waiwai

2018/08/10 03:20

なにが癪に障るのかわからんけど、 とにかく仕様をはっきりさせないと答えようがないですぜ #最初からそういってんだけど。。
otn

2018/08/10 04:20

> あたりまえですが、わからなくて質問してるんです。 解決方法が分からないのと、何がしたいのか分からないというのは違います。
otn

2018/08/10 04:23

ああ、「何がしたいのか分からない状態で質問するな」という意味じゃないです。 何がしたいのかよく分からない時は、自分の抱えているそもそもの問題を書くと良いです。
guest

0

ベストアンサー

どういうこと?ASCII文字以外はエスケープで表示したいってこと?
コンパイル後は"あ"と"\u3042"は同じ数値になるので出しわけるのは不可能です。
それがわからない場合は文字列がどういった扱いかを一回勉強し直してください。

C#

1var escapes = "\0\a\b\f\n\r\t\v"; 2var replaced = new[] { "\0", "\a", "\b", "\f", "\n", "\r", "\t", "\v" }; 3 4var sb = new StringBuilder(); 5 6for(var i=0; i<str.Length; i++) 7{ 8 var c = str[i]; 9 var p = escapes.IndexOf(c); 10 11 if (p != -1) 12 { 13 sb.Append(replaced[p]); 14 } 15 else if (0x20 <= c && c <= 0x7E) 16 { 17 sb.Append(c); 18 } 19 else if (i < str.Length - 1 && Char.IsHighSurrogate(c) && Char.IsLowSurrogate(str[i + 1])) 20 { 21 var u = Char.ConvertToUtf32(c, str[i + 1]); 22 sb.Append($"\U{u:X8}"); 23 i += 1; 24 } 25 else 26 { 27 sb.Append($"\u{(uint)c:X4}"); 28 } 29} 30Console.WriteLine(sb);

投稿2018/08/10 02:46

toki_td

総合スコア2850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

paul

2018/08/10 02:59

ご回答ありがとうございます。   string str = "あ\u3042";    str.Replace("\u3042","\u3042"); を実行して、自分の勘違いに理解しました。 また、「あ」と「\u3042」は同じ意味であり、分けることは不可能なことも理解しました。 そしてソースコードのご提示までありがとうございます。 「あ」などもすべて\u3042として表示することでも目的は達成できそうです。
paul

2018/08/10 03:06

もしかしたら、この回答にも勘違いがありそうです。 >「あ」などもすべて\u3042として表示することでも目的は達成できそうです。 この言い方だと、「1」なども「\u0031」にするような言い方ですよね。 語弊を生みそうですので、ここの部分、訂正いたします。 toki_tdさんのプログラムで目的が達成できそうです。 言葉足らずなのにくみ取っていただいて、感謝します。 また、理解不足な部分のご指摘をわかりやすくしていただきありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問