if文 比較対象が3つ
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2018/5/23 01:25:08
こういう場合には
> 実行すると
> if a>bになっています
『If a > b > c Then』という演算は、
『If (a > b) > c Then』の順で評価されます。
そして (a > b) の結果は、True または False になるため、これは即ち
『If True > c Then』
『If False > c Then』
のいずれかの意味になるわけです。
このとき、c のデータ型が Boolean だった場合には、
常に Else 句が実行されることになるはずです。
(VB においては、True よりも False の方が大きな値として扱われるため)
一方、c がもしも Integer だった場合、そこで暗黙の型変換が実行されます。
たとえば 『If CInt(a > b) > c Then』 相当という具合に。
そして、CInt(True) は -1、CInt(False) は 0 にあたりますので、
下記の実行結果は、Option Strict Off なら「真」、Option Strict On なら「エラー」扱いです。
If a > b AndAlso b > c Then
のように記述します。> 実行すると
> if a>bになっています
『If a > b > c Then』という演算は、
『If (a > b) > c Then』の順で評価されます。
そして (a > b) の結果は、True または False になるため、これは即ち
『If True > c Then』
『If False > c Then』
のいずれかの意味になるわけです。
このとき、c のデータ型が Boolean だった場合には、
常に Else 句が実行されることになるはずです。
(VB においては、True よりも False の方が大きな値として扱われるため)
一方、c がもしも Integer だった場合、そこで暗黙の型変換が実行されます。
たとえば 『If CInt(a > b) > c Then』 相当という具合に。
そして、CInt(True) は -1、CInt(False) は 0 にあたりますので、
下記の実行結果は、Option Strict Off なら「真」、Option Strict On なら「エラー」扱いです。
Dim a As Integer = +2
Dim b As Integer = 0
Dim c As Integer = -2
If a > b > c Then
投稿者 uuu  (社会人)
投稿日時
2018/5/23 22:12:30
途中でわからなくなったので、教えてください
a,b,cのテキストボックスが3つあります。
入力する値の大きさは下記が条件です
a>b>c
教えていただいた
If a > b AndAlso b > c Then
は a>cも含まれているでしょうか?
またテキストボックスに入力時に3つの関係が不適切ならメッセージを出すようにしたいです。
例えばb>aなら下記みたいなイメージです
If Val(TextBox2.Text) > Val(TextBox1.Text) Then
MsgBox("bはaより小さいです")
これをc>b>aで、まとめて比較し、できるようにしたいです
ただこれだけだと、TextBox2.Text入力後、違うテキストボックスに入力しようとするとメッセージが出てしまいます。
対策として下記で対応しているんですけど、問題はありませんか?
If TextBox2.TextLength <> 0 AndAlso TextBox1.TextLength <> 0 Then
現状はこのようになっています。
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each q In Me.Controls.OfType(Of TextBox)()
AddHandler q.Leave, AddressOf TextBoxes_Leave
Next
End Sub
Private Sub TextBoxes_Leave(sender As TextBox, e As EventArgs)
Dim d As Double
If Double.TryParse(sender.Text, d) AndAlso d > 0 Then
sender.ResetBackColor()
If TextBox2.TextLength <> 0 AndAlso TextBox1.TextLength <> 0 Then
If Val(TextBox2.Text) > Val(TextBox1.Text) Then
MsgBox("bはaより小さいです")
sender.BackColor = Color.Red
sender.Focus()
End If
ElseIf TextBox3.TextLength <> 0 AndAlso TextBox2.TextLength <> 0 Then
If Val(TextBox3.Text) > Val(TextBox2.Text) Then
MsgBox("cはbより小さいです")
sender.BackColor = Color.Red
sender.Focus()
ElseIf TextBox3.TextLength <> 0 AndAlso TextBox1.TextLength <> 0 Then
If Val(TextBox3.Text) > Val(TextBox1.Text) Then
MsgBox("cはaより小さいです")
sender.BackColor = Color.Red
sender.Focus()
End If
End If
End If
End If
End Sub
コードがものすごく長いので短くもしたいです。
a,b,cのテキストボックスが3つあります。
入力する値の大きさは下記が条件です
a>b>c
教えていただいた
If a > b AndAlso b > c Then
は a>cも含まれているでしょうか?
またテキストボックスに入力時に3つの関係が不適切ならメッセージを出すようにしたいです。
例えばb>aなら下記みたいなイメージです
If Val(TextBox2.Text) > Val(TextBox1.Text) Then
MsgBox("bはaより小さいです")
これをc>b>aで、まとめて比較し、できるようにしたいです
ただこれだけだと、TextBox2.Text入力後、違うテキストボックスに入力しようとするとメッセージが出てしまいます。
対策として下記で対応しているんですけど、問題はありませんか?
If TextBox2.TextLength <> 0 AndAlso TextBox1.TextLength <> 0 Then
現状はこのようになっています。
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each q In Me.Controls.OfType(Of TextBox)()
AddHandler q.Leave, AddressOf TextBoxes_Leave
Next
End Sub
Private Sub TextBoxes_Leave(sender As TextBox, e As EventArgs)
Dim d As Double
If Double.TryParse(sender.Text, d) AndAlso d > 0 Then
sender.ResetBackColor()
If TextBox2.TextLength <> 0 AndAlso TextBox1.TextLength <> 0 Then
If Val(TextBox2.Text) > Val(TextBox1.Text) Then
MsgBox("bはaより小さいです")
sender.BackColor = Color.Red
sender.Focus()
End If
ElseIf TextBox3.TextLength <> 0 AndAlso TextBox2.TextLength <> 0 Then
If Val(TextBox3.Text) > Val(TextBox2.Text) Then
MsgBox("cはbより小さいです")
sender.BackColor = Color.Red
sender.Focus()
ElseIf TextBox3.TextLength <> 0 AndAlso TextBox1.TextLength <> 0 Then
If Val(TextBox3.Text) > Val(TextBox1.Text) Then
MsgBox("cはaより小さいです")
sender.BackColor = Color.Red
sender.Focus()
End If
End If
End If
End If
End Sub
コードがものすごく長いので短くもしたいです。
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2018/5/24 04:52:12
kkkkk さんと uuu さんは同じ方でしょうか?
別の質問とはいえ、内容が酷似しているようなので。
> 教えていただいた
> If a > b AndAlso b > c Then
> は a>cも含まれているでしょうか?
はい。たとえば a, b, c いずれもが Integer 値だとすれば、
a > b かつ b > c であるにも関わらず、
a > c にならない(つまり a ≦ c である)ような数はありえませんよね。
数学的に言えば、 (a > b) ∧ (b > c) の関係を意味しますので、
それが (a > c) の関係であることも自明となります。
厳密に言ってしまえば、言語仕様的には
If a > b AndAlso b > c AndAlso a > c Then
If a > b AndAlso b > c Then
の 2 つの結果が異なる結果になることも、一応ありえなくはなかったりします。
とはいえそれは非常に特殊なケースに限られますので、
通常はそこまで考えなくて良いでしょう。
> If Val(TextBox2.Text) > Val(TextBox1.Text) Then
Val の利用はおすすめしません。(エラーになりえるので)
せっかく TryParse メソッドを利用しているのですから、
それで変換した値を使うべきでしょう。
> 対策として下記で対応しているんですけど、問題はありませんか?
問題があると思いますよ。
強制的にフォーカスを当てなおしているのが、あまり良くないですが、
それ以上に、テキストの内容が『』や『XYZ』や『0』や『-123』だった場合の
処置が抜けているのが問題ですし、sender と TextBox1~3 の組み合わせも不自然です。
また、a, b, c の 3 個所のうち、2 個所の修正が必要な場合において、
そのうちの 1 個所を編集すると、一時的に大小関係が崩れてしまい、
2 個所目の編集が始められないといったパターンが起こりそうです。
極端な話、初期状態でのフォーカス位置と TextBox の値が下記のようになっていた場合、
提示頂いたコードだと、a(TextBox1) と b(TextBox2) の比較でメッセージが表示されるのに、
それとは無関係のはずの c(TextBox3)が赤くなり、a や b を訂正しようとしても
阻害されてしまうことになると思います。
そもそも、今回の仕様が
・どういう時に赤くなってほしいのか
・赤から標準色に戻すのはどういう時か
・Leave したコントロール以外が赤になってほしいパターンがあるのか
・Leave したコントロール以外を標準色に戻したいパターンがあるのか
・「空欄時」「非数値の時」「マイナス値の時」「0 の時」とで、対処を変える必要があるのか否か
などが曖昧なので、どういう動作を求めているのかを、
より細かく確認しなおすのが先決かと思います。
> またテキストボックスに入力時に3つの関係が不適切ならメッセージを出すようにしたいです。
「3 つの関係」を調査しなければならないのに、1 つのボックスの Leave 時に
即時検査する画面設計にしているのが、話を複雑化しているように思います。
こういう場合には、入力後即時に検査するのではなく、値を確定するタイミングを
後回しにするという手法が良く利用されます。
たとえば、ファイルを右クリックしてプロパティを表示させた場合、
[全般]タブでファイル名を変更できるようになっていますが、ここで、
ファイル名のテキストボックスを空にしたり、ファイル名として利用できない文字を
入力したとしても、それだけでは直ちにエラーメッセージが表示されることはありません。
この場合、ファイル名の入力値検査は、プロパティ ダイアログの
[OK]ボタンを押したタイミングで行われるようになっています。
なのでそれを真似て、Leave 時あるいは Validating 時に検査するのは、
「現在のボックスに正数がセットされたか」のみに限定してしまい、
各ボックスの大小判定は、ボタンクリック時などといった
別のタイミングで検証した方が良いのではないでしょうか。
仮に、ユーザー入力の問題をその場で指摘した方がよい仕様だったとしても、
モーダルのメッセージなどを用いるのではなく、こういう場合には
インプレースエラー表示(たとえば ErrorProvider を利用した表現)や、
モードレスのエラー処理(たとえば Tooltip のバルーンモード) の利用を
検討した方が、うまくいくかもしれません。
https://msdn.microsoft.com/ja-jp/library/aa511267.aspx#presentation
MsgBox などといったモーダルのエラー処理を行うと、エラーメッセージを閉じるまで、
値の再入力ができなくなるので、連続した入力を阻害する結果になりえます。
別の質問とはいえ、内容が酷似しているようなので。
> 教えていただいた
> If a > b AndAlso b > c Then
> は a>cも含まれているでしょうか?
はい。たとえば a, b, c いずれもが Integer 値だとすれば、
a > b かつ b > c であるにも関わらず、
a > c にならない(つまり a ≦ c である)ような数はありえませんよね。
数学的に言えば、 (a > b) ∧ (b > c) の関係を意味しますので、
それが (a > c) の関係であることも自明となります。
厳密に言ってしまえば、言語仕様的には
If a > b AndAlso b > c AndAlso a > c Then
If a > b AndAlso b > c Then
の 2 つの結果が異なる結果になることも、一応ありえなくはなかったりします。
とはいえそれは非常に特殊なケースに限られますので、
通常はそこまで考えなくて良いでしょう。
> If Val(TextBox2.Text) > Val(TextBox1.Text) Then
Val の利用はおすすめしません。(エラーになりえるので)
せっかく TryParse メソッドを利用しているのですから、
それで変換した値を使うべきでしょう。
> 対策として下記で対応しているんですけど、問題はありませんか?
問題があると思いますよ。
強制的にフォーカスを当てなおしているのが、あまり良くないですが、
それ以上に、テキストの内容が『』や『XYZ』や『0』や『-123』だった場合の
処置が抜けているのが問題ですし、sender と TextBox1~3 の組み合わせも不自然です。
また、a, b, c の 3 個所のうち、2 個所の修正が必要な場合において、
そのうちの 1 個所を編集すると、一時的に大小関係が崩れてしまい、
2 個所目の編集が始められないといったパターンが起こりそうです。
極端な話、初期状態でのフォーカス位置と TextBox の値が下記のようになっていた場合、
提示頂いたコードだと、a(TextBox1) と b(TextBox2) の比較でメッセージが表示されるのに、
それとは無関係のはずの c(TextBox3)が赤くなり、a や b を訂正しようとしても
阻害されてしまうことになると思います。
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each q In Me.Controls.OfType(Of TextBox)()
AddHandler q.Leave, AddressOf TextBoxes_Leave
Next
TextBox1.Text = "10"
TextBox2.Text = "20"
TextBox3.Text = "30"
ActiveControl = TextBox3
End Sub
そもそも、今回の仕様が
・どういう時に赤くなってほしいのか
・赤から標準色に戻すのはどういう時か
・Leave したコントロール以外が赤になってほしいパターンがあるのか
・Leave したコントロール以外を標準色に戻したいパターンがあるのか
・「空欄時」「非数値の時」「マイナス値の時」「0 の時」とで、対処を変える必要があるのか否か
などが曖昧なので、どういう動作を求めているのかを、
より細かく確認しなおすのが先決かと思います。
> またテキストボックスに入力時に3つの関係が不適切ならメッセージを出すようにしたいです。
「3 つの関係」を調査しなければならないのに、1 つのボックスの Leave 時に
即時検査する画面設計にしているのが、話を複雑化しているように思います。
こういう場合には、入力後即時に検査するのではなく、値を確定するタイミングを
後回しにするという手法が良く利用されます。
たとえば、ファイルを右クリックしてプロパティを表示させた場合、
[全般]タブでファイル名を変更できるようになっていますが、ここで、
ファイル名のテキストボックスを空にしたり、ファイル名として利用できない文字を
入力したとしても、それだけでは直ちにエラーメッセージが表示されることはありません。
この場合、ファイル名の入力値検査は、プロパティ ダイアログの
[OK]ボタンを押したタイミングで行われるようになっています。
なのでそれを真似て、Leave 時あるいは Validating 時に検査するのは、
「現在のボックスに正数がセットされたか」のみに限定してしまい、
各ボックスの大小判定は、ボタンクリック時などといった
別のタイミングで検証した方が良いのではないでしょうか。
仮に、ユーザー入力の問題をその場で指摘した方がよい仕様だったとしても、
モーダルのメッセージなどを用いるのではなく、こういう場合には
インプレースエラー表示(たとえば ErrorProvider を利用した表現)や、
モードレスのエラー処理(たとえば Tooltip のバルーンモード) の利用を
検討した方が、うまくいくかもしれません。
https://msdn.microsoft.com/ja-jp/library/aa511267.aspx#presentation
MsgBox などといったモーダルのエラー処理を行うと、エラーメッセージを閉じるまで、
値の再入力ができなくなるので、連続した入力を阻害する結果になりえます。
投稿者 uuu  (社会人)
投稿日時
2018/5/24 19:17:50
仕様は
・どういう時に赤くなってほしいのか a>b>cの関係が成り立っていないときです
・赤から標準色に戻すのはどういう時 a>b>cの関係が成り立っているときです
・Leave したコントロール以外が赤になってほしいパターンがあるのか ないです
・Leave したコントロール以外を標準色に戻したいパターンがあるのか ないです
・「空欄時」「非数値の時」「マイナス値の時」「0 の時」とで、対処を変える必要があるのか否か いまのところは練習のためなしです。
今はa>b>cの関係だけに注目し作っています。
>なのでそれを真似て、Leave 時あるいは Validating 時に検査するのは、
>「現在のボックスに正数がセットされたか」のみに限定してしまい、
>各ボックスの大小判定は、ボタンクリック時などといった
>別のタイミングで検証した方が良いのではないでしょうか。
判定はボタンクリック時に変更しました。
これも実施しているのですが、うまくいきません。
If a > b AndAlso b > c Then
で実施しているのですが、3個に入力後にどれか1つ値を変化させると、a>b>cの関係性が崩れても
msgを出さないようになってしまっています
・どういう時に赤くなってほしいのか a>b>cの関係が成り立っていないときです
・赤から標準色に戻すのはどういう時 a>b>cの関係が成り立っているときです
・Leave したコントロール以外が赤になってほしいパターンがあるのか ないです
・Leave したコントロール以外を標準色に戻したいパターンがあるのか ないです
・「空欄時」「非数値の時」「マイナス値の時」「0 の時」とで、対処を変える必要があるのか否か いまのところは練習のためなしです。
今はa>b>cの関係だけに注目し作っています。
>なのでそれを真似て、Leave 時あるいは Validating 時に検査するのは、
>「現在のボックスに正数がセットされたか」のみに限定してしまい、
>各ボックスの大小判定は、ボタンクリック時などといった
>別のタイミングで検証した方が良いのではないでしょうか。
判定はボタンクリック時に変更しました。
これも実施しているのですが、うまくいきません。
If a > b AndAlso b > c Then
で実施しているのですが、3個に入力後にどれか1つ値を変化させると、a>b>cの関係性が崩れても
msgを出さないようになってしまっています
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2018/5/25 11:27:43
> 今はa>b>cの関係だけに注目し作っています。
c が最小値となるべきなのですよね。
仮に、kkkkk さん= uuu さんだとしたら、この条件は
a > b > c > 0
が正しいのでは無いでしょうか。
また、「数値しか入力させない」という前提で開発するのであれば、
そもそも TextBox1.Text を使うべきではなく、
NumericUpDown1.Value を使った方が楽でしょう。
NumericUpDown なら、必ず数値が入力されることになるので、
非数値が入力されることを考慮せず、a / b / c の大小判定のみに専念できますし、
NumericUpDown の DecimalPlaces と Minimum プロパティを適切にセットしておけば、
そもそも 0 以下の値が入力されることさえ防げます。
もしも TextBox で続けるのであれば、
>> ・「空欄時」「非数値の時」「マイナス値の時」「0 の時」とで、対処を変える必要があるのか否か
という入力が発生することは防げないので、そのときの対処は決めておかねばならず、
> いまのところは練習のためなしです。
と逃げるわけには行かなくなります。
とはいえ、もしも上記の 4 種を区別しないのであれば、
とりあえず簡単なのは、こんな実装ですかね。
c が最小値となるべきなのですよね。
仮に、kkkkk さん= uuu さんだとしたら、この条件は
a > b > c > 0
が正しいのでは無いでしょうか。
また、「数値しか入力させない」という前提で開発するのであれば、
そもそも TextBox1.Text を使うべきではなく、
NumericUpDown1.Value を使った方が楽でしょう。
NumericUpDown なら、必ず数値が入力されることになるので、
非数値が入力されることを考慮せず、a / b / c の大小判定のみに専念できますし、
NumericUpDown の DecimalPlaces と Minimum プロパティを適切にセットしておけば、
そもそも 0 以下の値が入力されることさえ防げます。
もしも TextBox で続けるのであれば、
>> ・「空欄時」「非数値の時」「マイナス値の時」「0 の時」とで、対処を変える必要があるのか否か
という入力が発生することは防げないので、そのときの対処は決めておかねばならず、
> いまのところは練習のためなしです。
と逃げるわけには行かなくなります。
とはいえ、もしも上記の 4 種を区別しないのであれば、
とりあえず簡単なのは、こんな実装ですかね。
Dim a, b, c As Decimal
Decimal.TryParse(TextBox1.Text, a)
Decimal.TryParse(TextBox2.Text, b)
Decimal.TryParse(TextBox3.Text, c)
If a > b AndAlso b > c AndAlso c > 0D Then
TextBox1.ResetBackColor()
TextBox2.ResetBackColor()
TextBox3.ResetBackColor()
'
'正しい値が得られたので、a,b,cを使った処理をここに記述
'
Else
'正しい入力ではない
TextBox1.BackColor = Color.Red
TextBox2.BackColor = Color.Red
TextBox3.BackColor = Color.Red
MsgBox("a>b>c>0な入力になっていません")
Return
End If
教えていただけないでしょうか?
if a>b>c then
処理
end if
実行すると
if a>bになっています