דילוג לתוכן המרכזי

מתכונת 1 במדעי המחשב - תכנות באינטרנט 899372

נבחנים אקסטרניים · שאלון 899372 · 9 שאלות · 2 שעות · פתרון מלא לכל סעיף

מבחן מתכונת במדעי המחשב, תכנות באינטרנט, במבנה של בחינת הבגרות. כל שאלה בו בנויה כמו שאלה מבגרות אחרת. לכל סעיף יש תשובה ופתרון מלא, וכל קוד מופיע ב-Java וב-C#. פתרו בזמן של הבחינה, ורק אחר כך פתחו את הפתרונות.

הוראות הבחינה

א. משך הבחינה: שעתיים.

ב. מבנה השאלון ומפתח הערכה: בשאלון זה שלושה פרקים.

פרק ראשון — (10x3) — 30 נקודות
פרק שני — (20x2)+(10x1) — 50 נקודות
פרק שלישי — (20x1) — 20 נקודות
סך הכול — 100 נקודות

ג. חומר עזר מותר בשימוש: כל חומר עזר, חוץ ממחשבון שיש בו אפשרות תכנות.

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

השאלות בשאלון זה מנוסחות בלשון רבים, אף על פי כן על כל תלמידה וכל תלמיד להשיב עליהן באופן אישי.

בהצלחה!

פרק ראשון

ענו על שלוש השאלות 3-1 (לכל שאלה – 10 נקודות).

שאלה 1 · מהי JavaScript

בבניית אתרים משתמשים לעיתים קרובות בשפה JavaScript. מהי JavaScript?
העתיקו למחברת הבחינה את התשובה הנכונה מבין האפשרויות א–ד שלפניכם.

א. שפת שאילתות לשליפת נתונים מטבלאות במסד הנתונים.
ב. תגית HTML שבעזרתה מוסיפים תמונה לדף.
ג. אובייקט בשרת השומר מידע עבור משתמש מסוים.
ד. שפת תכנות שהקוד שלה רץ בדפדפן ומאפשר לדף להגיב לפעולות המשתמש.

העתיקו למחברת הבחינה את התשובה הנכונה מבין האפשרויות א–ד.

(10 נקודות)
◂ פתרון מלא לשאלה 1

פתרון

תשובה

ד. שפת תכנות שהקוד שלה רץ בדפדפן ומאפשר לדף להגיב לפעולות המשתמש.

מה נדרש: לבחור את ההגדרה הנכונה של JavaScript.

רעיון: JavaScript היא שפת תכנות של צד הלקוח: הקוד נשלח לדפדפן יחד עם דף ה-HTML (בתוך תגית <script>) והדפדפן מריץ אותו. בעזרתה הדף מגיב לפעולות המשתמש – לחיצה על כפתור, הקלדה בתיבה – בלי לפנות שוב לשרת. לדוגמה:

HTML
<button onclick="alert('שלום!')">לחצו כאן</button>

בלחיצה על הכפתור הדפדפן מריץ את הקוד alert('שלום!') ומקפיץ הודעה.

פתרון – מעבר על האפשרויות:

•א. "שפת שאילתות לשליפת נתונים מטבלאות" – זו SQL. לא נכון.
•ב. "תגית HTML שמוסיפה תמונה" – זו התגית <img>. לא נכון.
•ג. "אובייקט בשרת השומר מידע עבור משתמש מסוים" – זה Session. לא נכון.
•ד. "שפת תכנות שהקוד שלה רץ בדפדפן ומאפשר לדף להגיב לפעולות המשתמש" – נכון.

תשובה: ד.

בדיקה: כל אחת מהאפשרויות א–ג מתארת מושג אחר מהחומר (SQL, תגית <img>, Session); רק ד' מתארת שפת תכנות שרצה בצד הלקוח.

טעות נפוצה: לבלבל בין JavaScript לבין Java – אלה שתי שפות שונות לגמרי, ו-JavaScript היא זו שרצה בדפדפן.

שאלה 2 · מהו IsPostBack

מהו IsPostBack?

(1) פעולה המחזירה את המשתמש לדף הקודם שבו ביקר.

(2) משתנה Session שהשרת יוצר כאשר המשתמש שולח טופס.

(3) פקודה בצד הלקוח השולחת את הטופס לשרת.

(4) תכונה של הדף בצד השרת שערכה true כאשר הדף נטען מחדש בעקבות שליחת טופס מאותו דף, ו-false כאשר הדף נטען בפעם הראשונה.

מהו IsPostBack?

(10 נקודות)
◂ פתרון מלא לשאלה 2

פתרון

תשובה

(4)

מה נדרש – לבחור את ההגדרה הנכונה של IsPostBack.

רעיון – הפעולה Page_Load בצד השרת רצה בכל טעינה של הדף: גם בכניסה הראשונה וגם כשהמשתמש לוחץ על כפתור שליחה בטופס שנשלח לאותו דף ("postback"). IsPostBack מאפשר להבחין בין שני המצבים.

פתרון

IsPostBack היא תכונה (property) של הדף בצד השרת, מסוג bool:

•false – הדף נטען בפעם הראשונה (המשתמש הגיע אליו מקישור או מהקלדת כתובת).
•true – הדף נטען שוב כי המשתמש שלח טופס מאותו הדף.

שימוש טיפוסי:

C#
if (!IsPostBack)
{
    // פעולות שיש לבצע רק בכניסה הראשונה, למשל מילוי ערכי ברירת מחדל
}
תשובהנכון/לא נכוןלמה
(1)✘חזרה לדף קודם היא פעולה של הדפדפן (כפתור "חזרה"), לא IsPostBack.
(2)✘IsPostBack אינו משתנה Session; זו תכונה של הדף בבקשה הנוכחית.
(3)✘IsPostBack נבדק בצד השרת, והוא אינו שולח דבר.
(4)✔ נכוןזו ההגדרה.

התשובה: (4).

בדיקה – דף שבו if (!IsPostBack) קובע בתיבת העיר ערך ברירת מחדל Haifa. בכניסה הראשונה (IsPostBack = false) נקבע Haifa; המשתמש הקליד Eilat ושלח, ובטעינה השנייה (IsPostBack = true) הקוד לא דרס את הערך, ונשאר Eilat.

טעות נפוצה: לשכוח את הבדיקה if (!IsPostBack) – אז ערכי ברירת המחדל נקבעים מחדש בכל שליחה ודורסים את מה שהמשתמש הקליד.

שאלה 3 · פלט של Response.Write עם כותרות

לפניכם הפונקציה Steps, הכתובה בצד שרת.

C#
public void Steps (int num) {
      string str = "";
      for (int i = 1; i <= num; i++) {
         str += "<h" + i + ">";
         for (int j = 1; j <= i; j++)
            str += "*";
         str += "</h" + i + ">";
         if (i % 2 == 0)
            str += "<hr>";
      }
      Response.Write(str);
}

כתבו במחברת הבחינה את הפלט שיוצג בדפדפן לאחר זימון הפונקציה Steps(4).

כתבו במחברת הבחינה את הפלט שיוצג בדפדפן לאחר זימון הפונקציה Steps(4).

(10 נקודות)
◂ פתרון מלא לשאלה 3

פתרון

תשובה

ארבע שורות כוכביות מודגשות שגודלן הולך וקטן: * (כותרת h1, הגדולה ביותר), (h2), קו אופקי, * (h3), (h4), קו אופקי.

מה נדרש: מה יראה המשתמש בדפדפן לאחר Steps(4).

רעיון: בכל סיבוב i (מ-1 עד 4) נבנית כותרת <hi> – כלומר <h1>, <h2>, <h3>, <h4> – והלולאה הפנימית מכניסה לתוכה i כוכביות. כותרות מוצגות מודגשות, כל אחת בשורה נפרדת, ו-h1 היא הגדולה ביותר; ככל שהמספר גדל הגופן קטן. אחרי כל i זוגי נוסף <hr> – קו אופקי לרוחב הדף.

פתרון – מעקב:

iהכוכביות (לולאת j)i % 2 == 0?מה נוסף
1*לא<h1>*</h1>
2כן<h2>**</h2><hr>
3*לא<h3>***</h3>
4כן<h4>****</h4><hr>

המחרוזת שנשלחת לדפדפן:

HTML
<h1>*</h1><h2>**</h2><hr><h3>***</h3><h4>****</h4><hr>

הפלט שיוצג בדפדפן:

1.* – בגופן הגדול ביותר (h1), מודגש
2.** – קטן יותר (h2)
3.קו אופקי
4.*** – קטן יותר (h3)
5.**** – הקטן מבין הארבעה (h4)
6.קו אופקי

בדיקה: מספר הכוכביות עולה (1, 2, 3, 4) בזמן שגודל הגופן יורד (h1 → h4); שני קווים – אחרי i = 2 ואחרי i = 4.

טעות נפוצה: לחשוב שהשורה עם יותר כוכביות גדולה יותר – הגודל נקבע לפי מספר הכותרת, ו-h1 היא הגדולה. טעות נוספת: לשכוח את הקו שאחרי השורה האחרונה (גם 4 זוגי).

פרק שני

ענו על שלוש שאלות: על שאלה 4 (חובה – 10 נקודות) ועל שתיים מן השאלות 7-5 (לכל שאלה – 20 נקודות).

שאלה 4 · JavaScript – בדיקת קוד יציאה הפוך (השלמת קוד)

באתר של חדר בריחה מקוון יש שדה שבו השחקן מזין את קוד היציאה מהחדר:

HTML
<input type="text" maxlength="12" name="exitCode" id="exitCode" />

בכל חדר מוצגת לשחקן מחרוזת רמז (clue). קוד היציאה (answer) תקין אם הוא מחרוזת הרמז בסדר הפוך: התו הראשון של answer הוא התו האחרון של clue, התו השני של answer הוא התו הלפני אחרון של clue, וכן הלאה – עד שהתו האחרון של answer הוא התו הראשון של clue. בפרט, לשתי המחרוזות אותו אורך.

דוגמה:

clue = "LOCK7"

answer = "7KCOL"

הקוד תקין.

דוגמאות נוספות עבור clue = "LOCK7":

answer = "7KCOD" – הקוד שגוי (התו האחרון אינו L)

answer = "KCOL" – הקוד שגוי (חסר התו 7)

הפעולה isReverse שלפניכם מחזירה true אם answer הוא קוד יציאה תקין עבור clue, ו־false אחרת. בפעולה חסרים שישה ביטויים המסומנים במספרים (1)–(6).
כתבו במחברת הבחינה את המספרים (1)–(6) ואת הביטויים החסרים שכל מספר מייצג.

HTML
<script>
   function isReverse (clue, answer)
   {
      var i = 0;
      var j = answer.length - 1;
      // נסרוק את clue מתחילתה ואת answer מסופה
      while (_______(1)_______ && _______(2)_______)
      {
         // אם התווים במיקומים המתאימים אינם שווים – הקוד שגוי
         if (_______(3)_______)
            return false;

         // נתקדם בשתי המחרוזות
         _____(4)_____; // i
         _____(5)_____; // j
      }

      // אם באחת המחרוזות נשארו תווים שלא נבדקו – הקוד שגוי
      if (_______(6)_______)
         return false;

      return true;
   }
</script>

כתבו במחברת הבחינה את המספרים (1)–(6) ואת הביטויים החסרים שכל מספר מייצג.

(10 נקודות)
◂ פתרון מלא לשאלה 4

פתרון

תשובה

(1) i < clue.length
(2) j >= 0
(3) clue.charAt(i) != answer.charAt(j)
(4) i++
(5) j--
(6) i < clue.length || j >= 0

מה נדרש – להשלים שישה ביטויים בפעולה שבודקת אם answer הוא clue בסדר הפוך.

רעיון – משתמשים בשני אינדקסים שנעים בכיוונים מנוגדים:

•i עובר על clue מההתחלה (0, 1, 2, ...);
•j עובר על answer מהסוף (answer.length − 1, ..., 1, 0) – לכן הוא מאותחל ל-answer.length - 1.

בכל צעד משווים את התו ה-i ב-clue לתו ה-j ב-answer; אם הם שונים – הקוד שגוי. הלולאה נעצרת כשאחד האינדקסים יוצא מגבולות המחרוזת שלו. אם בסוף נשארו תווים שלא נבדקו באחת המחרוזות (i עדיין קטן מאורך clue, או j עדיין לא ירד מתחת ל־0) – האורכים שונים והקוד שגוי.

פתרון

מספרביטויהסבר
(1)i < clue.lengthלא הגענו לסוף clue
(2)j >= 0j עדיין בתוך answer (לא ירדנו מתחת למקום 0)
(3)clue.charAt(i) != answer.charAt(j)התווים במיקומים המתאימים שונים
(4)i++מתקדמים תו אחד קדימה ב-clue
(5)j--מתקדמים תו אחד אחורה ב-answer
(6)i < clue.length || j >= 0נשארו תווים שלא נבדקו באחת המחרוזות

גם ביטויים שקולים מתקבלים, למשל j > -1 במקום j >= 0, i = i + 1 במקום i++ ו-j = j - 1 במקום j--.

הפעולה המלאה:

JavaScript
function isReverse (clue, answer)
{
   var i = 0;
   var j = answer.length - 1;
   // נסרוק את clue מתחילתה ואת answer מסופה
   while (i < clue.length && j >= 0)
   {
      // אם התווים במיקומים המתאימים אינם שווים – הקוד שגוי
      if (clue.charAt(i) != answer.charAt(j))
         return false;

      // נתקדם בשתי המחרוזות
      i++; // i
      j--; // j
   }

   // אם באחת המחרוזות נשארו תווים שלא נבדקו – הקוד שגוי
   if (i < clue.length || j >= 0)
      return false;

   return true;
}

בדיקה

מעקב עבור clue = "LOCK7", answer = "7KCOL" (שני האורכים 5):

ijclue.charAt(i)answer.charAt(j)שווים?
04LLכן
13OOכן
22CCכן
31KKכן
4077כן
5−1––הלולאה נעצרת

בסוף: 5 < 5 שקר ו--1 >= 0 שקר ⇐ התנאי (6) שקר ⇐ מוחזר true.

התוצאות:

•isReverse("LOCK7", "7KCOL") → true
•isReverse("LOCK7", "7KCOD") → false (כבר בהשוואה הראשונה: L מול D)
•isReverse("LOCK7", "KCOL") → false (ארבע ההשוואות מצליחות, אבל j יורד ל־−1 כש-i = 4 – נשאר תו ב-clue, ולכן (6) אמת)
•isReverse("LOCK7", "77KCOL") → false (חמש ההשוואות מצליחות, אבל כש-i מגיע ל־5 נשאר j = 0 – נשאר תו ב-answer, ולכן (6) אמת)
•בדיקה ממוחשבת מול ההגדרה ("answer שווה ל-clue הפוכה") על כל המחרוזות מעל {A,B,C}: clue עד אורך 4 ו-answer עד אורך 5 (44,044 זוגות) – הפעולה המושלמת נכונה בכל המקרים.

טעות נפוצה: לאתחל או לקדם את j כמו את i (j++), או לבדוק בסוף רק את אחד האינדקסים – אז מחרוזת קצרה או ארוכה מדי תתקבל כתקינה.

שאלה 5 · Session – סוג משלוח בחנות מקוונת

בחנות המקוונת ״ספורט פלוס״ קובעים לכל הזמנה את סוג המשלוח. לשם כך אנו משתמשים במספר משתני Session:

•Session["cartSum"]: מספר ממשי (double) המייצג את הסכום לתשלום בעגלת הקניות, בשקלים.
•Session["isClub"]: ערך בוליאני (bool) – true אם הלקוח הוא חבר מועדון, אחרת false.
•Session["delivery"]: מחרוזת המייצגת את סוג המשלוח ("free", "reduced", "standard").

בהתבסס על משתנים אלה, אנו מעדכנים את המשתנה delivery ומפנים את הלקוח לדף המתאים:

א. הזמנה שסכומה 400 ש״ח ומעלה תעודכן למשלוח free ותועבר לדף freeDelivery.aspx
ב. הזמנה של חבר מועדון שסכומה 150 ש״ח לפחות תעודכן למשלוח reduced ותועבר לדף clubDelivery.aspx
ג. שאר ההזמנות יעודכנו למשלוח standard ויועברו לדף delivery.aspx

כתבו קוד בצד השרת המתאים לדרישות.

כתבו קוד בצד השרת המתאים לדרישות.

(20 נקודות)
◂ פתרון מלא לשאלה 5

פתרון

תשובה

double cartSum = (double)Session["cartSum"]; bool isClub = (bool)Session["isClub"]; ואז: cartSum >= 400 ⇐ free + freeDelivery.aspx; אחרת isClub && cartSum >= 150 ⇐ reduced + clubDelivery.aspx; אחרת standard + delivery.aspx.

מה נדרש: קוד צד-שרת ב-C# שקורא את סכום העגלה ואת סטטוס המועדון מה-Session, מעדכן את Session["delivery"] ומפנה לדף המתאים.

רעיון:

1.ההמרה מ-object צריכה להתאים לטיפוס שנשמר: הסכום נשמר כ-double ⇐ (double)Session["cartSum"]; חבר מועדון נשמר כ-bool ⇐ (bool)Session["isClub"].

משתנה בוליאני אפשר לכתוב ישירות בתנאי: if (isClub && ...) (אין צורך ב-isClub == true).

2.המקרים נבדקים לפי הסדר במבנה if – else if – else: קודם המשלוח החינמי (לכל לקוח, חבר מועדון או לא), אחר כך המשלוח המוזל – רק אם גם הלקוח חבר מועדון וגם הסכום לפחות 150 ⇐ &&.
3.מעדכנים את Session["delivery"] לפני Response.Redirect.

פתרון – הקוד המלא בלשונית C#:

C#
protected void Page_Load(object sender, EventArgs e)
{
    double cartSum = (double)Session["cartSum"];
    bool isClub = (bool)Session["isClub"];

    if (cartSum >= 400)
    {
        Session["delivery"] = "free";
        Response.Redirect("freeDelivery.aspx");
    }
    else if (isClub && cartSum >= 150)
    {
        Session["delivery"] = "reduced";
        Response.Redirect("clubDelivery.aspx");
    }
    else
    {
        Session["delivery"] = "standard";
        Response.Redirect("delivery.aspx");
    }
}

בדיקה:

cartSumisClubdeliveryהפניה
520.5falsefreefreeDelivery.aspx
400truefreefreeDelivery.aspx
399.9truereducedclubDelivery.aspx
150truereducedclubDelivery.aspx
149.9truestandarddelivery.aspx
250falsestandarddelivery.aspx
0falsestandarddelivery.aspx

שימו לב לשורה 400/true: חבר מועדון עם 400 ש״ח מקבל free ולא reduced, כי התנאי הראשון נבדק קודם.

טעות נפוצה: להמיר את הסכום ל-(int) – אם נשמר בו double ההמרה נכשלת בזמן ריצה (וגם הסכום 149.9 היה נחתך); או להפוך את סדר התנאים, ואז חבר מועדון עם 500 ש״ח יקבל בטעות reduced.

הקוד המלא
C#
protected void Page_Load(object sender, EventArgs e)
{
    double cartSum = (double)Session["cartSum"];
    bool isClub = (bool)Session["isClub"];

    if (cartSum >= 400)
    {
        Session["delivery"] = "free";
        Response.Redirect("freeDelivery.aspx");
    }
    else if (isClub && cartSum >= 150)
    {
        Session["delivery"] = "reduced";
        Response.Redirect("clubDelivery.aspx");
    }
    else
    {
        Session["delivery"] = "standard";
        Response.Redirect("delivery.aspx");
    }
}

שאלה 6 · פעולת שרת IsPeak – ספרת אחדות מקסימלית

נגדיר מספר Peak – מספר שלם חיובי שספרת האחדות שלו גדולה ממש מכל אחת מהספרות האחרות שלו, וגם סכום הספרות שלו הוא מספר זוגי.

דוגמאות למספרים Peak:

•1359 - ספרת האחדות 9 גדולה מ־1, מ־3 ומ־5, וסכום הספרות הוא 18 שהוא מספר זוגי.
•446 - ספרת האחדות 6 גדולה מ־4 ומ־4, וסכום הספרות הוא 14 שהוא מספר זוגי.

דוגמאות למספרים שאינם Peak:

•249 - ספרת האחדות 9 אמנם גדולה מ־2 ומ־4, אך סכום הספרות הוא 15 שאינו זוגי.
•466 - ספרת האחדות 6 אינה גדולה ממש מספרת העשרות 6.

הניחו כי num הוא מספר בן שתי ספרות לפחות.

כתבו בצד שרת פעולה בשם IsPeak המקבלת מספר שלם חיובי – num, ומחזירה אמת אם המספר הוא Peak. אחרת, מחזירה שקר.

כתבו בצד שרת פעולה בשם IsPeak המקבלת מספר שלם חיובי – num, ומחזירה אמת אם המספר הוא Peak. אחרת, מחזירה שקר.

(20 נקודות)
◂ פתרון מלא לשאלה 6

פתרון

תשובה

units = num % 10, sum = units; בלולאה על שאר הספרות: אם ספרה ≥ units מחזירים false, אחרת מוסיפים לסכום; בסוף מחזירים sum % 2 == 0.

מה נדרש – פעולה בוליאנית ב-C# בצד השרת שבודקת שני תנאים על ספרות המספר: ספרת האחדות גדולה ממש מכל שאר הספרות, וסכום כל הספרות זוגי.

רעיון

1.שומרים את ספרת האחדות: units = num % 10. היא גם הערך ההתחלתי של הסכום.
2.מוחקים אותה (n = num / 10) ועוברים בלולאה על שאר הספרות.
3.לכל ספרה: אם היא גדולה או שווה ל-units – התנאי הראשון נשבר, ואפשר להחזיר מיד false. אחרת מוסיפים אותה לסכום.
4.אם הלולאה הסתיימה – כל הספרות קטנות מ-units, ונשאר לבדוק שהסכום זוגי: sum % 2 == 0.

פתרון

C#
public bool IsPeak(int num)
{
    int units = num % 10;
    int sum = units;
    int n = num / 10;
    while (n > 0)
    {
        int digit = n % 10;
        if (digit >= units)
            return false;
        sum += digit;
        n = n / 10;
    }
    return sum % 2 == 0;
}

בדיקה:

numספרת אחדותספרות אחרות קטנות ממנה?סכוםתוצאה
13599כן18true
4466כן14true
244כן6true
2499כן15false
4666לא (6 = 6)–false
3944לא (9 > 4)–false
900לא–false

המספרים Peak בין 10 ל־100: 13, 15, 17, 19, 24, 26, 28, 35, 37, 39, 46, 48, 57, 59, 68, 79.

טעות נפוצה: לבדוק digit > units במקום digit >= units – ואז 466 יתקבל בטעות, כי "גדולה ממש" פירושו שספרה שווה פוסלת. טעות נוספת: לשכוח להוסיף את ספרת האחדות עצמה לסכום.

הקוד המלא
C#
public bool IsPeak(int num)
{
    int units = num % 10;
    int sum = units;
    int n = num / 10;
    while (n > 0)
    {
        int digit = n % 10;
        if (digit >= units)
            return false;
        sum += digit;
        n = n / 10;
    }
    return sum % 2 == 0;
}

שאלה 7 · SQL – שאילתה עם כמה תנאים (OR)

במסד נתונים של אתר להזמנת חדרים במלונות יש טבלה ששמה HotelsTable המכילה את נתוני המלונות באתר.
העמודות בטבלה הן:

א. name (שם המלון), מסוג טקסט.
ב. city (העיר שבה נמצא המלון), מסוג טקסט.
ג. stars (מספר כוכבים), מסוג מספר שלם.
ד. rooms (מספר החדרים במלון), מסוג מספר שלם.
ה. occupied (מספר החדרים התפוסים הלילה), מסוג מספר שלם.
ו. price (מחיר לילה בש"ח), מסוג מספר שלם.

דוגמה לטבלה ובה כמה מן המלונות באתר:

namecitystarsroomsoccupiedprice
מלון היםאילת4120115900
נוף הכרמלחיפה36035420
מצפה המדברמצפה רמון540381200
העיר העתיקהירושלים4150140600
חוף הצפוןנהריה23012300
גלי הכנרתטבריה38050340

כתבו שאילתה אחת בשפת SQL המבקשת להציג את שמות המלונות המקיימים אחד או יותר מהתנאים הבאים:

א. מספר החדרים הפנויים הלילה (חדרים שאינם תפוסים) הוא 20 לפחות.
ב. המלון נמצא בעיר אילת.
ג. מחיר לילה בין 350 ש"ח ל־600 ש"ח (כולל).

(20 נקודות)
◂ פתרון מלא לשאלה 7

פתרון

תשובה

SELECT name FROM HotelsTable WHERE rooms - occupied >= 20 OR city = 'אילת' OR price BETWEEN 350 AND 600;
(על טבלת הדוגמה: מלון הים, נוף הכרמל, העיר העתיקה, גלי הכנרת)

מה נדרש – שאילתה אחת שמחזירה את שמות המלונות שמקיימים לפחות אחד משלושת התנאים.

רעיון – "אחד או יותר מהתנאים" ⇒ מחברים את התנאים ב־OR:

•א: אין עמודה של חדרים פנויים, אבל אפשר לחשב אותה בתנאי: rooms - occupied. "20 לפחות" ⇒ rooms - occupied >= 20.
•ב: השוואת טקסט – הערך בין גרשיים בודדים: city = 'אילת'.
•ג: "בין 350 ל־600 (כולל)" ⇒ price BETWEEN 350 AND 600 (BETWEEN כולל את שני הקצוות; שקול ל־price >= 350 AND price <= 600).

פתרון

SQL
SELECT name
FROM HotelsTable
WHERE rooms - occupied >= 20
   OR city = 'אילת'
   OR price BETWEEN 350 AND 600;

בדיקה – על טבלת הדוגמה. לכל שורה – אילו תנאים מתקיימים:

nameא: rooms − occupied ≥ 20ב: city = אילתג: 350 ≤ price ≤ 600מוצג?
מלון הים5 ✘✔900 ✘כן
נוף הכרמל25 ✔✘420 ✔כן
מצפה המדבר2 ✘✘1200 ✘לא
העיר העתיקה10 ✘✘600 ✔כן
חוף הצפון18 ✘✘300 ✘לא
גלי הכנרת30 ✔✘340 ✘כן

התוצאה: מלון הים, נוף הכרמל, העיר העתיקה, גלי הכנרת.

טעות נפוצה: לחבר את התנאים ב־AND – אז נדרשים כל התנאים יחד, ובטבלת הדוגמה לא מוחזר אף מלון. טעות נוספת: לכתוב את תנאי ג כ־price > 350 AND price < 600 למרות ש"כולל" – אז "העיר העתיקה" (600 בדיוק) לא תוצג. ואם משלבים AND בתוך OR – חובה סוגריים: ... OR (price >= 350 AND price <= 600).

פרק שלישי

ענו על שאלה אחת מן השאלות 9-8.

שאלה 8 · בדיקת קוד קופון מול מסד הנתונים

בדף התשלום של חנות ספרים מקוונת יכול הלקוח להקליד קוד קופון הנחה בשדה זה:

HTML
<input type="text" name="coupon" id="coupon"/>

בבסיס הנתונים של האתר קיימת טבלה בשם coupons ובה שלוש עמודות:

•code – קוד הקופון, משתנה מסוג טקסט
•discount – אחוז ההנחה, משתנה מסוג מספר שלם
•remaining – מספר השימושים שנותרו בקופון, משתנה מסוג מספר שלם
codediscountremaining
SUMMER101025
VIP30300
BOOK15151

לפניכם קטע קוד חלקי תקין של פעולה בשם CheckCoupon הבודקת את קוד הקופון שהוקלד. יש להפנות את הלקוח לעמוד המתאים על פי החוקים הבאים:

•אם קוד הקופון אינו קיים בבסיס הנתונים, הפעולה תפנה לעמוד badCoupon.aspx
•אם קוד הקופון קיים אך לא נותרו בו שימושים (remaining שווה 0), הפעולה תפנה לעמוד usedUp.aspx
•אחרת, הפעולה תשמור את אחוז ההנחה של הקופון כמספר שלם במשתנה Session["discount"] ותפנה לעמוד cart.aspx
C#
protected void CheckCoupon(string connectionString){
    SqlConnection connection = new SqlConnection(connectionString);
    SqlCommand command = new SqlCommand();
    DataSet ds = new DataSet();
    command.CommandText = string.Format("Select * From coupons Where code = '{0}'",
    Request.Form["coupon"]);
    command.Connection = connection;
    connection.Open();
    SqlDataAdapter adapter = new SqlDataAdapter(command);
    adapter.Fill(ds);
    connection.Close();
                    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
                    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
}

יש להשלים את הקוד החסר בסוף הפעולה (מסומן בכוכביות)

(20 נקודות)
◂ פתרון מלא לשאלה 8

פתרון

תשובה

if (ds.Tables[0].Rows.Count == 0)
{
Response.Redirect("badCoupon.aspx");
}
else
{
DataRow row = ds.Tables[0].Rows[0];
int remaining = int.Parse(row["remaining"].ToString());
if (remaining == 0)
{
Response.Redirect("usedUp.aspx");
}
else
{
Session["discount"] = int.Parse(row["discount"].ToString());
Response.Redirect("cart.aspx");
}
}

מה נדרש – להשלים את סוף הפעולה: אחרי שהשאילתה רצה והתוצאות נמצאות ב־ds, להחליט לאיזה מבין שלושת הדפים להפנות, ובמקרה של קופון תקף – גם לשמור את אחוז ההנחה ב־Session.

רעיון

•השאילתה מחזירה רק את השורות שבהן code שווה לקוד שהוקלד בשדה coupon. התוצאה נמצאת ב־ds.Tables[0].
•אין שורות (ds.Tables[0].Rows.Count == 0) ⇒ הקוד לא קיים ⇒ badCoupon.aspx.
•אחרת לוקחים את השורה הראשונה ds.Tables[0].Rows[0] וקוראים ממנה את remaining ואת discount. ערך בתא של DataRow הוא object, ולכן ממירים: int.Parse(row["remaining"].ToString()).
•remaining == 0 ⇒ usedUp.aspx.
•אחרת: Session["discount"] = ... ואז Response.Redirect("cart.aspx"). את ה־Session שומרים לפני ההפניה.

פתרון – הקוד שנכתב במקום הכוכביות:

C#
if (ds.Tables[0].Rows.Count == 0)
{
    Response.Redirect("badCoupon.aspx");
}
else
{
    DataRow row = ds.Tables[0].Rows[0];
    int remaining = int.Parse(row["remaining"].ToString());
    if (remaining == 0)
    {
        Response.Redirect("usedUp.aspx");
    }
    else
    {
        Session["discount"] = int.Parse(row["discount"].ToString());
        Response.Redirect("cart.aspx");
    }
}

הפעולה המלאה:

C#
protected void CheckCoupon(string connectionString){
    SqlConnection connection = new SqlConnection(connectionString);
    SqlCommand command = new SqlCommand();
    DataSet ds = new DataSet();
    command.CommandText = string.Format("Select * From coupons Where code = '{0}'",
    Request.Form["coupon"]);
    command.Connection = connection;
    connection.Open();
    SqlDataAdapter adapter = new SqlDataAdapter(command);
    adapter.Fill(ds);
    connection.Close();

    // ---- the missing code ----
    if (ds.Tables[0].Rows.Count == 0)
    {
        Response.Redirect("badCoupon.aspx");
    }
    else
    {
        DataRow row = ds.Tables[0].Rows[0];
        int remaining = int.Parse(row["remaining"].ToString());
        if (remaining == 0)
        {
            Response.Redirect("usedUp.aspx");
        }
        else
        {
            Session["discount"] = int.Parse(row["discount"].ToString());
            Response.Redirect("cart.aspx");
        }
    }
}

בדיקה – הפעולה המלאה על הטבלה coupons מהשאלה:

couponהפניהSession["discount"]
SUMMER10cart.aspx10
BOOK15cart.aspx15
VIP30usedUp.aspx(לא נשמר)
WINTER20badCoupon.aspx(לא נשמר)

טעות נפוצה: לגשת ל־Rows[0] לפני שבודקים שיש שורות – כשהקוד לא קיים זו שגיאת זמן ריצה. טעות נוספת: להשוות row["remaining"] == 0 בלי המרה – זו השוואה בין object למספר, שגיאת הידור.

הערה: בניית שאילתה משרשור הקלט של המשתמש (string.Format עם Request.Form) חשופה ל־SQL Injection; באתר אמיתי משתמשים בפרמטרים. כאן הקוד הנתון כתוב כך, ואנו רק משלימים אותו.

הקוד המלא
C#
protected void CheckCoupon(string connectionString){
    SqlConnection connection = new SqlConnection(connectionString);
    SqlCommand command = new SqlCommand();
    DataSet ds = new DataSet();
    command.CommandText = string.Format("Select * From coupons Where code = '{0}'",
    Request.Form["coupon"]);
    command.Connection = connection;
    connection.Open();
    SqlDataAdapter adapter = new SqlDataAdapter(command);
    adapter.Fill(ds);
    connection.Close();

    // ---- the missing code ----
    if (ds.Tables[0].Rows.Count == 0)
    {
        Response.Redirect("badCoupon.aspx");
    }
    else
    {
        DataRow row = ds.Tables[0].Rows[0];
        int remaining = int.Parse(row["remaining"].ToString());
        if (remaining == 0)
        {
            Response.Redirect("usedUp.aspx");
        }
        else
        {
            Session["discount"] = int.Parse(row["discount"].ToString());
            Response.Redirect("cart.aspx");
        }
    }
}

שאלה 9 · דיווח על אבדות ומציאות – Request.Form ו-INSERT

לפניכם התוכנית הבאה בדף Found.aspx (אין טעויות תחביר). בעזרת הדף תלמידים מדווחים על חפצים שמצאו בבית הספר; כל דיווח נשמר בטבלה Found.

HTML
01. <%@ Page Language="C#" %>
02. <%@ Import Namespace="System.Data" %>
03. <%@ Import Namespace="System.Data.SqlClient" %>
04.
05. <script runat="server">
06.  public string msg = "";
07.  protected void Page_Load(object sender, EventArgs e)
08.  {
09.      if (Request.Form["item"] != null)
10.      {
11.          string item = Request.Form["item"];
12.          string place = Request.Form["place"];
13.          if (item == "" || place == "")
14.          {
15.              msg = "יש למלא את כל השדות";
16.          }
17.          else
18.          {
19.              string connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\school.mdf;Integrated Security=True";
20.              SqlConnection connection = new SqlConnection(connectionString);
21.              string sql = string.Format("Insert Into Found (Item, Place) Values ('{0}', '{1}')", item, place);
22.              SqlCommand command = new SqlCommand(sql, connection);
23.              connection.Open();
24.              command.ExecuteNonQuery();
25.              connection.Close();
26.              if (Session["count"] == null)
27.                  Session["count"] = 0;
28.              Session["count"] = (int)Session["count"] + 1;
29.              msg = "הדיווח נשמר. מספר הדיווחים שלך: " + Session["count"];
30.          }
31.      }
32.  }
33. </script>
34. <html xmlns="http://www.w3.org/1999/xhtml">
35. <head runat="server">
36.    <title>Lost and Found</title>
37. </head>
38. <body>
39.    <form id="form1" action="Found.aspx" method="post">
40.       חפץ: <input type="text" name="item" />
41.       מקום: <input type="text" name="place" />
42.       <input type="submit" value="Send" />
43.    </form>
44.    <p><%= msg %></p>
45. </body>
46. </html>

לפניכם חמישה הגדים, רשמו עבור כל הגד נכון / לא נכון.

1.כאשר תלמיד נכנס לדף Found.aspx על ידי הקלדת הכתובת שלו בדפדפן, לא נוספת שורה לטבלה Found.
2.אם תלמיד ימלא רק את שדה החפץ וישאיר את שדה המקום ריק, תתווסף לטבלה Found שורה שבה המקום ריק.
3.שני תלמידים שונים שולחים, כל אחד מהמחשב שלו, דיווח תקין אחד. כל אחד מהם יראה בדף: "הדיווח נשמר. מספר הדיווחים שלך: 1".
4.השורות 19 עד 29 יתבצעו רק בעת בקשה הכוללת הגשת נתוני טופס, ששני השדות שלו אינם ריקים.
5.דיווח על החפץ ג'קט כחול (הגרש מוקלד בתו ') שנמצא באולם הספורט יישמר בטבלה Found כמו כל דיווח אחר.

לפניכם חמישה הגדים, רשמו עבור כל הגד נכון / לא נכון.

(20 נקודות)
◂ פתרון מלא לשאלה 9

פתרון

תשובה

1 – נכון; 2 – לא נכון; 3 – נכון; 4 – נכון; 5 – לא נכון

מה נדרש – לקבוע לכל אחד מחמשת ההגדים אם הוא נכון.

רעיון – לעקוב מתי רץ כל חלק של Page_Load: הטופס (שורה 39) נשלח בשיטה post לאותו דף, ולכן נתוני הטופס נקראים ב-Request.Form; בבקשה רגילה (get) Request.Form["item"] הוא null.

פתרון

מה הקוד עושה: רק כשיש נתוני טופס (שורה 9) נקראים החפץ והמקום. אם אחד מהם ריק – מוצגת הודעה ולא נשמר דבר (שורות 13–16). אחרת נבנית פקודת INSERT מהטקסט שהוקלד (שורה 21), היא מתבצעת (שורות 22–25), ומונה הדיווחים של הגולש הזה ב-Session גדל ב-1 (שורות 26–28).

הגדתשובההסבר
1נכוןהקלדת כתובת היא בקשת get בלי נתוני טופס: Request.Form["item"] הוא null, ושום שורה לא נוספת.
2לא נכוןהשדה place נשלח כמחרוזת ריקה "", התנאי בשורה 13 מתקיים ומוצגת ההודעה "יש למלא את כל השדות" – בלי INSERT.
3נכוןהמונה נשמר ב-Session, שהוא נפרד לכל גולש. אצל כל אחד מהם Session["count"] מתחיל ב-null, מאותחל ל-0 וגדל ל-1.
4נכוןהשורות 19–29 נמצאות בתוך if של שורה 9 (יש נתוני טופס) ובחלק ה-else של שורה 13 (שני השדות אינם ריקים).
5לא נכוןהפקודה נבנית בשרשור (string.Format): Values ('ג'קט כחול', 'אולם הספורט'). הגרש סוגר את המחרוזת של SQL באמצע המילה, הפקודה אינה תקינה, ו-ExecuteNonQuery זורק שגיאה – הדיווח לא נשמר. (הפתרון: פקודה עם פרמטרים, או הכפלת הגרש.)

בדיקה – קוד השרת (שורות 6–32), כשפקודת ה-INSERT מתבצעת על הטבלה:

בקשהתוצאהשורות בטבלה
דנה נכנסת לדף (get)הודעה ריקה0
דנה שולחת חפץ "קלמר אדום" ומקום ריק"יש למלא את כל השדות"0
דנה שולחת דיווח תקין"...מספר הדיווחים שלך: 1"1
יוסי שולח דיווח תקין"...מספר הדיווחים שלך: 1"2
דנה שולחת דיווח נוסף"...מספר הדיווחים שלך: 2"3
יוסי שולח "ג'קט כחול"שגיאת תחביר ב-SQL (near "קט")3

טעות נפוצה: לחשוב שמונה ב-Session משותף לכל התלמידים (זה Application), ולענות על הגד 5 "נכון" בלי לבדוק איך נבנית פקודת ה-SQL מהטקסט שהוקלד.

טבלת התשובות
שאלהסעיףתשובה
1-

ד. שפת תכנות שהקוד שלה רץ בדפדפן ומאפשר לדף להגיב לפעולות המשתמש.

2-

(4)

3-

ארבע שורות כוכביות מודגשות שגודלן הולך וקטן: * (כותרת h1, הגדולה ביותר), (h2), קו אופקי, * (h3), (h4), קו אופקי.

4-

(1) i < clue.length
(2) j >= 0
(3) clue.charAt(i) != answer.charAt(j)
(4) i++
(5) j--
(6) i < clue.length || j >= 0

5-

double cartSum = (double)Session["cartSum"]; bool isClub = (bool)Session["isClub"]; ואז: cartSum >= 400 ⇐ free + freeDelivery.aspx; אחרת isClub && cartSum >= 150 ⇐ reduced + clubDelivery.aspx; אחרת standard + delivery.aspx.

6-

units = num % 10, sum = units; בלולאה על שאר הספרות: אם ספרה ≥ units מחזירים false, אחרת מוסיפים לסכום; בסוף מחזירים sum % 2 == 0.

7-

SELECT name FROM HotelsTable WHERE rooms - occupied >= 20 OR city = 'אילת' OR price BETWEEN 350 AND 600;
(על טבלת הדוגמה: מלון הים, נוף הכרמל, העיר העתיקה, גלי הכנרת)

8-

if (ds.Tables[0].Rows.Count == 0)
{
Response.Redirect("badCoupon.aspx");
}
else
{
DataRow row = ds.Tables[0].Rows[0];
int remaining = int.Parse(row["remaining"].ToString());
if (remaining == 0)
{
Response.Redirect("usedUp.aspx");
}
else
{
Session["discount"] = int.Parse(row["discount"].ToString());
Response.Redirect("cart.aspx");
}
}

9-

1 – נכון; 2 – לא נכון; 3 – נכון; 4 – נכון; 5 – לא נכון

כל האתר במבט אחד

קיצורי דרך לכל הכלים, הבגרויות והקורסים

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