ورود

View Full Version : راهنمایی در مورد کد ذیل!



farzad7056
سه شنبه 01 اردیبهشت 1394, 19:36 عصر
سلام دوستان
یه چند روزی می شه برنامه نویسی جاوا رو شروع کردم بنابراین اگه اشکالم ابتداییه پوزش می خوام
این قطعه کدی که نوشتم اسم و فامیل و حقوق ماهیانه فرد رو دریافت می کنه و سپس اسم و فامیل و حقوق سالیانه رو نشون می ده!
منتها یه قسمت از کد رو هر چقد نگاه می کنم مشکلی نمی بینم برنامه درست بعد از این که از متد nextInt استفاده میکنه(سومین استفاده از next در برنامه) وقتی بعدش می خواد از متد nextLine استفاده کنه اون دستور رو رد می کنه!
من کد رو ترتیبش رو جابه جا کردم مشکل رفع شد یعنی اول nextLine ها رو وارد کردم بعد nextInt ها رو!
علت این امر چی می تونه باشه؟
دسته کد اولی کلاس employee
و دسته کد دوم حاوی تابع main
در ضمن من از jdk 7 hsj

//Employee.java

public class Employee
{
String name;
String family;
int mahane;

public Employee(String a, String b, int c)
{
name = a;
family = b;
if(c > 0)

mahane = c;
}

public String getName()
{
return name;
}

public String getFamily()
{
return family;
}

public int getMahane()
{
return mahane;
}

public int getAnnual()
{
int annual = 12 * mahane;
return annual;
}

public double getNewMahane()
{
double newMahane = mahane * 1.1;
return newMahane;
}

public double getNewAnnual()
{
double newAnnual = 12 * 1.1 * mahane;
return newAnnual;
}

}



//EmployeeTest.java
import java.util.Scanner;

public class EmployeeTest
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);

System.out.println("Name khod ra vared konid: ");
String nam1 = input.nextLine();

System.out.println("Familie khod ra vared konid: ");
String famil1 = input.nextLine();

System.out.println("hoghughe mahiane ra vared konid: ");
int mahiane1 = input.nextInt();

System.out.println("Name khod ra vared konid: ");
String nam2 = input.nextLine();

System.out.println("Familie khod ra vared konid: ");
String famil2 = input.nextLine();

System.out.println("hoghughe mahiane ra vared konid: ");
int mahiane2 = input.nextInt();

Employee employee1 = new Employee(nam1, famil1, mahiane1);
Employee employee2 = new Employee(nam2, famil2, mahiane2);


System.out.println("\tnam\t\tfamil\t\tmahane\t\tannual");

System.out.printf("1\t%s\t\t%s\t\t%d\t\t%d\n", employee1.getName(), employee1.getFamily(), employee1.getMahane(),employee1.getAnnual());

System.out.printf("2\t%s\t\t%s\t\t%d\t\t%d\n\n", employee2.getName(), employee2.getFamily(), employee2.getMahane(),employee2.getAnnual());

System.out.println("BAD AZ EMALE AFZAYESHE 10% HOGHUGH\n");

System.out.println("\tnam\t\tfamil\t\tmahane\t\tannual");

System.out.printf("1\t%s\t\t%s\t\t%.0f\t\t%.0f\n", employee1.getName(), employee1.getFamily(), employee1.getNewMahane(),employee1.getNewAnnual()) ;

System.out.printf("2\t%s\t\t%s\t\t%.0f\t\t%.0f\n", employee2.getName(), employee2.getFamily(), employee2.getNewMahane(),employee2.getNewAnnual()) ;
}
}

-سیّد-
سه شنبه 01 اردیبهشت 1394, 23:14 عصر
سلام دوستان
یه چند روزی می شه برنامه نویسی جاوا رو شروع کردم بنابراین اگه اشکالم ابتداییه پوزش می خوام

سلام
پوزش خواستن نداره! هر کسی یه روزی برنامه‌نویسی به هر زبونی رو شروع کرده و توی روزها و ماه‌های اول (شایدم سال‌های اول) خیلی اشکالات ابتدایی داشته.
این خیلی هم خوبه که شما به دنبال یادگیری هستید.



این قطعه کدی که نوشتم اسم و فامیل و حقوق ماهیانه فرد رو دریافت می کنه و سپس اسم و فامیل و حقوق سالیانه رو نشون می ده!
منتها یه قسمت از کد رو هر چقد نگاه می کنم مشکلی نمی بینم برنامه درست بعد از این که از متد nextInt استفاده میکنه(سومین استفاده از next در برنامه) وقتی بعدش می خواد از متد nextLine استفاده کنه اون دستور رو رد می کنه!
من کد رو ترتیبش رو جابه جا کردم مشکل رفع شد یعنی اول nextLine ها رو وارد کردم بعد nextInt ها رو!
علت این امر چی می تونه باشه؟

اگه بخوام خیلی خلاصه جواب بدم، می‌شه این:
http://stackoverflow.com/questions/13102045/skipping-nextline-after-use-next-nextint-or-other-nextfoo-methods
یعنی یا یه nextLine بلافاصله بعد از هر بار nextInt بذارید، یا این که از nextLine + parseInt استفاده کنید:

int mahiane1 = Integer.parseInt(input.nextLine());

که البته در صورت استفاده از parseInt، اگر کاربر عدد وارد نکنه، NumberFormatException پرتاب می‌شه.

حالا توضیحش:
نکته اینجاست که Scanner برای console و گرفتن ورودی از کاربر ساخته نشده، بلکه یه کلاس general هست برای خوندن داده از یه ورودی.
وقتی کاربر شما یه عدد وارد می‌کنه و enter می‌زنه، چیزی که توی بافر ورودی قرار می‌گیره، یه عدد هست، بعلاوه‌ی یه enter (یعنی کاراکتر n\ ). وقتی به Scanner می‌گید یه عدد از توی بافر بردار (nextInt)، خوب عدد رو برمی‌داره، ولی enter سر جاش می‌مونه. حالا وقتی می‌گید خط بعدی رو بخون (nextLine)، انقدر توی بافر می‌ره جلو، تا برسه به کاراکتر n\ ، و رشته‌ای که به دست میاد رو به عنوان خروجی به شما برمی‌گردونه. خوب در این مورد این رشته چیه؟ رشته‌ی خالی.
دلیل این قضیه همونطور که گفتم اینه که Scanner برای خوندن یه مشت دیتای اینطوری طراحی شده:

123 456 789 ...
شما اگه این مثالی که زدم رو شروع کنید با Scanner و nextInt خوندن، قشنگ یکی یکی به شما عددا رو برمی‌گردونه. و دقت کنید که اینجا خبری از کاراکتر n\ و nextLine نیست.

در نهایت چند تا اشکال ریز کلی توی برنامه‌تون هست (اگه طبق یه آموزش دارید جلو می‌رید، ممکنه این چیزایی که می‌گم رو جلوتر بهش اشاره کرده باشن. دونستن و رعایت اینهایی که می‌گم خیلی به آدم توی نوشتن کد خوب کمک می‌کنه):


public Employee(String a, String b, int c)

اینجا بهتره به جای استفاده از اسامی a و b و c، از اسامی واقعی خود متغیرها استفاده کنید، یعنی name و family و mahane. اون وقت برای مقداردهی، از this استفاده کنید:

this.name = name;

که یعنی متغیر name این شیء رو برابر متغیر name که به عنوان پارامتر داده شده قرار بده.


if(c > 0)
mahane = c;

این if که گذاشتید، else اش چی می‌شه؟ یعنی اگه مقدار پارامتری که به شما داده شده، کوچکتر یا مساوی صفر باشه، مقدار متغیر mahane چی می‌شه؟
با توجه به این که شما در این حالت مقداری بهش نمی‌دید، مقدارش می‌شه مقدار پیش‌فرض نوع int، که برابر صفر هست.
ولی خوبه که یا از else استفاده کنید، یا مقدار اولیه رو جلوی خود متغیر اونجایی که تعریف می‌کنید بنویسید:

int mahane = 0;

این کار به خوانایی کد و فهم منطقش خیلی کمک می‌کنه.


public double getNewAnnual()
{
double newAnnual = 12 * 1.1 * mahane;
return newAnnual;
}

اینجا شما منطق ضرب کردن حقوق در ۱.۱ رو توی ۲ تابع getNewMahane و getNewAnnual تکرار کردید. یعنی هم اونجا در ۱.۱ ضرب کردید، هم اینجا این کارو کردید. بهتر بود این کار یک جا انجام می‌شد:

public double getNewAnnual()
{
double newAnnual = 12 * getNewMahane();
return newAnnual;
}

این کار (که بهش refactor کردن کد می‌گن) کمک می‌کنه که یک منطق، در یک جا قرار بگیره. خوبی‌ای که داره اینه که اگه پس فردا خواستید توی کد تغییر ایجاد کنید و مثلاً به جای ضرب کردن در ۱.۱، در ۱.۲ ضرب کنید، مجبور نباشید بگردید ببینید کجاها این کار رو داشتید انجام می‌دادید و همه رو تغییر بدید (که کاملاً ممکنه در صورت بزرگ شدن کد، از دستتون در بره و یه جا رو عوض نکنید، که می‌شه منشأ یه باگی که باید کلی دنبالش بگردید تا ریشه‌اش رو پیدا کنید).
یا مثلاً فرض کنید می‌خواین یه شرط بذارین: اگه یه نفر حقوقش از ۳ میلیون تومن بالاتر بود، به جای ضرب در ۱.۱، در ۱.۰۵ ضرب بشه. یا ایجاد هر تغییری در منطق.