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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

1回答

1353閲覧

&str の2文字ずつ &[u8]に変換する方法を教えてください!

KOTTON

総合スコア47

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2021/10/27 12:41

編集2021/10/27 14:50

質問

"49 75 ? EB"b"\x49\x75\x3F\xEB" (&[u8])と同等の物に変換したいのですが方法が分からないため、教えていただきたいです。当たり前なのですが?はasciiにおける3Fなので上記のように変換されているとお考えください。

最終的には変換したものを、&[u8]を引数に取る関数に渡したいです。

書いたコード

rust

1let string = "49 75 ? EB 10 ? ? 24 18 03 00 00 52" 2// まずsplitで空白ごとに区切って、それをmapでbytesに変換してcollectしたかった。 3let string_byte = string.split(" ").map(|b| b.as_bytes()).collect::<&[u8]>();

結果

std::iter::Iterator<Item=&[u8]>は&[u8]に変換できませんというエラーが発生しました。

どうも自分はイテレータから目的の型にcollectする際にいつもエラーに見舞われます。

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

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

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

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

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

toast-uz

2021/10/27 14:01

変換ルールを明文化する(特殊な変換が必要なのは"?"だけでしょうか?)とともに、少なくともそのルールを意識したコード(特殊な変換である"?"はどこで処理していますか?)にしていただけますでしょうか。
tatsuya6502

2021/10/28 01:33 編集

質問者さんへ 変換ルールですが現状で以下のように少なくても2つのルールが混在しているので、それらを意識したコード(ifかmatchで場合分けを行う)を書いてみてください。また3.についても明確にしてください。 1. "49".as_bytes() → &[0x34_u8, 0x39_u8] →(変換A)→ 0x49_u8 2. "?".as_bytes() → &[0x3F_u8] →(変換B)→ 0x3F_u8 3. 他の文字列(2桁の16進数文字列でも"?"でもない) → どうなる?
KOTTON

2021/10/28 01:53 編集

すみません、Split後イテレータを消費できていないので実際内側の処理がどうなってるか一度もprintできず、このような曖昧なコードになってしまっていました。 また、as_bytesに関して勘違いをしていました。&strに対するas_bytesはascii tableに則って16進数に変換するものなんですね...。ではそもそもas_bytesを使うこと自体が間違っているのかもしれません。今考えると、"49".parse()で49i32に変換し、それをそのまま0x49に変換する策を模索するのが正しいアプローチなのかもしれません。 やりたいこととしましては、49、75などの、&str内の空白で区切られた数字をそれぞれ"そのまま"16進数に変換したいです。(例えば0x49、0x75などのように) ?に関してどのように変換するかですが、最終的に変換後の値が一意であり、?であるかどうかが判別できる形であれば、0x3Fに限らずどのように変換しても大丈夫です。 他の文字列はできればキャッチしてエラーを起こすのが好ましいです。
KOTTON

2021/10/28 02:08 編集

コードに関しましては、自力で試行錯誤してみてもしこれより程度の高いコードが出来ましたら更新させていただきます!><
tatsuya6502

2021/10/28 01:54

> そもそもas_bytesを使うこと自体が間違っているのかもしれません。 > > 49、75などの、&str内の空白で区切られた数字をそれぞれ"そのまま"16進数に変換したいです。(例えば0x49、0x75などのように) u8型にfrom_str_radixというメソッドがあるので、それを使うのが楽です。 https://doc.rust-lang.org/stable/std/primitive.u8.html#method.from_str_radix > コードに関しましては、自力で試行錯誤してみてもしこれより程度の高いコードが出来ましたら更新させていただきます!>< うまくいくといいですね。頑張ってください!
KOTTON

2021/10/28 02:13

ありがとうございます!from_str_radixを使えば49を0x49に変換することができました!なので大元の課題も問題なく解決できると思います。&strやi32のクラスメソッドで使えそうなのを探していたのですが、u8のstaticメソッドは完全に失念していました...。ほんとに何でもご存じで尊敬しています。ありがとうございました!
guest

回答1

0

自己解決

解決策

若干冗長になってしまっているのでもしかしたらもっとスマートな方法があるのかもしれないのですが、空のVec<u8>の中に、16進数に変換したものを順次詰めていくような形で求めていたものを実装することができました。

rust

1fn main() { 2 let plane_pattern = "89 0D ? ? ? ? 8B 0D ? ? ? ? 8B F2 8B C1 83 CE 04"; 3 let p_array = plane_pattern.split(" ").collect::<Vec<&str>>(); 4 let mut pattern: Vec<u8> = Vec::new(); 5 for p in p_array { 6 if p == "?" { 7 pattern.push(b'?'); 8 continue; 9 } 10 pattern.push(u8::from_str_radix(p, 16).unwrap()); 11 } 12 let p_slice = pattern.as_slice(); 13 println!("{:X?}", p_slice); 14}

投稿2021/10/28 07:38

KOTTON

総合スコア47

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

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

tatsuya6502

2021/10/28 09:48

> 若干冗長になってしまっているのでもしかしたらもっとスマートな方法があるのかもしれないのですが たしかに、p_array: Vec<&str> は作らなくて済みますね。以下のように書くことができます。 let pattern: Vec<u8> = plane_pattern  .split_whitespace()  .map(|p| {   if p == "?" {    b'?'   } else {    u8::from_str_radix(p, 16).unwrap()   }  })  .collect(); (コメント欄では半角スペースによるインデントが働かないので、全角スペースを使用しています。コードをコピー&ペーストしたあとに、全角スペースを半角スペースで置き換えてください)
KOTTON

2021/10/29 11:09 編集

うおおおお、ほんとですね! イテレータを使うと、goとかだと空の配列に順次追加するような処理を単体で完結できるの凄いです。。 ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問