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

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

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

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

Q&A

解決済

3回答

34273閲覧

インデックスの範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません,とでてしまいます

ncncup

総合スコア13

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

0グッド

0クリップ

投稿2016/07/27 00:57

こんにちは。ビジュアルスタジオでC#を使ってWindows Formsアプリを作成しています。質問なんですが、
シリアル通信で豆電球を点灯させたり、消灯させたりしています。
フォームには 送信テキストボックスと受信テキストボックス、送信ボタンとチェックボックス16個あります。
豆電球が16個ついている装置をUSBとつないでます。
チェックボックス1をチェックすると豆電球1が点灯します。チェックを外すと消灯します。

装置とアプリの関係は
・アプリでコマンド値(16進数)をテキストぼっくすに入力して送信ボタンを押すとシリアル通信でそのコマンドを送出する
・コマンド値は豆電球のオンオフをビットパターンで表していて、0x0001=豆電球1~0x8000=豆電球16に対応している。
・コマンド送信を実行すると、コマンド値でビットが1になっている豆電球について、アプリ側ではチェックボックスがオンになり装置側では豆電球が点灯する(ビットが0ならチェックがオフ、豆電球が消灯)

やりたいことは
デバックしてテキストボックスに16進数"mh,ffff"と入力して送信すると豆電球は全部点灯して、フォームのチェックボックスもチェックされた状態になります。
一個の豆電球を点灯させたいときは"aa,1"と送信すれば、豆電球1が点灯しチェックボックス1が自動チェックされます。
そして "?MH" と入力して送信すると
"インデックスの範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。"
パラメータ名:startIndex
と出てきてしまいます。

なんか対処法はないでしょうか?ご教授お願いいたします。

コードは次のようになります。

try
{
//! シリアルポートからテキストを送信する.
serialPort1.Write(data +"\n");

int startIndex = data.IndexOf(",") + 1; // 開始位置","の次の文字
string tValue = data.Substring(startIndex);

//入力された16進数文字列を数値に変換
int value = Convert.ToInt32(tValue, 16);

for (int i = 1; i <= 16; i++)
{
//画面上の処理対象チェックボックスコントロールを特定
Control[] cs = this.Controls.Find("CheckBox" + i.ToString(), true);
//チェック対象ビットに1が立っていればチェックオン、0ならチェックオフ
((CheckBox)cs[0]).Checked = ((value & (1 << (i - 1))) > 0);
}

}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

}

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

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

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

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

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

guest

回答3

0

こんにちは。
直接の解決法ではないですが、回答します。

この質問の場合、コードの修正以前に、まず「そのテキストボックスに"何を"入力するのか?」という点の仕様を明確にする必要があります。
質問文には、

アプリでコマンド値(16進数)をテキストぼっくすに入力して送信ボタンを押す

とありますが、直後にテキストボックスに入力している"mh,"はどう見ても16進数の値ではないですよね。

まずは、「テキストボックスに入力する可能性のあるデータ」を片っ端から羅列してみてください。
そして、「このプログラムに処理させたいデータ」がどんな形のものなのかを明確にしてください。
それが全て完了してから、ようやくコードを「処理してもいいデータかどうかを判定して、正しいデータだけを処理する」ように変更できるようになります。

投稿2016/07/27 01:33

tamoto

総合スコア4228

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

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

ncncup

2016/07/27 01:56

なるほどです!細かい説明ありがとうございます。 文字は文字で送信すればいいんですよね? 誠に申し訳ないんですがどのように書けば良いか教えていただけませんか? よろしくお願いいたします。
ozwk

2016/07/27 02:00

回答読んでます?
tamoto

2016/07/27 02:29

んん……w ちょっと…… えっと、現状をもっと簡単に一言で言うと、「正しい回答をするのに必要な情報が足りてない」って状況なので、まずは回答に書いた通りの「必要な情報」を集めて下さい。。
ncncup

2016/07/27 02:58

ozwkさん 毎回返信、ご指摘ありがとうございます。 まだ初心者で理解力が足りなかったようです。 またよろしくお願いいたします。 tomatoさん 返信ありがとうございます。 情報が足りなかったようですね。必要な情報を集めてきます。 ありがとうございました。
guest

0

ベストアンサー

テキストBOXに入れた文字をそのまま処理しようとしていますが、
"?MH"って想定している送信する文字列なんでしょうか?
想定していないものをシリアル通信で送ること自体がまずいと思いますので、
想定していない文字列の場合は、
処理を抜けるように、IF文判定するとかはいかがでしょう。

投稿2016/07/27 03:54

KIYOSHI

総合スコア268

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

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

ncncup

2016/07/27 04:26

毎回こうやって返信してもらえて本当にうれしいです。本当にありがとうございます。 ?MHは想定している文字です。?MHは無事に送信できました。 ms,1やmr,1と送信した場合は16進数変換処理を抜けるようにしたいです。 If文でいろいろ調べているんですけどなかなかできません。 どのように書けばよいか教えてくださいませんか? ほんとにすみません。よろしくお願いいたします。
ncncup

2016/07/27 04:28

このコードだと"ms,1"と送っても16進数に変換されてしまいます。 public void sndTextBox_KeyDown(Object sender, KeyEventArgs e) { // エンターを押したらテキストが送信される if (e.KeyCode == Keys.Enter) { switch (this.sndTextBox.Text.Trim()) { case "MS,1": case "Ms,1": case "mS,1": case "ms,1": this.checkBox1.Checked = true; break; case "MR,1": case "Mr,1": case "mR,1": case "mr,1": this.checkBox1.Checked = false; break; case "MS,2": case "Ms,2": case "mS,2": case "ms,2": this.checkBox2.Checked = true; break; case "MR,2": case "Mr,2": case "mR,2": case "mr,2": this.checkBox2.Checked = false; break; } //! シリアルポートをオープンしていない場合、処理を行わない if (serialPort1.IsOpen == false) { return; } //! テキストボックスから、送信するテキストを取り出す String data = sndTextBox.Text; //! 送信するテキストがない場合、データ送信は行わない if (string.IsNullOrEmpty(data) == true) { return; } try { //! シリアルポートからテキストを送信する. serialPort1.Write(data + "\n"); int startIndex = data.IndexOf(","); if (startIndex > -1) { startIndex = startIndex + 1; // 開始位置","の次の文字 string tValue = data.Substring(startIndex); int value = Convert.ToInt32(tValue, 16); for (int i = 1; i <= 16; i++) { //画面上の処理対象チェックボックスコントロールを特定 Control[] cs = this.Controls.Find("CheckBox" + i.ToString(), true); //チェック対象ビットに1が立っていればチェックオン、0ならチェックオフ ((CheckBox)cs[0]).Checked = ((value & (1 << (i - 1))) > 0); } } } catch (Exception ex) { MessageBox.Show(ex.Message); } } }
KIYOSHI

2016/07/27 04:38

","以降の"1"は16進数としても有効なのですが変換しないようにしたいということですか? それとも、"MS,1"はCheckBoxの操作のみさせたいということですか?
ncncup

2016/07/27 04:41

ありがとうございます。 ms、1はcheckBoxの操作のみにしたいです。
KIYOSHI

2016/07/27 04:47

Swich文で、 CheckBox.Checkedを設定している後に、 return; で処理ぬけてはいかがでしょうか?
ncncup

2016/07/27 05:09

ありがとうございます。 いろいろ試しているのですが、エラーが出てきちゃいます。 どのように入れればいいか教えていただけませんか? 聞いてばかりで本当にすみません。よろしくお願いいたします。
KIYOSHI

2016/07/27 05:15

エラーとはどこで発生していますか? なんというエラーでしょうか? ソースがあちこちに書かれているので、どれでどのようなエラーが出ているかわかりませんよ。 ここに書かれたソースだと、 ”?MH"を送ってもエラーにはならないと思いますよ。 if (startIndex > -1) {   :処理略 } 処理には文字に","がないと入りませんので。
guest

0

必ずカンマがあるという前提だからスね。

C#

1int startIndex = data.IndexOf(",") + 1; // 開始位置","の次の文字 2string tValue = data.Substring(startIndex);

カンマの有無を判定して処理を分ければいいと思います。
--- 追加 ---

例えばこんな感じでどうスかね。

C#

1string tValue = data; 2int startIndex = data.IndexOf(","); 3if (startIndex > -1) { 4 startIndex = startIndex + 1; // 開始位置","の次の文字 5 tValue = data.Substring(startIndex); 6}

--- 追加2 ---

画面をいじらないってんならこんな感じで

C#

1try { 2 //! シリアルポートからテキストを送信する. 3 serialPort1.Write(data +"\n"); 4 int startIndex = data.IndexOf(","); 5 if (startIndex > -1) { 6 startIndex = startIndex + 1; // 開始位置","の次の文字 7 string tValue = data.Substring(startIndex); 8 int value = Convert.ToInt32(tValue, 16); 9 for (int i = 1; i <= 16; i++) { 10 //画面上の処理対象チェックボックスコントロールを特定 11 Control[] cs = this.Controls.Find("CheckBox" + i.ToString(), true); 12 //チェック対象ビットに1が立っていればチェックオン、0ならチェックオフ 13 ((CheckBox)cs[0]).Checked = ((value & (1 << (i - 1))) > 0); 14 } 15 } 16} catch (Exception ex) { 17 MessageBox.Show(ex.Message); 18}

投稿2016/07/27 01:01

編集2016/07/27 02:13
takasima20

総合スコア7460

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

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

ncncup

2016/07/27 01:07

回答ありがとうございます。ほんとに助かります。 申し訳ないんですけど、そのカンマの有無を判定する処理を どのように書けばいいか、教えてくださいませんか? すみません。よろしくお願いいたします。
ncncup

2016/07/27 01:48

ありがとうございます。 そのコードで試させてもらいましたが、 "認識可能な数値が見つかりませんでした" とでてきちゃいます。もしかしたら"?MH"も16進数に変換されてしまうからでしょうか? 質問ばかりで申し訳ないのですが、なんか対処法があれば教えていただけませんか?
takasima20

2016/07/27 01:53

そうスね。 で、"?mh"を受け取ったらどんなことをさせるのか? それが分からないとなんとも…
ncncup

2016/07/27 01:59

返信ありがとうございます。 ?mh 送信とは点灯している豆電球の状態を受信ボックスに表してくれます。 文字は文字として送れるようにしたいんですけどできますか? よろしくお願いいたします。
ncncup

2016/07/27 02:03

追記です。すみません。 テキストボックスでms.1 mr,1 ?mhは文字として送って、 mh.(16進数)は16進数で送るっていう風にしたいです。 このようにはできますでしょうか?よろしくお願いいたします。
takasima20

2016/07/27 02:19

いや、送るのは常に入力のまま送るようにコーディングされてますよね。 今回問題になったのは送ったものから画面(チェックボックス)を 変化させようってとこなんで「送る」とは関係ないです。 ということを理解してコーディングしてますか?
ncncup

2016/07/27 02:32

本当に毎回回答をありがとうございます。本当に本当に感謝しています。 ?mhも正常に動きました。 はい。もともとはms,1と送ったら、豆電球1は点灯し、チェックボックスもチェックされて、mr,1と送信したら電気は消灯され、チェックボックスも外れます。でも、上記のようなコードを足したらms,1やmr,1がうまく動かなくなってしまいました。 上記のようなコードを書いていただいてほんとに感謝しています。よろしくお願いいたします。
ncncup

2016/07/27 02:36

このようなコードになっています。 public void sndTextBox_KeyDown(Object sender, KeyEventArgs e) { // エンターを押したらテキストが送信される if (e.KeyCode == Keys.Enter) { switch (this.sndTextBox.Text.Trim()) { case "MS,1": case "Ms,1": case "mS,1": case "ms,1": this.checkBox1.Checked = true; break; case "MR,1": case "Mr,1": case "mR,1": case "mr,1": this.checkBox1.Checked = false; break; case "MS,2": case "Ms,2": case "mS,2": case "ms,2": this.checkBox2.Checked = true; break; case "MR,2": case "Mr,2": case "mR,2": case "mr,2": this.checkBox2.Checked = false; break; } //! シリアルポートをオープンしていない場合、処理を行わない if (serialPort1.IsOpen == false) { return; } //! テキストボックスから、送信するテキストを取り出す String data = sndTextBox.Text; //! 送信するテキストがない場合、データ送信は行わない if (string.IsNullOrEmpty(data) == true) { return; } try { //! シリアルポートからテキストを送信する. serialPort1.Write(data + "\n"); int startIndex = data.IndexOf(","); if (startIndex > -1) { startIndex = startIndex + 1; // 開始位置","の次の文字 string tValue = data.Substring(startIndex); int value = Convert.ToInt32(tValue, 16); for (int i = 1; i <= 16; i++) { //画面上の処理対象チェックボックスコントロールを特定 Control[] cs = this.Controls.Find("CheckBox" + i.ToString(), true); //チェック対象ビットに1が立っていればチェックオン、0ならチェックオフ ((CheckBox)cs[0]).Checked = ((value & (1 << (i - 1))) > 0); } } } catch (Exception ex) { MessageBox.Show(ex.Message); } } }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問