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

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

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

Re[12]: 文字列を数値に変換


(過去ログ 117 を表示中)

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

■68666 / inTopicNo.1)  文字列を数値に変換
  
□投稿者/ じょしゅ (1回)-(2013/11/05(Tue) 16:29:50)

分類:[VB.NET/VB2005 以降] 

環境:Visual Basic 2008 Express Edition
OS:Xp、Win7
DB:mdb

デスクトップアプリケーションを作成しています。
入力画面で金額を入力するテキストボックスがあります。
たとえば1000を入力したら1,000と表示するようにしてあります。
この値をDBの数値型(長整数型)に保存するときに以下の処理をしています。

Dim str As String = Trim(txTanka.Text)
Dim num As Integer = Integer.Parse(str, NumberStyles.AllowThousands)

この方法の場合、入力した値がプラスの数字なら保存できます。
マイナスの場合ではエラーとなってしまいます。
プラスでもマイナスでも保存できるようにするため、以下の通りとしました。

Dim str As String = Trim(txTanka.Text)
Dim num As Integer = str

これって問題ないやり方でしょうか?

ちなみにテキストボックスには数字で正数しか受け付けないようにしてあります。


引用返信 編集キー/
■68669 / inTopicNo.2)  Re[1]: 文字列を数値に変換
□投稿者/ WebSurfer (81回)-(2013/11/05(Tue) 17:06:49)
No68666 (じょしゅ さん) に返信
> Dim str As String = Trim(txTanka.Text)
> Dim num As Integer = str
>
> これって問題ないやり方でしょうか?

あると言えばあるし、ないといえばないし、質問者さんのポリシーにもよると思い
ます。

Option Strict On にするとコンパイルエラーになると思いますが、何故そのような
オプションがあるか考えてみれば(分からなければググって見れば)問題あるのかど
うか分かると思います。
引用返信 編集キー/
■68670 / inTopicNo.3)  Re[1]: 文字列を数値に変換
□投稿者/ shu (412回)-(2013/11/05(Tue) 17:48:24)
No68666 (じょしゅ さん) に返信
> 環境:Visual Basic 2008 Express Edition
> OS:Xp、Win7
> DB:mdb
>
> デスクトップアプリケーションを作成しています。
> 入力画面で金額を入力するテキストボックスがあります。
> たとえば1000を入力したら1,000と表示するようにしてあります。
ここで一旦、数値に変換されているのであればその値を保持しておくのがよいかと思います。


> Dim str As String = Trim(txTanka.Text)
> Dim num As Integer = str
>
こう書くならCInt関数は使用した方がよいと思います。

あとTrimは関数ではなくTrimメソッドを使用する方が個人的にはすきです。
Trim(txtTanka.Text) => txtTanka.Text.Trim()

引用返信 編集キー/
■68675 / inTopicNo.4)  Re[2]: 文字列を数値に変換
□投稿者/ じょしゅ (2回)-(2013/11/06(Wed) 02:05:11)
No68669 (WebSurfer さん) に返信
>
> あると言えばあるし、ないといえばないし、質問者さんのポリシーにもよると思い
> ます。
>
> Option Strict On にするとコンパイルエラーになると思いますが、何故そのような
> オプションがあるか考えてみれば(分からなければググって見れば)問題あるのかど
> うか分かると思います。

WebSurfer さん ありがとうございます。
Option Strict Onの件調べてみました。
Onにするかどうかは確かに製作者のポリシー次第ですね。
今回は既に出来上がってるものの改修のため、全部を見直すとなるとちょっと大変なので
offでいきたいと思います。
ありがとうございました。
引用返信 編集キー/
■68676 / inTopicNo.5)  Re[2]: 文字列を数値に変換
□投稿者/ じょしゅ (3回)-(2013/11/06(Wed) 02:08:48)
No68670 (shu さん) に返信

>>デスクトップアプリケーションを作成しています。
>>入力画面で金額を入力するテキストボックスがあります。
>>たとえば1000を入力したら1,000と表示するようにしてあります。
> ここで一旦、数値に変換されているのであればその値を保持しておくのがよいかと思います。
>
>
>> Dim str As String = Trim(txTanka.Text)
>> Dim num As Integer = str
>>
> こう書くならCInt関数は使用した方がよいと思います。
>
> あとTrimは関数ではなくTrimメソッドを使用する方が個人的にはすきです。
> Trim(txtTanka.Text) => txtTanka.Text.Trim()
>
shu さん ありがとうございます。

Dim str As String = txtTanka.Text.Trim()
Dim num As Integer = CInt(str)
という形でいいのですよね。

引用返信 編集キー/
■68677 / inTopicNo.6)  Re[3]: 文字列を数値に変換
□投稿者/ 魔界の仮面弁士 (407回)-(2013/11/06(Wed) 03:10:45)
No68676 (じょしゅ さん) に返信
>   Dim str As String = txtTanka.Text.Trim()
>   Dim num As Integer = CInt(str)
> という形でいいのですよね。

簡易的にはその通りですが、システム設定が日本語になっていることが条件となります。

そもとも Trim せずとも、
 Dim num As Integer = CInt("   1,234   ")
は 1234 を返します。地域設定が「日本」の場合は。
しかし、地域設定がドイツになっている場合、上記は 1 を返すことに注意してください。

日本やアメリカでは、「, で桁区切り」「. が小数点」ですが、
ドイツやスペインは、「. で桁区切り」「, が小数点」だからです。
(他にも、空白で桁区切りする地域などがあります)


地域設定に依存せずに動作させるようにするのであれば、Integer.Parse や Integer.TryParse を用い、
引数に CultureInfo.InvariantCulture のカルチャを指定するのが安全です。
その分コードは冗長的になってしまうので、ケースバイケースで使い分けてみてください。


'Imports System.Globalization
Dim culture As CultureInfo = CultureInfo.InvariantCulture
Dim fmtInteger As NumberStyles = NumberStyles.Integer Or NumberStyles.AllowThousands
Dim num As Integer = Integer.Parse(txtTanka.Text, fmtInteger, culture)

ちなみに上記では、Trim を利用していません。
これは、NumberStyles.Integer に、前後の空白を無視するための指定
(AllowLeadingWhite と AllowTrailingWhite)が含まれているためです。


また、書式エラーなどの事も鑑みるのであれば、Intger.TryParse メソッドを使うのも手です。

あるいは、そもそも正しい入力値しか入れられないようにするために、
TextBox.Text の代わりに NumericUpDown.Value を使うと言う手もあります。
NumericUpDown なら、最小値/最大値も制限できますしね。



--- 以下、蛇足情報として ---

ついでに言うと、『strValue.Trim()』と『Trim(strValue)』とでは、
必ずしも同じ結果を返すわけではありません。
両者は、strValue が Nothing の場合の動作が異なる事に注意してください。

Nothing だった場合、前者(Trim メソッド)は NullReferenceException の例外エラーを
発生させますが、後者(VB の Trim関数)ではエラーとならず、長さ 0 の文字列 "" を返します。
その意味では、Trim 関数の方が安全であると見ることもできます。

とはいえ今回の場合で言えば、txtTanka.Text が Nothing を返すことは有りえないため、
結果的にはどちらを使っても一緒です。お好きなほうをどうぞ。



それから、VB には「Str 関数」が存在するため、str という変数名は
避けておいた方が無難かと思います。別に予約語というわけではありませんので、
変数名を str としても、動作上の問題は無いのですが、一応念のため。

引用返信 編集キー/
■68678 / inTopicNo.7)  Re[4]: 文字列を数値に変換
□投稿者/ じょしゅ (4回)-(2013/11/06(Wed) 03:31:59)
No68677 (魔界の仮面弁士 さん) に返信
> ■No68676 (じょしゅ さん) に返信
>> Dim str As String = txtTanka.Text.Trim()
>> Dim num As Integer = CInt(str)
>>という形でいいのですよね。
>
> 簡易的にはその通りですが、システム設定が日本語になっていることが条件となります。
>
> そもとも Trim せずとも、
>  Dim num As Integer = CInt(" 1,234 ")
> は 1234 を返します。地域設定が「日本」の場合は。
> しかし、地域設定がドイツになっている場合、上記は 1 を返すことに注意してください。
>
> 日本やアメリカでは、「, で桁区切り」「. が小数点」ですが、
> ドイツやスペインは、「. で桁区切り」「, が小数点」だからです。
> (他にも、空白で桁区切りする地域などがあります)
>

日本でしか使いませんので心配ないです。

> それから、VB には「Str 関数」が存在するため、str という変数名は
> 避けておいた方が無難かと思います。別に予約語というわけではありませんので、
> 変数名を str としても、動作上の問題は無いのですが、一応念のため。

strは実際には使ってませんので大丈夫ですが、今後のために頭にいれておきます。

魔界の仮面弁士 さん 大変勉強になりました。
ありがとうございました。
解決済み
引用返信 編集キー/
■68679 / inTopicNo.8)  Re[5]: 文字列を数値に変換
□投稿者/ 魔界の仮面弁士 (408回)-(2013/11/06(Wed) 03:56:36)
2013/11/06(Wed) 04:00:29 編集(投稿者)

No68678 (じょしゅ さん) に返信
> 日本でしか使いませんので心配ないです。

今回の件とは無関係ですが、関連情報として紹介:

日本の場合、地域設定で「和暦」設定されているケースに留意してください。
日付を yyyyMMdd 書式に Format する際、2013年 ではなく 25年と出力されます。

先の数値書式の件も含め、動作テストを行う際には、コントロールパネルの地域設定から、
日付・時刻・数値の形式を意図的に変更した状態での動作テストも行っておくことが望ましいです。


> Dim num As Integer = Integer.Parse(str, NumberStyles.AllowThousands)
> この方法の場合、入力した値がプラスの数字なら保存できます。
> マイナスの場合ではエラーとなってしまいます。

これは、NumberStyles にて符号書式を許可を行っていないためです。

「-1234」などの 前符号なら AllowLeadingSign を、
「1234-」などの 後符号なら AllowTrailingSign を併せて指定しましょう。

ちなみに No68677 のサンプルに書いた NumberStyles.Integer を使った場合、
AllowLeadingSign 相当の機能を含んでいる為、マイナス値も扱う事ができます。



それと、CInt 関数を用いた場合は
  num = CInt( "(1234)" )
という変換で -1234 が返されます。この場合の括弧は負数を意味します。
Integer.Parse では、AllowParentheses スタイルに相当する処理です。


また、
  num = CInt( "1e2" )
では、100 となります。1.0×10の2乗、という意味です。
Integer.Parse では、AllowExponent スタイルです。



このように、Integer.Parse や Integer.TryParse では、NumberStyles の指定によって、
受け入れる書式をコントロールすることができます。一方、CInt ではそれができません。
  num = CInt( "123" ) '全角数字
も、123 という数値に読みかえられますしね。


なので、(業務アプリなどで)厳密性を求める処理においては、書式やカルチャを指定可能な
TryParse メソッドを用いて制御すると良いでしょう。

もっとも自分の場合は、書式付文字列を変換するケース自体が稀であり、
入力値を事前に書式制限してしまうので、普段は CInt で変換することが多いです。
引用返信 編集キー/
■68686 / inTopicNo.9)  Re[3]: 文字列を数値に変換
□投稿者/ WebSurfer (82回)-(2013/11/06(Wed) 13:32:53)
No68675 (じょしゅ さん) に返信
> ■No68669 (WebSurfer さん) に返信
>>
>>あると言えばあるし、ないといえばないし、質問者さんのポリシーにもよると思い
>>ます。
>>
>>Option Strict On にするとコンパイルエラーになると思いますが、何故そのような
>>オプションがあるか考えてみれば(分からなければググって見れば)問題あるのかど
>>うか分かると思います。
>
> WebSurfer さん ありがとうございます。
> Option Strict Onの件調べてみました。
> Onにするかどうかは確かに製作者のポリシー次第ですね。
> 今回は既に出来上がってるものの改修のため、全部を見直すとなるとちょっと大変なので
> offでいきたいと思います。
> ありがとうございました。

いえ、On に変更するようお勧めした訳ではなくて、見つけにくいバグのもとになる VB6以前
の型変換に頼るのがよいのか、自分のコードできちんと型変換するのがよいのか、考えてみ
てはいかがですかというのが前の私のレスの趣旨なんですけど。

既存のコードまで直すのに手が回らなくても、改修する部分だけでも Option Strict On で通
るコードを書くことはできるはずです。

既にその方向で進まれているようですので、余計なお世話だったかもしれませんが・・・
引用返信 編集キー/
■68689 / inTopicNo.10)  Re[6]: 文字列を数値に変換
□投稿者/ ???債?? (1回)-(2013/11/07(Thu) 03:05:02)

魔界の仮面弁士 さんのNo68677No68679をじっくり読んで
以下のようにすることにしました。

まず、txTanka.textのLeaveで数字かどうか、小数点は含まれてないかをチェックして
OKなら#,##0の形式で画面に表示します。(txTankaのImeModeはoff)
ここまでで、半角の数値しかtxTankaにはないはず。

登録ボタンをクリックでDBに保存するところで

Dim fmtInteger As NumberStyles = NumberStyles.Integer Or NumberStyles.AllowThousands
Dim num As Integer = Integer.Parse(txTanka.Text, fmtInteger)
oCommand.Parameters.Add _
(New OleDbParameter("@u_sTanka", OleDbType.Integer, 20))
oCommand.Parameters("@u_sTanka").Value = num
---以下省略

としました。

ありがとうございました。


WebSurferへ
余計なお世話なんてとんでもないです。
勉強になりました。



解決済み
引用返信 編集キー/
■68691 / inTopicNo.11)  Re[7]: 文字列を数値に変換
□投稿者/ 魔界の仮面弁士 (409回)-(2013/11/07(Thu) 09:59:08)
No68689 (???債?? さん) に返信
じょしゅさんでしょうか。cookie砕けたかな。

> まず、txTanka.textのLeaveで数字かどうか、小数点は含まれてないかをチェックして
Leave イベントで行えなくも無いですが、こういう場合には、
 ・入力チェックは Validating イベントで行う。フォーカスの移動をキャンセルすることも可能。
 ・入力後の処理が必要な場合は、Validated イベントで行う。"1000" → "1,000" など。
のが一般的かと思います。


> OKなら#,##0の形式で画面に表示します。(txTankaのImeModeはoff)
OK で無かった場合はどうされていますか?
もしも Leave 内でフォーカス制御や MessageBox 表示を行っているのであれば、
それは避けた方が良いでしょう。


> ここまでで、半角の数値しかtxTankaにはないはず。
入力手段を封じておくと言う選択肢もあります。
http://jeanne.wankuma.com/tips/csharp/textbox/permitchars.html


> WebSurferへ
敬称抜けを警鐘
解決済み
引用返信 編集キー/
■68692 / inTopicNo.12)  Re[7]: 文字列を数値に変換
□投稿者/ shu (414回)-(2013/11/07(Thu) 11:53:36)
No68689 (???債?? さん) に返信

> まず、txTanka.textのLeaveで数字かどうか、小数点は含まれてないかをチェックして
> OKなら#,##0の形式で画面に表示します。(txTankaのImeModeはoff)
> ここまでで、半角の数値しかtxTankaにはないはず。
ImeModeをOffにしておくとキーボード、マウス操作でOnに出来てしまいます。
Disableにされた方が良いです。他にも対策をするならクリップボードからの貼り付けとか。
解決済み
引用返信 編集キー/
■68693 / inTopicNo.13)  Re[8]: 文字列を数値に変換
□投稿者/ 魔界の仮面弁士 (410回)-(2013/11/07(Thu) 12:15:15)
No68692 (shu さん) に返信
> ImeModeをOffにしておくとキーボード、マウス操作でOnに出来てしまいます。
> Disableにされた方が良いです。他にも対策をするならクリップボードからの貼り付けとか。

クリップボード入力は、WM_PASTE を捉えるなどすれば防げますね。
http://dobon.net/vb/dotnet/control/disablepaste.html


ただし、キー入力制限、IMEモード制限、クリップボード禁止などを盛り込んでも、
想定外の文字が入力される場合がありますので、その点はご注意を。
(たとえば、音声入力やペンによる手書き文字認識など)
解決済み
引用返信 編集キー/
■68702 / inTopicNo.14)  Re[9]: 文字列を数値に変換
□投稿者/ じょしゅ (5回)-(2013/11/08(Fri) 01:48:16)
WebSurferさんへ
敬称抜けてるのに気が付きませんでした。
大変失礼いたしました。
お詫び申し上げます。

shu さんへ
ありがとうございます。
ImeのoffとDisableの違いを意識してなかったです。
今後はDisableにしていきます。

魔界の仮面弁士 さんへ
クリップボード対策の仕方教えていただいてありがとうございます。

>> OKなら#,##0の形式で画面に表示します。(txTankaのImeModeはoff)
>OK で無かった場合はどうされていますか?
MessageBoxをだしてテキストボックスに0をセットして、そのテキストボックスにフォーカスを
移してます。

>もしも Leave 内でフォーカス制御や MessageBox 表示を行っているのであれば、
>それは避けた方が良いでしょう。
はじめは、MessageBox、フォーカス移動だけにしてたので延々とMessageBoxがでてしまったので
0を入れるようにしました。他に何か憂慮すべきことがあるのでしょうか?


>ただし、キー入力制限、IMEモード制限、クリップボード禁止などを盛り込んでも、
>想定外の文字が入力される場合がありますので、その点はご注意を。
>(たとえば、音声入力やペンによる手書き文字認識など)
いろんなことが想定できますね。音声入力なんかは考えもしなかったです。

引用返信 編集キー/
■68709 / inTopicNo.15)  Re[10]: 文字列を数値に変換
□投稿者/ 魔界の仮面弁士 (414回)-(2013/11/08(Fri) 14:49:56)
No68702 (じょしゅ さん) に返信
> ImeのoffとDisableの違いを意識してなかったです。
> 今後はDisableにしていきます。
以下、関連情報として。
http://www.roppi.net/2010/12/imemode_bug_or_spec/
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=28619&forum=7
http://d.hatena.ne.jp/studio-m/20090312/


>> もしも Leave 内でフォーカス制御や MessageBox 表示を行っているのであれば、
>> それは避けた方が良いでしょう。
> はじめは、MessageBox、フォーカス移動だけにしてたので延々とMessageBoxがでてしまったので
> 0を入れるようにしました。他に何か憂慮すべきことがあるのでしょうか?

イベント連鎖の問題というよりも、モーダルダイアログ(この場合は MessageBox)を
そのタイミングで表示すること自体が、あまり望ましく無い、という程度の話です。

ダイアログが出ることにより、ユーザー入力操作が阻害されてしまいますので、
連続タイピングするようなユーザーにとっては邪魔になります。表示させるのであれば
直ちにユーザーの操作を中断させるほどの事情がある場合に限定した方が良いでしょうね。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=42520&forum=7&start=8
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=28938&forum=7


ただし、別コントロールにフォーカスを移すような制御については御法度とされています。
問題が生じるとすれば、むしろこちらのパターンです。
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.control.leave.aspx
》 【注意】
》 Enter、 GotFocus、 Leave、 LostFocus、 Validating、または
》 Validated イベント ハンドラーの中からフォーカスを設定しないでください。
》 フォーカスを設定すると、アプリケーションやオペレーティング システムが
》 応答を停止することがあります。詳細については、MSDN ライブラリにある
》 「Keyboard Input Reference」セクションの WM_KILLFOCUS、および
》 「About Messages and Message Queues」トピックの
》 「Message Deadlocks」セクションを参照してください。
引用返信 編集キー/
■68710 / inTopicNo.16)  Re[11]: 文字列を数値に変換
□投稿者/ 魔界の仮面弁士 (415回)-(2013/11/08(Fri) 15:14:32)
No68709 (魔界の仮面弁士) に追記
> そのタイミングで表示すること自体が、あまり望ましく無い、という程度の話です。

以下蛇足:

ちなみに下記は、Visual Studio の設定画面への入力操作中の画面イメージです。
入力値エラーに対する通知方法について、とりあえず 3 パターン集めてみました。

http://www.vb-user.net/junk/replySamples/2013.11.08.13.43/error1.png
http://www.vb-user.net/junk/replySamples/2013.11.08.13.43/error2.png
http://www.vb-user.net/junk/replySamples/2013.11.08.13.43/error3.png


error1 は非数字を入力しようとしたときの表示ですが、MessageBox ではなく
いわゆるバルーン通知となっています。ダイアログによる通知とは異なり、
フォーカスが奪われないため、ユーザーの入力操作を阻害しません。
(逆に言うと、阻害した方が良いパターンでは使えません)

フォーカス移動時だけではなく、入力中にリアルタイムに警告を表示することも
可能な手法です。パスワード入力画面の CapsLock 警告などにも使われていますね。
http://blog.hiros-dot.net/?p=1626
http://anetm.com/dev/tools/vbdotnet/112270.htm
http://dobon.net/vb/dotnet/control/balloontooltip.html


error2 は入力値の修正を依頼する警告で、こちらはメッセージボックスが使われています。
しかし、それが表示されるタイミングはフォーカス遷移時ではなく、値の確定時
(ダイアログの[OK]を押したタイミングや、次画面に遷移する場合など)です。
フォーカス遷移時に呼ばれるわけではないため、入力処理が中断されることが無く、
汎用的に使える手法です。他の方法(error1/error3 など)と併用して使うこともありますね。


error3 は、フォーカス遷移時にメッセージボックス通知されるタイプです。
先の投稿で非推奨としていたパターンがこちら。
入力操作を中断させる行為となるため、多用するのは考え物ですが、
緊急性の高い入力エラーを直ちに修正させるのには有用かと思います。
引用返信 編集キー/
■68716 / inTopicNo.17)  Re[12]: 文字列を数値に変換
□投稿者/ じょしゅ (6回)-(2013/11/08(Fri) 21:41:28)
No68710 (魔界の仮面弁士 さん) に返信
魔界の仮面弁士さん。
いろいろな有用情報をありがとうございます。
メッセージの出し方にもいろんな方法があるのですね。
勉強になりました。


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


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

このトピックに書きこむ

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

管理者用

- Child Tree -