PDA

View Full Version : راهنمایی برای تشخیص نوع ورودی ها در #C



sina4everafter
پنج شنبه 04 اردیبهشت 1393, 09:31 صبح
سلام.امکانش هست راهنمایی کنید که چهطور وقتی یه ورودی و کاربر وارد می کنه، برنامه تشخیص بده که اون ورودی عدد نیست و یه ورودی ای از نوع String (ه).
اگه راهنمایی کنید ممنون میشم.

hadi46
پنج شنبه 04 اردیبهشت 1393, 11:32 صبح
با سلام
میتونید از این کد برای تشخیص عدد استفاده کنید وبه دلخواه برای تشخیص رشته استفاده کنید

private void txtLong_KeyPress(System.Object sender, System.Windows.Forms.KeyPressEventArgs e){
if (!Information.IsNumeric(e.KeyChar)) {
e.Handled = true;
}


}

علی متقی پور
پنج شنبه 04 اردیبهشت 1393, 14:32 عصر
هیچ راه کاملی جز استفاده از try...catch وجود نداره

hamid_hr
پنج شنبه 04 اردیبهشت 1393, 15:05 عصر
نه حتما نمیخواد داخل try catch بزاری
بنویس

long x;
bool bl = long.TryParse(txt,out x);

اگه bl برابر true بود یعنی عددی هست وگرنه تکست هست

علی متقی پور
پنج شنبه 04 اردیبهشت 1393, 18:11 عصر
حمید عزیز در داخل متد TryParse هم از همن تکنیک استفاده شده
این مطلب هم که دیتا تایپ Long رو انتخاب کردید برام جالب بود :)

plus
پنج شنبه 04 اردیبهشت 1393, 18:43 عصر
حمید عزیز در داخل متد TryParse هم از همن تکنیک استفاده شده ضمن اینکه با این کار فقط عدد بود رو میفهمیم ولی عملا عدد کانورت شده رو نداریم
این مطلب هم که دیتا تایپ Long رو انتخاب کردید برام جالب بود :)
پیاده سازی Parse با TryParse تا حدی متفاوته.قرار دادن Parse در Try..Catch عملا باعث ایجاد یک Exception بی جا میشه و از اونجایی که TryParse ارائه شده، اشتباه هست؛ TryParse ارائه شده که این کار انجام نشه :)
مقدار تبدیل شده هم توسط پارامتر out برگردونده میشه.Long هم نوع داده عددی 64 بیتی هست تعجبی نداره که این دوستمون استفاده کردن :)

esafb52
پنج شنبه 04 اردیبهشت 1393, 19:30 عصر
پیاده سازی Parse با TryParse تا حدی متفاوته.قرار دادن Parse در Try..Catch عملا باعث ایجاد یک Exception بی جا میشه و از اونجایی که TryParse ارائه شده، اشتباه هست؛ TryParse ارائه شده که این کار انجام نشه :)
مقدار تبدیل شده هم توسط پارامتر out برگردونده میشه.Long هم نوع داده عددی 64 بیتی هست تعجبی نداره که این دوستمون استفاده کردن :) دقیقا قابل توجه جناب متقی پور
در ضمن اون out برای گرفتن اون عدد هست که شما می فرمایین بهش دسترسی ندارین

علی متقی پور
جمعه 05 اردیبهشت 1393, 00:01 صبح
با سلام

با روشی که شما میفرمائید تمام اعداد اعشاری هم غیر عدد تشخیص داده میشن

مگه اینکه نوع عددی را دسیمال مشخص کنیم نه لانگ (ممنون از آقای پلاس که به بنده یاد دادن لانگ چیه!!!)

ضمنا همیشه تولید اکسپشن بد نیست :)

علی متقی پور
جمعه 05 اردیبهشت 1393, 00:19 صبح
در حقیقت اگر بخواهیم منصفانه حرف بزنیم مطمئن ترین راه اینه عدد رو به دسیمال کانورت کنیم. بعدم در قسمت catch اگر اپلیکیشنمون یه آپ حرفه ای و اینترپرایز بود یک استثناء کاستومایز تولید میکنیم و به ماژول هندل استثنائات پاس میدیم اما اگر یه برنامه ساده بود همونجا بر حسب سناریو قضیه رو هندل میکنیم. نمیشه یک راه وحد رو پیشنهاد داد. ممکنه تو یک سناریو اگر دیتای ورودی نامعتبر تشخیص داده بشه بجاش یک مقدار پیش فرض جایگزین بشه. یا ممکنه اصولا همانند حالیبه حساب بیاد که کاربر چیزی وارد نکرده. مثلا فرض کنید تو یک فرم ثبت نام یکی سنش را "علی" وارد کنه یکی "1250" خب هر دوی اینها واقعا نامعتبرن و ما بسته به سناریومون هست که در مرودشون تصمیم میگیریم.

plus
جمعه 05 اردیبهشت 1393, 10:57 صبح
با سلام
با روشی که شما میفرمائید تمام اعداد اعشاری هم غیر عدد تشخیص داده میشن
مگه اینکه نوع عددی را دسیمال مشخص کنیم نه لانگ (ممنون از آقای پلاس که به بنده یاد دادن لانگ چیه!!!)
ضمنا همیشه تولید اکسپشن بد نیست :)
اگه قرار باشه اعداد اعشاری هم مورد قبول باشن به عنوان عدد باید از Double.TryParse یا float.TryParse استفاده بشه. حالا اگه شما int.Parse رو داخل Try...Catch بگذاری اعداد اعشاری هم عدد تشخیص داده میشن؟!
خوب از اونجایی که شما نمیدونستی int.TryParse یک پارامتر نوع out میگیره و lاز long قرار دادن دوستمون متعجب بودی گفتم شاید نمیدونی! والا!
تولید Exception بد نیست اما تولید Exception بی جا کاملا اشتباه هست.فکر میکنید طراحان دات نت نمیدونستن میشه Parse رو داخل Try Catch گذاشت، همینطوری TryParse (اونم با پیاده سازی که درونش try catch نیست) رو ارائه دادن که تعداد متد ها رو ببرن بالا؟!
من نمیفهمم وقتی یک چیزی رو اشتباه میگین چرا روی اشتباه خودتون پافشاری میکنید...برای اونهایی که شما براشون تدریس میکنین متاسفم.نه صرفا بخاطر سطح دانشتون بلکه به خاطر این روحیه ای که دارین.
ضمنا اگه کسی توی فروم چیزی رو اشتباه بگه برای من مهم نیست به هر حال هرکس در سطح دانش خودش صحبت میکنه...منم ممکنه چیزی رو اشتباه بگم.اما اینکه شما از کسی ایراد میگیری و ایرادت هم کاملا اشتباه است باعث شد من پست بگذارم.


در حقیقت اگر بخواهیم منصفانه حرف بزنیم مطمئن ترین راه اینه عدد رو به دسیمال کانورت کنیم. بعدم در قسمت catch اگر اپلیکیشنمون یه آپ حرفه ای و اینترپرایز بود یک استثناء کاستومایز تولید میکنیم و به ماژول هندل استثنائات پاس میدیم اما اگر یه برنامه ساده بود همونجا بر حسب سناریو قضیه رو هندل میکنیم. نمیشه یک راه وحد رو پیشنهاد داد. ممکنه تو یک سناریو اگر دیتای ورودی نامعتبر تشخیص داده بشه بجاش یک مقدار پیش فرض جایگزین بشه. یا ممکنه اصولا همانند حالیبه حساب بیاد که کاربر چیزی وارد نکرده. مثلا فرض کنید تو یک فرم ثبت نام یکی سنش را "علی" وارد کنه یکی "1250" خب هر دوی اینها واقعا نامعتبرن و ما بسته به سناریومون هست که در مرودشون تصمیم میگیریم.
تبدیل به Decimal برای تشخص عددی که میدونیم باید صحیح باشه؟ و بعد گذاشتن اون در Try Catch و....؟ اصلا متوجه هستین چی میگین؟
اگه قراره عدد صحیح باشه و لازمه که استثنایی روی بده:

int value;
if (!int.TryParse(input, out value)) {
throw new Exception("Invalid Input..");
}

اگه قراره استثنای پیشفرض روی بده (توی حالتی که انتظار دارین رشته ورودی متعبر باشه):

int value = int.Parse(input);

برای هر سناریویی که فرض کنید، با وجود TryParse، گذاشتن Parse در Try Catch اشتباه هست...اصلا منطق وجودی TryParse رو زیر سوال میبره.برای سناریوی سن، فرض که قراره اگه مقدار عددی نبود یک خطا اعلام بشه و اگه خارج از محدوده بود یک خطای دیگ.

int value;
if (!int.TryParse(input, out value)) {
throw new Exception("Invalid Input..");
}
if (value > 100 || value < 0) {
throw new ArgumentOutOfRangeException("Age must be between 0 and 100");
}

ضمن اینکه ما اینجا به صورت دستی بازه مورد علاقمون رو بررسی میکنیم.اگه بخواین به نوع Exception ایجاد شده توسط Parse اتکا کنی، اون کل بازه int رو مد نظر قرار میده.یعنی کد مورد نظر شما چیزی شبیه این میشه!:

int value;
try {
value = int.Parse(input);
}
catch (FormatException fe) {
throw new Exception("Invalid input..");
}
catch (OverflowException oe) {
throw new ArgumentOutOfRangeException("Age must be between 0 and 100");
}
if (value > 100 || value < 0) {
throw new ArgumentOutOfRangeException("Age must be between 0 and 100");
}

ضمن اینکه ایجا آخرش کد مقایسه به صورت مجزا نوشته میشه...
حالا اگه شما بخوای بگه من میخوام از Decimal استفاده کنم تا محدوده بیشتری رو به عنوان عدد خارج از محدوده (بجای ورودی کلا غیر عدد) تشخیص بدم، باز توی کد اول، جای int از decimal یا هر چیز دیگه ای استفاده میکنی...باز هم قرار نیست Parse در try..catch قرار بگیره...
بله از طریق نوع Exception میشه فهمید که مقدار خارج از محدوده هست یا کلا نامعتبر.به فرض اینکه واقعا یک چنین نیازی هم باشه، با یک مقایسه ساده میشه این کار رو انجام داد تا اینکه بخواین بی جهت باعث ایجاد یک Exception بشین که قراره بلافاصله Handle بشه.
حالا شما اگه بخوای میتونی روی اشتباه خودت پافشاری کنی فکر نمیکنم بیشتر از این برای من اهمیت داشته باشه که بخوام توی این تاپیک پست بگذارم :)

پینوشت: محض اطلاع بیشتر، این کد رو اجرا کنید:

string input = "1d2131";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
for (int i = 0; i < 10000; i++) {
int value;
try {
value = int.Parse(input);
}
catch (Exception) {
}
}
stopWatch.Stop();
Debug.WriteLine(string.Format("Process time: {0}ms", stopWatch.ElapsedMilliseconds));

stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < 10000; i++) {
int value;
int.TryParse(input, out value);
}
stopWatch.Stop();
Debug.WriteLine(string.Format("Process time (2): {0}ms", stopWatch.ElapsedMilliseconds));

خروجی برای من:


Process time: 27950ms
Process time (2): 1ms

اصلا قابل مقایسه هست؟! البته موضوع 10000 تا اجرا نیست.حتی روی 1 دونه اجرا هم نتیجه قابل تامله:


Process time: 14ms
Process time (2): 0ms

علی متقی پور
جمعه 05 اردیبهشت 1393, 20:12 عصر
پلاس جان چقد روضه خوندی پسر

اینقد متاسف باش که ... :)

esafb52
جمعه 05 اردیبهشت 1393, 22:00 عصر
پلاس جان چقد روضه خوندی پسر

اینقد متاسف باش که ... :)
جواب شما رو به صورت درست و منطقی دادن !!پس شما هم به همین سیاق عمل کنین
فکر کنم شما روضه رو تو دانشگاهتون میخونین در ضمن از جناب plus تشکر میکنم بابت توضیح خوبشون که باعث میشه افراد مبتدی مثل ما نکات خوبی یاد بگیرن
موفق باشین