ورود

View Full Version : مبتدی: چند سوال درباره خطا گیری



Raizex
شنبه 27 شهریور 1395, 21:00 عصر
سلام دوستان عزیز , من دارم زبان برنامه نویسی جاوا رو یاد میگیریم , چند تا سوال برام پیش امده

کلاس مورد نظر اینه

import java.util.Scanner;

public class main {

public static void main(String[] args) {

System.out.println("Enter Your Age ?");

Scanner sc = new Scanner(System.in);

float age = 0;
try {
age = sc.nextFloat();
} catch (Exception e) {

System.out.println("Give me a Num !");;
}
if(age<11 && age>0)
{
System.out.println("You are Kid");
}
else if(age>=11 && age<=20)
{
System.out.println("You are Teen");
}
else if(age>=20 && age<=40)
{
System.out.println("You are Young");
}
else if(age>40 && age<=60)
{
System.out.println("You are Mid-Age");
}
else if(age>60 && age<=80)
{
System.out.println("You are Old-Age");
}
else if(age>80 )
{
System.out.println("PLZ ......");
}
main(null);
}

}


سوال 1 : چرا موقعی که float age رو مقدار دهی نمی کنم برنامه به خطا میخوره ,


float age;
try {
age = sc.nextFloat();
} catch (Exception e) {

System.out.println("Give me a Num !");;

}



و تمامی age که در شرط های پایین نوشته شده خطا گرفته میشه و میگه باید مقدار دهی اولیه گرفته بشه و وقتی مشاوی صفر می کنم float age رو برنامه کار میکنه

چرا صفر , بعضی اموزش ها حتی منفی یک هم میزارن ؟ چرا برنامه بدون مقدار دهی اولیه به خطا می خوره , lمن که می خوام کاربر بهم سن رو بگه ؟ میشه یکی کامل توضیح بده ؟

Raizex
شنبه 27 شهریور 1395, 21:15 عصر
از یه روش دیگه هم برای اینگونه خطا گیری استفاده میکنند

import java.util.Scanner;

public class Main3 {


public static void main(String[] args) {

System.out.println("Enter Your Age ?");

Scanner sc = new Scanner(System.in);

int age =0;
String s = sc.next();
try {
age = Integer.parseInt(s);
} catch (Exception e) {

System.out.println("Give me a Num !");;

}

if(age<11 && age>0)
{
System.out.println("You are Kid");
}
else if(age>=11 && age<=20)
{
System.out.println("You are Teen");
}
else if(age>=20 && age<=40)
{
System.out.println("You are Young");
}
else if(age>40 && age<=60)
{
System.out.println("You are Mid-Age");
}
else if(age>60 && age<=80)
{
System.out.println("You are Old-Age");
}
else if(age>80 )
{
System.out.println("PLZ ......");
}

main(null);

}


}




توی این قسمت

این
String s = sc.next();
و
age = Integer.parseInt(s);
رو میشه توضیح بدید ؟

poker97
یک شنبه 28 شهریور 1395, 00:10 صبح
سلام دوستان عزیز , من دارم زبان برنامه نویسی جاوا رو یاد میگیریم , چند تا سوال برام پیش امده

کلاس مورد نظر اینه

import java.util.Scanner;

public class main {

public static void main(String[] args) {

System.out.println("Enter Your Age ?");

Scanner sc = new Scanner(System.in);

float age = 0;
try {
age = sc.nextFloat();
} catch (Exception e) {

System.out.println("Give me a Num !");;
}
if(age<11 && age>0)
{
System.out.println("You are Kid");
}
else if(age>=11 && age<=20)
{
System.out.println("You are Teen");
}
else if(age>=20 && age<=40)
{
System.out.println("You are Young");
}
else if(age>40 && age<=60)
{
System.out.println("You are Mid-Age");
}
else if(age>60 && age<=80)
{
System.out.println("You are Old-Age");
}
else if(age>80 )
{
System.out.println("PLZ ......");
}
main(null);
}

}


سوال 1 : چرا موقعی که float age رو مقدار دهی نمی کنم برنامه به خطا میخوره ,


float age;
try {
age = sc.nextFloat();
} catch (Exception e) {

System.out.println("Give me a Num !");;

}



و تمامی age که در شرط های پایین نوشته شده خطا گرفته میشه و میگه باید مقدار دهی اولیه گرفته بشه و وقتی مشاوی صفر می کنم float age رو برنامه کار میکنه

چرا صفر , بعضی اموزش ها حتی منفی یک هم میزارن ؟ چرا برنامه بدون مقدار دهی اولیه به خطا می خوره , lمن که می خوام کاربر بهم سن رو بگه ؟ میشه یکی کامل توضیح بده ؟

به خاطر try catch چون شما گرفتن ورودی از کابر تو دستورات try نوشتین ممکنه مثلا کاربر int وارد کنه در حالی که شما float میخواستین برای همین برنامه catch میشه و متغیر age بدونه مقدار میمونه برای همین هم به شما اررور میده

vahid-p
دوشنبه 29 شهریور 1395, 00:57 صبح
به خاطر try catch چون شما گرفتن ورودی از کابر تو دستورات try نوشتین ممکنه مثلا کاربر int وارد کنه در حالی که شما float میخواستین برای همین برنامه catch میشه و متغیر age بدونه مقدار میمونه برای همین هم به شما اررور میده
به این دلیل نیست. مقدار عددی به float تبدیل میشه وقتی از nextFloat استفاده میکنیم چه عدد ممیز دار باشه چه بدون ممیز.

بقیش فردا مینویسم.

Raizex
دوشنبه 05 مهر 1395, 00:13 صبح
به این دلیل نیست. مقدار عددی به float تبدیل میشه وقتی از nextFloat استفاده میکنیم چه عدد ممیز دار باشه چه بدون ممیز.

بقیش فردا مینویسم.

همچنان منتظرم :لبخندساده:

vahid-p
دوشنبه 05 مهر 1395, 17:42 عصر
ببخشید بابت اینکه فراموش کردم!
ولی عجب صبری شما داری. زودتر یادآوری میکردی خب


چرا صفر , بعضی اموزش ها حتی منفی یک هم میزارن ؟ چرا برنامه بدون مقدار دهی اولیه به خطا می خوره , lمن که می خوام کاربر بهم سن رو بگه ؟ میشه یکی کامل توضیح بده
اینکه چه مقداری برای مقدار اولیه مشخص کنید قانون خاصی نداره. بسته به منطق برنامتون میتونید 0، -1، 1000 یا هر عددی بذارید. اما از اونجایی که در زبان C که Exception Handler وجود نداره، رسم بر این بوده مثلا خطا رو با مقدار -1 در خیلی از تابع ها مشخص می کردن. شاید برای همین هم -1 رو میذارن تا اگر عدد تغییر نکرد پس از try-catch مقدار -1 باشه و بدونن این مقداری نداشته. (البته در صورتی که -1 یکی از مقادیر ورودی مجاز نباشه)
از طرفی در جاوا هر متغیری قبل از استفاده باید حداقل یکبار مقداردهی بشه. حتی متغیری از نوع یک کلاس، اگر حتی نخواهیم مقداردهی کنیم ولی استفاده کنیم، لااقل باید به صورت صریح null رو به اون assign کنیم. اینکار برای جلوگیری از خطاهایی میشه که در زبان های دیگه به وفور ایجاد میشه. مثلا در زبان C اگر یک مقدار رو تعریف کنید و مقدار اولیه ندید، خودش یک مقدار خواهد گرفت (برابر مقداری که در اون خونه حافظه از قبل وجود داشته) و در صورتی که چنین عددی در برنامه ما معنی نداشته و در هر بار اجرا ممکنه عدد های مختلفی باشه. لذا مقدار دهی اولیه چه به صورت i=1 مثلا یا باید تابعی باشه که حتما یک مقدار بازگشتی داشته باشه مثلا i=f(x) که f(x) همیشه موفقیت آمیز باشه.
حتی اگر بخواهید در یک if ... else ... متغیر رو مقداردهی کنید و پس از اون استفاده کنید، باید در هر دو بدنه وجود داشته باشه تا کامپایلر مطمئن بشه این متغیر از هر مسیری که بره مقداردهی خواهد شد.
try-catch هم شبیه if...else هست. چون لزوما هر تابعی در try موفقیت آمیز نیست و اگر خطا رخ بده ادامه خطها و اون خط در try اجرا نمیشه. لذا اگر برنامه در nextFloat با خطا روبرو شد (مثلا انتظار یک عدد داره چه صحیح چه ممیز دار، ولی حروف بگیره) این try شکسته میشه و بدنه catch اجرا میشه و پس از اون ادامه برنامه در خارج از try-catch اجرا میشه.
در نتیجه هر چند شما میخواستید با nextFloat متغیر age رو مقداردهی اولیه کنید، ولی ممکنه این خط موفقیت آمیز نباشه و assignment (مقداردهی) انجام نشه

Raizex
دوشنبه 05 مهر 1395, 18:30 عصر
ببخشید بابت اینکه فراموش کردم!
ولی عجب صبری شما داری. زودتر یادآوری میکردی خب


اینکه چه مقداری برای مقدار اولیه مشخص کنید قانون خاصی نداره. بسته به منطق برنامتون میتونید 0، -1، 1000 یا هر عددی بذارید. اما از اونجایی که در زبان C که Exception Handler وجود نداره، رسم بر این بوده مثلا خطا رو با مقدار -1 در خیلی از تابع ها مشخص می کردن. شاید برای همین هم -1 رو میذارن تا اگر عدد تغییر نکرد پس از try-catch مقدار -1 باشه و بدونن این مقداری نداشته. (البته در صورتی که -1 یکی از مقادیر ورودی مجاز نباشه)
از طرفی در جاوا هر متغیری قبل از استفاده باید حداقل یکبار مقداردهی بشه. حتی متغیری از نوع یک کلاس، اگر حتی نخواهیم مقداردهی کنیم ولی استفاده کنیم، لااقل باید به صورت صریح null رو به اون assign کنیم. اینکار برای جلوگیری از خطاهایی میشه که در زبان های دیگه به وفور ایجاد میشه. مثلا در زبان C اگر یک مقدار رو تعریف کنید و مقدار اولیه ندید، خودش یک مقدار خواهد گرفت (برابر مقداری که در اون خونه حافظه از قبل وجود داشته) و در صورتی که چنین عددی در برنامه ما معنی نداشته و در هر بار اجرا ممکنه عدد های مختلفی باشه. لذا مقدار دهی اولیه چه به صورت i=1 مثلا یا باید تابعی باشه که حتما یک مقدار بازگشتی داشته باشه مثلا i=f(x) که f(x) همیشه موفقیت آمیز باشه.
حتی اگر بخواهید در یک if ... else ... متغیر رو مقداردهی کنید و پس از اون استفاده کنید، باید در هر دو بدنه وجود داشته باشه تا کامپایلر مطمئن بشه این متغیر از هر مسیری که بره مقداردهی خواهد شد.
try-catch هم شبیه if...else هست. چون لزوما هر تابعی در try موفقیت آمیز نیست و اگر خطا رخ بده ادامه خطها و اون خط در try اجرا نمیشه. لذا اگر برنامه در nextFloat با خطا روبرو شد (مثلا انتظار یک عدد داره چه صحیح چه ممیز دار، ولی حروف بگیره) این try شکسته میشه و بدنه catch اجرا میشه و پس از اون ادامه برنامه در خارج از try-catch اجرا میشه.
در نتیجه هر چند شما میخواستید با nextFloat متغیر age رو مقداردهی اولیه کنید، ولی ممکنه این خط موفقیت آمیز نباشه و assignment (مقداردهی) انجام نشه

ممنون که بسیار کامل و به زبان ساده توضیح داد

من یه عادتی دارم تا مطلبی رو کامل متوجه نشوم , مغزم تا حد انفجار داغ میشه , زیاد سایت های مختلف رو چک کردم , همشون به مطالبی که شما گفتید اشاره کرده بودند ولی مثل شما قابل درک برای اماتور ها توضیح نداده بودند :قلب:

میشه درباره پست دوم هم یه اطلاعاتی بدید؟

درباره صبر هم , تو فروم های برنامه نویسی که سوال میپرسی خیلی کم پیدا میشه جواب بدند , گفتم حالت اجبار نشه , کلا جواب داده نشه , من انگلیسی خوبه ولی تو قسمت برنامه نویسی نمیتونم مفهوم سوالامو تو سایت های خارجی توضیح بدم , حتی وقتی کسی هم که جواب میده , کامل درک نمی کنم مفهومشو

vahid-p
دوشنبه 05 مهر 1395, 21:01 عصر
روش دومی که گفتید هم تفاوتی نداره. (به جز اینکه اولی float بود و دومی int)
در روش اول شما مستقیما از تابع nextFloat میخواید که از ورودی (که همیشه یک جریان کاراکتری هست) یک عدد ممیزدار بهتون بده، در روش دوم شما از جریان کاراکتری یک رشته ساختید و به متغیر s دادید، بعد اون متغیر s رو با استفاده از تابع parseInt به عدد صحیح (Integer) تبدیل کردید.
حتما داکیومنت توابع رو بخونید. مثلا
scanner.next() اگر بخونید در خروجی یک رشته میده که انتهای اون رشته رو کاراکتر space یا خط بعد تشکیل میده. برادرش nextLine هست که یک خط رو میگیره و انتهاش رو خط بعد مشخص میکنه و کاراکتر space رو هم در رشته قرار میده.
parseInt تبدیل یک رشته که متشکل از کاراکترهای معادل عدد ('0','1','2',...) هستند رو به یک متغیر از نوع int با اون مقداری که مدنظرمون بوده تبدیل میکنه. خب اگر به جز کاراکتر عددی چیز دیگه ای بود exception میده و بدنه catch اجرا میشه.


دلیل اینکه چرا parseInt داریم و nextInt برای تمام موارد کفایت نمیکنه اینه چون همیشه ما با یک جریان (Stream) سر و کار نداریم. Scanner بر روی یک Stream کار میکنه ولی گاهی اوقات ما یک رشته رو داریم (منشاء اون مهم نیست) و میخواهیم به عدد تبدیل کنیم. تابع parseInt یا parseFloat یا هر چیزی شبیه این، اینکار رو برامون انجام میده.
Scanner کلاس مفیدی هست و توابع nextX که X میتونه خیلی چیزها باشه، برای کار با کیبورد یا فایل یا ... که به صورت یک جریان کاراکتری ورودی (InputStream) بشه تبدیلش کرد استفاده فراوانی داره. چون کارکردن باهاش راحته و ابزارهای خوبی رو با دقت و عملکرد خوب در اختیارمون قرار میده.

یه نکته: هر چند یک رشته رو هم میتونیم به صورت یک جریان کاراکتری در نظر بگیریم، ولی عملا وقتی رشتمون مشخصه، نیازی به استفاده از این سری توابع نیست. جریان کاراکتری معمولا وقتی استفاده میشه که ما نمیدونیم چه تعداد کاراکتر خواهیم داشت و بر اساس چیزی که تا اون لحظه بهمون رسیده تصمیم گیری میکنیم. مثلا ما نمیدونیم اندازه یک جریان چقدره و ممکنه بی نهایت باشه، ولی رشته از اولش میدونیم متشکل از چند کاراکتره.

یه نکته دیگه: اگر آرایه ای از عددها (int,float,...) درست کنی، مقدار اولیه هر عنصر آرایه به صورت پیشفرض 0 خواهد بود. پس نیازی به مقدار دهی اولیه با مقدار صفر نیست.
int list[]=new int[10];