6 minute read

בפוסט הקודם בסדרת הפוסטים הראשית, שעסק בחלוקה ושארית בשלמים, הצגתי תרגיל אופציונלי בו מכניסים מעין קלט למשתנים, אבל בלי באמת להשתמש בקלט. הנה הניסוח שוב:

כתבו תוכנית שבה אתן מכניסות למשתנה players מספר כלשהו המייצג כמות אנשים, ול-teams הכניסו מספר המייצג כמות קבוצות שיש לחלק אליהן את האנשים למשחק טריוויה, והדפיסו כמה אנשים צריכים להיות בכל קבוצה ומה שארית החלוקה. שנו את המספרים והריצו שוב וראו את התוצאה משתנה. בהמשך נלמד איך לקבל קלט מהמשתמש במקום לשנות את המספרים הכתובים בתוכנה.

קודם כל, הנה הפתרון:

כאן אפשר להריץ קוד!

כאן תוכלו להריץ קוד ממש בדפדפן שלכן. מומלץ להשתמש בסביבת עבודה על המחשב במקום (IntelliJ IDEA, Visual Studio Code ודומיהם) במידה ויש - האופציה הזו עדיפה רק למי שאין לה סביבת עבודה מותקנת.

הבעיה היא, כמו שכתבתי, שאנחנו לא מקבלים קלט מהמשתמש. דמיינו שהיו מנסים למכור לכן “מחשבון” שיכול לחשב את שארית החלוקה של 25 ב-4. יש למחשבון שני כפתורים - כפתור הפעלה וכפתור כיבוי. כאשר מפעילים את הכפתור, המחשבון באמת עושה עבודה חישובית כדי לחשב את שארית החלוקה, במקום שהוא סתם זוכר את זה - הוא תמיד חושב לעשירית שניה, ומציג $1$ על המסך עד שלוחצים על כפתור הכיבוי. בבירור, זה לא מחשבון ולא הייתן משלמות אפילו חמש אגורות בשביל זה, אפילו אם המטבע של חמש אגורות עדיין היה קיים.

לא כל תוכנה צריכה קלט מהמשתמש. דמיינו למשל תוכנה שכאשר מפעילים אותה, מגרילה מספר בין 1 ל-6 כמו קוביית משחק, מציגה את התוצאה, וזהו. תוצאת הריצה יכולה להיות שונה בין ריצות, כי היא משתמשת במנגנונים שנועדים לדמות אקראיות (למי שמעוניינת לקרוא עוד, המונח הרלוונטי הוא Pseudorandom number generator). אמנם לא למדנו עדיין את הדברים הרלוונטיים ב-Java לזה (אבל אנחנו לא רחוקים מזה), אבל רק בשביל להוכיח שזה אפשרי, הנה לכן הקוד אם אתן רוצות להריץ אותו (אגב, למי שעוד לא נתקלה במילה die בהקשר הזה, לא, אני לא אומר לכן למות, זו צורת היחיד של dice, המילה האנגלית ל”קוביות”):

כאן אפשר להריץ קוד!

כאן תוכלו להריץ קוד ממש בדפדפן שלכן. מומלץ להשתמש בסביבת עבודה על המחשב במקום (IntelliJ IDEA, Visual Studio Code ודומיהם) במידה ויש - האופציה הזו עדיפה רק למי שאין לה סביבת עבודה מותקנת.

ובכל זאת, סביר שנצטרך קלט בהרבה תוכנות. כשנגיע לתכנות רובוט, הקלט שלנו יהיה מהנהגות, בצורה של ג’וסטיקים או שלטי XBox, בצורה של בחירת אפשרויות ממסך בשם SmartDashboard או Shuffleboard (או אלטרנטיבה אחרת), בצורה של חיישנים (אני לא אכנס לשאלה הפילוסופית של האם זו אותה קטגוריה של קלט), בצורה של מידע מהמערכת שמנהלת את התחרות (FMS), וייתכן שאני שוכח עוד אופציות. אבל בינתיים, נהיה במודל של קלט בטרמינל, ה”צא’ט עם המחשב” שבו אנחנו גם שולחים פלט למשתמש עם System.out.

הדבר הראשון שנצטרך לשנות בתוכנה שלנו כדי להשתמש בקלט הוא להכניס את השורה import java.util.Scanner; בין הצהרת ה-package שלנו לבין השורה בה אנחנו מתחילים את ה-class. שורה זו מאפשרת לקובץ הנוכחי להשתמש ב-Scanner המוגדר בחבילה java.util. לאחר מכן נצטרך ליצור משתנה מסוג Scanner ולהשים לו ערך בצורה מיוחדת שעוד לא ראינו:

package your.package.name;

import java.util.Scanner;

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

אלו מכן שמשתמשות ב-JDoodle, העורך הקטן שאני מציג בו אפשרות להריץ קוד כאן בדפדפן - אם תרצו להמשיך להשתמש בו עם Scanner תצטרכו להפעיל את interactive mode, אבל באמת שאם אתן קוראות את זה על המחשב שלכן, הגיע הזמן להתרגל להשתמש ב-IDE על המחשב שלכן. זו הסיבה שהקוד הזה למשל לא מוצג ב-JDoodle (וגם, זה מנפח את הגודל של הדף).

בחרתי לקרוא למשתנה בשם input, אבל אפשר גם לקרוא לו scanner או כל שם משמעותי אחר (ולגבי Scanner אני מוכן גם להיות סלחן לגבי הכלל לגבי שמות משמעותיים - לקרוא לו s זה בסדר כל עוד התוכנית קצרה יחסית, ואני אומר את זה כי גם אני עושה את זה לעתים קרובות. עדיין, השם צריך להיות lowerCamelCase!).

אז מהו Scanner, ומה הדבר המוזר שהכנסנו שם?

Scanner היא טיפוס

קודם כל, Scanner היא סוג של טיפוס (כאשר “טיפוס” הוא הצורה שאנחנו מצמידים לכל משתנה) - ראו תזכורת על טיפוסים כאן. בפוסט בו דיברתי על טיפוסים, היה חלק ספציפי בו ציינתי כמה סוגי משתנים טיפוסיים ב-Java, בואו נראה את הטבלה הזו שוב:

שם הטיפוס משמעות ערכים אפשריים הערות
int מספרים שלמים 0, -1, 5, 4319  
double מספרים עשרוניים 0.0, -0.1,-9876.7, 123.54 שימו לב שגם כשהמספר שלם אני כותב אותו עם “נקודה 0” כדי להראות שהוא ב”צורת” double ולא ב”צורת” int. למספר 0.0 יש אותו ערך כמו ל-0 אבל “צורה” שונה.
char תו (אחד) של טקסט 'a', 'A', ' ', '+', 'א', 'α', 'ﷺ', 'ﭏ',’'🗾' שימו לב שאני מייצג כל תו מוקף בגרש יחיד משני הצדדים
boolean ערך אמת – “כן”/”לא” true, false  
long מספרים שלמים (בטווח יותר גדול) 0L, 1234L, 5534023222112865483L, -5270498306774157604L שימו לב שאני מסיים את המספר ב-L כדי להבדיל אותו מ-int. כמו ההבדל בין int ל-double, למספר 1L יש אותו ערך כמו ל-1 אבל “צורה” שונה.
String טקסט – רצף של תווים “”, “Hello world” שימו לב שהטקסט מוקף במרכאות משני הצדדים (אין להתבלבל בין מרכאות - מה שנקרא באנגלית double quotes, לבין גרשיים, מה שנקרא באנגלית single quotes)

כל הטיפוסים כאן חוץ מ-String הם מה שנקרא ב-Java טיפוס פרימיטיבי, ויש רק כמה מהם (אלו המופיעים כאן הם כמעט תמיד היחידיים שרלוונטיים לרוב מתכנתי Java), והם מייצגים את הדברים הפשוטים ביותר שניתן לייצג ב-Java. שימו לב שגם כותבים אותם באותיות קטנות. לעומת זאת, String למשל היא מחלקה - היא סוג נתונים יותר מורכב והערכים בתוכה הם אובייקטים. על אובייקטים באופן כללי ובמה הם שונים מפרימיטיביים נדבר בשלב יותר מאוחר.

לבינתיים, אנחנו צריכים לדעת רק שני דברים על אובייקטים - איך יוצרים כאלה, ובהינתן אובייקט, איך משתמשים בו.

נתחיל בשאלה הראשונה - איך יוצרים אובייקטים? במקרה של String, התשובה מופיעה בטבלה - בעזרת מרכאות. אבל String זה המקרה החריג (למי שמעניין אותה לקרוא מעבר - המילה הרלוונטית היא Literal - מחרוזת היא טיפוס האובייקט היחיד ב-Java שאפשר ליצור בעזרת ליטרל). את שאר סוגי האובייקטים יוצרים, בדרך כלל, בעזרת המילה new שאת משמעותה נלמד בהמשך. לבינתיים, עליכן, בחריקת שיניים מסוימת, לקבל את זה שאני “מנחית” עליכן שבמקרה של Scanner, שהוא טיפוס האובייקט היחיד חוץ מ-String שמעניין אותנו עד כה, יוצרים אותו עם:

new Scanner(System.in)

לשאלה השניה - בהינתן אובייקט מסוג Scanner, איך משתמשים בו? במשתנים עם פרימיטיביים, למשל int, משתמשים בפעולות - כפל, חיבור, חילוק, חיסור, הוצאת שארית. ובאובייקטים הפעולות מוגדרות על ידי שימוש בסימן הנקודה (.). ל-Scanner יש פעולות שונות שמאפשרות לקבל קלט מהמשתמש, מביניהם רק שלושת הבאים מעניינים אותנו:

פעולה מטרה
.nextInt() מקבלת מהמשתמש מספר שלם כקלט
.nextDouble() מקבלת מהמשתמש מספר עשרוני כקלט (המשתמש רשאי להכניס גם בפורמט של שלם, כלומר אם המשתמש מקליד 19, נקבל 19.0)
.nextLine() מקבלת מהמשתמש מחרוזת עד ה-Enter

בשלושת המקרים, כאשר נבצע את הפעולה, התוכנית תחכה שהמשתמש יקליד משהו וילחץ Enter. במקרה של nextInt ו-nextDouble, אם מה שהמשתמש הכניס לא תקין, למשל אם הוא אותיות במקום ספרות, תקרה שגיאה בזמן ריצה והתוכנית תקרוס בנקודה זו ולא תמשיך.

נסי את הקוד הבא, שהוא הקוד שכתבנו קודם, רק עם Scanner (הוספנו גם הוראות למשתמש לפני פעולות הקליטה מה-Scanner, כדי שהמשתמש יבין מה מצופה ממנו ולא רק יביט מול מסך המחכה לו)

כאן אפשר להריץ קוד!

כאן תוכלו להריץ קוד ממש בדפדפן שלכן. מומלץ להשתמש בסביבת עבודה על המחשב במקום (IntelliJ IDEA, Visual Studio Code ודומיהם) במידה ויש - האופציה הזו עדיפה רק למי שאין לה סביבת עבודה מותקנת.

כדי להריץ עם קלט בעזרת Scanner, ניתן להכניס מראש את הקלט במקום שבו כתוב STDIN Input או לסמן interactive mode כדי להכניס קלט בזמן ריצה כמו בצורה ה"רגילה".

נסי להריץ את הקוד הבא, לשנות אותו ולשחק איתו באופן כללי.

נקודות עיקריות

  • כדי לקבל קלט מהמשתמש אנחנו צריכות את המחלקה Scanner
  • אנחנו צריכות לעשות לה import עם השורה import java.util.Scanner;
  • אנחנו מגדירות משתנה מסוג Scanner ומבצעות השמה עם הביטוי הלא מוסבר לבינתיים new Scanner(System.in)
  • אנחנו מקבלות קלט דרך ה-Scanner בעזרת .nextInt(), .nextDouble() ו-.nextLine()

Comments