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

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

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

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

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

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

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

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

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

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

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

בהצלחה!

פרק ראשון

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

שאלה 1 · הפקודה Response.Redirect

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

C#
Response.Redirect("menu.aspx");

מה קורה בעקבות ביצוע הפקודה?

א. הטקסט menu.aspx נכתב בתוך הדף login.aspx המוצג בדפדפן
ב. השרת שולח לדפדפן הוראה לעבור לדף menu.aspx, והדפדפן שולח לשרת בקשה חדשה לדף זה
ג. שם הדף menu.aspx נשמר באובייקט Session של המשתמש
ד. הדף menu.aspx נשמר במסד הנתונים של האתר

מה קורה בעקבות ביצוע הפקודה Response.Redirect("menu.aspx"); בקוד צד השרת?

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

פתרון

תשובה

ב. השרת שולח לדפדפן הוראה לעבור לדף menu.aspx, והדפדפן שולח לשרת בקשה חדשה לדף זה

מה נדרש – להבין מה עושה הפעולה Redirect של האובייקט Response.

רעיון – האובייקט Response מייצג את התגובה שהשרת שולח ללקוח (לדפדפן). הפעולה Response.Redirect(url) אינה שולחת לדפדפן את תוכן הדף, אלא הוראת הפניה: "עבור לכתובת menu.aspx". הדפדפן מקבל את ההוראה, שולח לשרת בקשה חדשה לדף menu.aspx, והשרת מריץ את הדף ומחזיר אותו. כך, לאחר התחברות מוצלחת, המשתמש מגיע לדף התפריט.

פתרון – התשובה הנכונה: ב.

בדיקה – למה האחרות שגויות:

•א – כתיבת טקסט לתוך הדף נעשית בעזרת Response.Write(...), לא Redirect.
•ג – שמירה ב-Session נעשית בהשמה מפורשת, למשל Session["page"] = "menu.aspx";. Redirect אינו שומר דבר.
•ד – Redirect אינו עובד מול מסד הנתונים.

השרת מחזיר תגובה עם קוד 302 (הפניה), הכתובת Location = menu.aspx וגוף דף ריק – כלומר רק הוראה לדפדפן לבקש דף אחר.

טעות נפוצה: לחשוב שהשרת "מדביק" את הדף menu.aspx בתוך הדף הנוכחי – בפועל הדפדפן מבקש את הדף החדש בבקשה נפרדת.

שאלה 2 · תגית לשורה בטבלה

איזו תגית HTML משמשת ליצירת שורה בטבלה?

א. <td>
ב. <th>
ג. <table>
ד. <tr>

איזו תגית HTML משמשת ליצירת שורה בטבלה?

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

פתרון

תשובה

ד. <tr>

מה נדרש: לזהות את התגית שיוצרת שורה בטבלת HTML.

רעיון: טבלה בנויה משורות, וכל שורה בנויה מתאים. שורה = Table Row, ובקיצור tr.

פתרון:

•<td> – תא רגיל בתוך שורה (Table Data).
•<th> – תא כותרת (Table Header); הטקסט שבו מודגש וממורכז.
•<table> – הטבלה כולה (התגית העוטפת).
•<tr> – שורה בטבלה (Table Row). ✓

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

HTML
<table border="1">
  <tr>
    <td>שם</td>
    <td>ציון</td>
  </tr>
  <tr>
    <td>דנה</td>
    <td>95</td>
  </tr>
</table>

תשובה: ד.

בדיקה: בדוגמה יש שתי תגיות <tr> וארבע תגיות <td>. בטבלה יש בדיוק 2 שורות ו-2 עמודות – מספר השורות שווה למספר תגיות ה-<tr>.

טעות נפוצה: לבחור <td> – אבל <td> יוצרת תא אחד בתוך שורה, ולא את השורה עצמה.

שאלה 3 · פלט של פעולת שרת – טבלת HTML בשורה אחת

לפניכם פעולה בשם Draw הכתובה בצד שרת. העתיקו למחברתכם את מה שיוצג בדפדפן לאחר הרצת הפעולה Draw עם הפרמטר n = 7.

C#
public void Draw (int n) {
   string str = "<table border = '1'><tr>";
   for (int i = n; i >= 1; i--)
   {
      if (i % 4 == 0)
         str += "<td>Tik</td>";
      else if (i % 2 == 0)
         str += "<td>" + (i * 10) + "</td>";
      else
         str += "<td>" + i + "</td>";
   }
   str += "</tr></table>";
   Response.Write (str);
}

העתיקו למחברתכם את מה שיוצג בדפדפן לאחר הרצת הפעולה Draw עם הפרמטר n = 7.

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

פתרון

תשובה

טבלה עם מסגרת, שורה אחת ו־7 תאים, משמאל לימין: 7, 60, 5, Tik, 3, 20, 1

מה נדרש – לא את קוד ה-HTML, אלא את מה שהדפדפן מציג אחרי שהשרת שולח לו את המחרוזת str.

רעיון – לפני הלולאה נפתחות הטבלה (עם מסגרת, border = '1') ושורה אחת (<tr>). בכל סיבוב של הלולאה נוסף תא (<td>) לאותה שורה, ורק אחרי הלולאה השורה והטבלה נסגרות. לכן מתקבלת טבלה בעלת שורה אחת ו־7 תאים זה לצד זה. הלולאה רצה מ־n כלפי מטה (i = 7, 6, ..., 1), ולכן התא הראשון הוא של i = 7. שימו לב שהבדיקה i % 4 == 0 נעשית לפני i % 2 == 0.

פתרון – מעקב:

ii % 4 == 0 ?i % 2 == 0 ?התא שנוסף
7לאלא<td>7</td>
6לאכן<td>60</td> (6 * 10)
5לאלא<td>5</td>
4כן(לא נבדק)<td>Tik</td>
3לאלא<td>3</td>
2לאכן<td>20</td> (2 * 10)
1לאלא<td>1</td>

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

HTML
<table border = '1'><tr><td>7</td><td>60</td><td>5</td><td>Tik</td><td>3</td><td>20</td><td>1</td></tr></table>

מה יוצג בדפדפן – טבלה עם מסגרת סביב כל תא, שורה אחת ושבעה תאים (משמאל לימין):

7605Tik3201

בדיקה – עבור n = 7 מתקבלת בדיוק המחרוזת שלמעלה – שורה אחת (<tr> אחד) ושבעה תאים.

טעות נפוצה: לכתוב 40 עבור i = 4 (כי 4 זוגי) – אבל התנאי הראשון i % 4 == 0 מתקיים ולכן נכתב Tik. טעות נוספת: לצייר את התאים זה מתחת לזה – כל התאים נמצאים באותו <tr>, ולכן הם מוצגים באותה שורה.

פרק שני

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

שאלה 4 · טבלת HTML עם colspan/rowspan וקישור לדף באתר (10 נקודות)

עידו, תלמיד מדעי המחשב, בנה אתר ובו מידע על שמורות טבע בצפון הארץ. באתר תיקייה בשם Images ובה תמונה של הר בשם mountain.png, ותיקייה בשם Pages ובה הדף meron.html.

HTML
<!DOCTYPE html>
<html lang="he">
  <meta charset="utf-8"/>
  <table style="width:240px" border="2" dir="rtl">
    <tr>
      <td colspan="3">שמורות טבע בצפון</td>
    </tr>
    <tr>
      <td rowspan="2">נחלים</td>
      <td>תל דן</td>
      <td>בניאס</td>
    </tr>
    <tr>
      <td>נחל עמוד</td>
      <td>נחל כזיב</td>
    </tr>
    <tr>
      <td>הרים</td>
      <td colspan="2">הר מירון</td>
    </tr>
    <tr>
      <td colspan="3" align="center">
        <img src="Images/mountain.png" />
      </td>
    </tr>
  </table>
</html>
א.

כיצד יוצג הדף? כתבו במחברת הבחינה את האות של התשובה הנכונה מבין האפשרויות (a-d).

ב.

הוסיפו קוד HTML מתאים כך שלחיצה על הכיתוב "הר מירון" תעביר לדף meron.html שבתיקייה Pages באתר.

◂ פתרון מלא לשאלה 4

סעיף א

תשובה

c

מה נדרש – לזהות איזה מארבעת הציורים מתאים לטבלה שבקוד.

רעיון – עוברים שורה־שורה (<tr>) וסופרים תאים. colspan – תא שמתפרש על כמה עמודות; rowspan – תא שמתפרש על כמה שורות. dir="rtl" – התא הראשון בכל שורה מופיע מימין. בטבלה 3 עמודות (שורה 2 מכילה 3 תאים).

פתרון

1.שורה 1: תא אחד colspan="3" – "שמורות טבע בצפון" לרוחב כל הטבלה.
2.שורה 2: "נחלים" עם rowspan="2" בעמודה הימנית, תופס גם את שורה 3; משמאל לו "תל דן" ואחריו "בניאס".
3.שורה 3: רק שני תאים – "נחל עמוד" ו"נחל כזיב". העמודה הימנית תפוסה על ידי "נחלים", ולכן הם נכנסים לעמודה האמצעית והשמאלית ("נחל עמוד" מתחת ל"תל דן", "נחל כזיב" מתחת ל"בניאס").
4.שורה 4: "הרים" מימין, ו"הר מירון" עם colspan="2" – על פני שתי העמודות השמאליות.
5.שורה 5: תא colspan="3" עם align="center" – תמונת ההר במרכז שורה ברוחב כל הטבלה.

נפסול את האפשרויות האחרות:

•a – "נחלים" תופס שורה אחת בלבד, ו"נחל עמוד" זז לעמודה הימנית – כך נראית הטבלה בלי rowspan. שגוי.
•b – "נחלים" ו"הרים" מופיעים משמאל – כך נראית הטבלה בכיוון ltr. שגוי.
•d – "הר מירון" תופס עמודה אחת בלבד והתא השמאלי בשורה ריק – כך נראית הטבלה בלי colspan בשורה 4. שגוי.
•c – תואם את כל חמשת הסעיפים שלמעלה.

תשובה: c.

בדיקה – בדפדפן הקוד מוצג בדיוק כמו ציור c; שלושת הציורים האחרים מתאימים לגרסאות שגויות של הקוד (בלי rowspan, ltr, בלי colspan בשורה 4).

טעות נפוצה: לחשוב שבשורה 3 התא הראשון ("נחל עמוד") יופיע בעמודה הימנית – אבל המקום הזה תפוס על ידי התא עם rowspan משורה 2.

סעיף ב

תשובה

עוטפים את הכיתוב בתגית קישור עם כתובת יחסית:
<td colspan="2"><a href="Pages/meron.html">הר מירון</a></td>

מה נדרש – שלחיצה על הכיתוב "הר מירון" תעביר לדף meron.html שנמצא בתיקייה Pages של האתר.

רעיון – קישור נוצר בתגית <a href="...">, ומה שנמצא בין <a> ל־</a> הוא האזור הלחיץ. הדף נמצא באותו אתר, לכן מספיקה כתובת יחסית – שם התיקייה ושם הקובץ: Pages/meron.html (בדיוק כמו Images/mountain.png בתגית התמונה).

פתרון – התא של "הר מירון" הופך ל:

HTML
<td colspan="2"><a href="Pages/meron.html">הר מירון</a></td>

הדף המלא אחרי השינוי:

HTML
<!DOCTYPE html>
<html lang="he">
  <meta charset="utf-8"/>
  <table style="width:240px" border="2" dir="rtl">
    <tr>
      <td colspan="3">שמורות טבע בצפון</td>
    </tr>
    <tr>
      <td rowspan="2">נחלים</td>
      <td>תל דן</td>
      <td>בניאס</td>
    </tr>
    <tr>
      <td>נחל עמוד</td>
      <td>נחל כזיב</td>
    </tr>
    <tr>
      <td>הרים</td>
      <td colspan="2"><a href="Pages/meron.html">הר מירון</a></td>
    </tr>
    <tr>
      <td colspan="3" align="center">
        <img src="Images/mountain.png" />
      </td>
    </tr>
  </table>
</html>

בדיקה – הצגנו את הדף המתוקן בדפדפן: מבנה הטבלה לא השתנה, והכיתוב "הר מירון" מוצג כקישור (קו תחתון) שמוביל ל־Pages/meron.html. בהשוואה לקוד המקורי השתנתה שורה אחת בלבד.

טעות נפוצה: לשים את תגית <a> מחוץ ל־<td> (בין <tr> ל־<td>) – זה HTML לא תקין בטבלה. טעות נוספת: לכתוב href="meron.html" בלי שם התיקייה – הדפדפן יחפש את הקובץ ליד הדף הנוכחי ולא ימצא אותו.

שאלה 5 · הצגת מתנדבים מעיר נבחרת – השלמת ביטויים

בעמותה "לב פתוח" מתנדבים תושבים מכמה ערים. במסד הנתונים קיימת טבלה - Volunteers, השומרת לכל מתנדב את שמו (FullName), את העיר שבה הוא גר (City) ואת מספר שעות ההתנדבות שלו החודש (Hours, מספר שלם).

לפניכם פונקציה שכותרתה: protected void showVolunteers(string connectionString, string city)

הפונקציה מקבלת מחרוזת connectionString שמפנה לבסיס הנתונים, ושם של עיר city. הפונקציה מציגה בדף טבלת HTML ובה השם ומספר השעות של כל המתנדבים מהעיר city, מסודרים מהמתנדב שהתנדב הכי הרבה שעות להכי מעט, ובשורה האחרונה של הטבלה – סך כל השעות של מתנדבי העיר.

דוגמה לטבלה שתוצג עבור city = "חיפה":

שם המתנדבשעות
מאיה פרץ51
נועה כהן34
רוני אדלר19
יונתן אזולאי8
סך הכול112

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

C#
protected void showVolunteers(string connectionString, string city)
{
    string html = "";
    int total = 0;
    DataSet ds = ______(1)______;
    SqlConnection conn = new SqlConnection(connectionString);
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "SELECT FullName, Hours FROM Volunteers WHERE ______(2)______ ORDER BY Hours DESC";
    cmd.Connection = ______(3)______;
    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
    conn.Open();
    adapter.Fill(ds, "vol");
    conn.Close();
    DataTable t = ds.Tables[______(4)______];
    html += "<table border='1'><tr><th>שם המתנדב</th><th>שעות</th></tr>";
    for (int i = 0; i < ______(5)______; i++)
    {
        DataRow row = t.Rows[i];
        html += "<tr><td>" + row["FullName"] + "</td><td>" + row["Hours"] + "</td></tr>";
        total = total + ______(6)______;
    }
    html += "<tr><td>סך הכול</td><td>" + total + "</td></tr>";
    html += ______(7)______;
    ______(8)______;
}

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

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

פתרון

תשובה

(1) new DataSet()
(2) City = '" + city + "'
(3) conn
(4) "vol"
(5) t.Rows.Count
(6) (int)row["Hours"]
(7) "</table>"
(8) Response.Write(html)

מה נדרש – להשלים 8 ביטויים בפונקציה שקוראת ממסד הנתונים את המתנדבים של עיר אחת, מציגה אותם בטבלת HTML ומחשבת את סך השעות.

רעיון – הדרך הרגילה לקרוא נתונים: חיבור (SqlConnection) ← פקודה (SqlCommand) עם שאילתה וחיבור ← מתאם (SqlDataAdapter) שממלא DataSet ← לוקחים מה-DataSet את ה-DataTable ← עוברים על השורות, בונים מחרוזת HTML ובדרך צוברים סכום ← Response.Write.

פתרון

מספרהביטוי החסרהסבר
(1)new DataSet()יוצרים את ה-DataSet שהמתאם ימלא בהמשך.
(2)City = '" + city + "'תנאי הסינון: רק השורות שבהן העיר שווה לפרמטר city. ערך טקסט ב-SQL נכתב בין גרשיים בודדים, ולכן סוגרים את המחרוזת של C#, משרשרים את city ופותחים אותה שוב: התוצאה היא למשל WHERE City = 'חיפה' ORDER BY Hours DESC.
(3)connהפקודה צריכה לדעת דרך איזה חיבור לעבוד – החיבור conn שנוצר בשורה הקודמת.
(4)"vol"המתאם מילא את ה-DataSet בטבלה בשם "vol" (Fill(ds, "vol")), ולכן ניגשים אליה בשמה. גם 0 (הטבלה הראשונה) נכון.
(5)t.Rows.Countהלולאה עוברת לפי מספר (אינדקס) על כל שורות הטבלה – מספר השורות הוא t.Rows.Count.
(6)(int)row["Hours"]צוברים את מספר השעות של השורה. row["Hours"] הוא מטיפוס object, ולכן צריך המרה למספר: (int)row["Hours"] או Convert.ToInt32(row["Hours"]).
(7)"</table>"סוגרים את טבלת ה-HTML.
(8)Response.Write(html)שולחים את מחרוזת ה-HTML לדפדפן.

הפונקציה המלאה:

C#
protected void showVolunteers(string connectionString, string city)
{
    string html = "";
    int total = 0;
    DataSet ds = new DataSet();
    SqlConnection conn = new SqlConnection(connectionString);
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "SELECT FullName, Hours FROM Volunteers WHERE City = '" + city + "' ORDER BY Hours DESC";
    cmd.Connection = conn;
    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
    conn.Open();
    adapter.Fill(ds, "vol");
    conn.Close();
    DataTable t = ds.Tables["vol"];
    html += "<table border='1'><tr><th>שם המתנדב</th><th>שעות</th></tr>";
    for (int i = 0; i < t.Rows.Count; i++)
    {
        DataRow row = t.Rows[i];
        html += "<tr><td>" + row["FullName"] + "</td><td>" + row["Hours"] + "</td></tr>";
        total = total + (int)row["Hours"];
    }
    html += "<tr><td>סך הכול</td><td>" + total + "</td></tr>";
    html += "</table>";
    Response.Write(html);
}

בדיקה – טבלה עם 7 מתנדבים והפונקציה המלאה ב-C#. עבור "חיפה" נשלחה השאילתה SELECT FullName, Hours FROM Volunteers WHERE City = 'חיפה' ORDER BY Hours DESC והתקבלה בדיוק הטבלה שבדוגמה: מאיה פרץ 51, נועה כהן 34, רוני אדלר 19, יונתן אזולאי 8, ובשורה האחרונה סך הכול 112. עבור עיר שאין בה מתנדבים התקבלה טבלה עם שורת הכותרות ושורת "סך הכול" 0 בלבד. גם עם Tables[0] ועם Convert.ToInt32(row["Hours"]) התקבלה אותה תוצאה.

טעות נפוצה: לכתוב ב-(2) City = city – כך מחפשים עמודה בשם city ולא את הערך שהתקבל בפרמטר; וב-(6) לכתוב total + row["Hours"] בלי המרה – זו שגיאת הידור (object).

הקוד המלא
C#
protected void showVolunteers(string connectionString, string city)
{
    string html = "";
    int total = 0;
    DataSet ds = new DataSet();
    SqlConnection conn = new SqlConnection(connectionString);
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "SELECT FullName, Hours FROM Volunteers WHERE City = '" + city + "' ORDER BY Hours DESC";
    cmd.Connection = conn;
    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
    conn.Open();
    adapter.Fill(ds, "vol");
    conn.Close();
    DataTable t = ds.Tables["vol"];
    html += "<table border='1'><tr><th>שם המתנדב</th><th>שעות</th></tr>";
    for (int i = 0; i < t.Rows.Count; i++)
    {
        DataRow row = t.Rows[i];
        html += "<tr><td>" + row["FullName"] + "</td><td>" + row["Hours"] + "</td></tr>";
        total = total + (int)row["Hours"];
    }
    html += "<tr><td>סך הכול</td><td>" + total + "</td></tr>";
    html += "</table>";
    Response.Write(html);
}

שאלה 6 · זוג "תאומים"

זוג "תאומים" הוא זוג של מספרים חיוביים ושלמים שבהם מספר הספרות זהה וגם סכום הספרות זהה.

דוגמאות לזוגות מספרים שהם "תאומים":

מספר 1מספר 2הסבר
352514בשניהם 3 ספרות, סכום הספרות 10
4774בשניהם 2 ספרות, סכום הספרות 11
10902008בשניהם 4 ספרות, סכום הספרות 10

הזוג 1234 ו-55 אינו זוג "תאומים": סכום הספרות בשניהם הוא 10, אך מספר הספרות שונה.

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

כתבו פונקציה בשם IsTwins בצד שרת, המקבלת שני מספרים שלמים חיוביים ומחזירה אמת אם הם זוג "תאומים". אחרת, הפונקציה מחזירה שקר.

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

פתרון

תשובה

return CountDigits(num1) == CountDigits(num2) && SumDigits(num1) == SumDigits(num2); (שתי פעולות עזר: ספירת ספרות וסכום ספרות בלולאת while (num > 0) עם % 10 ו-/ 10)

מה נדרש: פונקציה בוליאנית שבודקת ששני מספרים זהים גם במספר הספרות וגם בסכום הספרות.

רעיון:

•מפרקים מספר לספרות בלולאה: num % 10 היא ספרת האחדות, ו-num / 10 (חילוק שלמים) "מוחק" אותה. ממשיכים כל עוד num > 0.
•פעולת עזר CountDigits סופרת כמה פעמים הלולאה רצה; פעולת עזר SumDigits מחברת את הספרות.
•הזוג "תאומים" רק אם שני התנאים מתקיימים – לכן &&.
•המספרים חיוביים, ולכן לכל מספר יש לפחות ספרה אחת והלולאה רצה לפחות פעם אחת.

פתרון:

C#
// פעולת עזר: מחזירה את מספר הספרות של מספר חיובי
public int CountDigits(int num)
{
    int count = 0;
    while (num > 0)
    {
        count++;
        num = num / 10;
    }
    return count;
}

// פעולת עזר: מחזירה את סכום הספרות של מספר חיובי
public int SumDigits(int num)
{
    int sum = 0;
    while (num > 0)
    {
        sum = sum + num % 10;
        num = num / 10;
    }
    return sum;
}

public bool IsTwins(int num1, int num2)
{
    return CountDigits(num1) == CountDigits(num2) && SumDigits(num1) == SumDigits(num2);
}

בדיקה:

num1num2ספרותסכומיםתוצאה
3525143, 310, 10True
47742, 211, 11True
109020084, 410, 10True
1234554, 210, 10False
305443, 28, 8False
7161, 27, 7False

טעות נפוצה: לבדוק רק את סכום הספרות (אז 1234 ו-55 ייחשבו בטעות "תאומים"). טעות נוספת: לכתוב את שתי הלולאות ישירות בפונקציה על num1 – אחרי הלולאה הראשונה num1 כבר 0, והלולאה השנייה לא רצה. בפעולות עזר אין בעיה, כי כל פעולה מקבלת עותק של המספר.

הקוד המלא
C#
// פעולת עזר: מחזירה את מספר הספרות של מספר חיובי
public int CountDigits(int num)
{
    int count = 0;
    while (num > 0)
    {
        count++;
        num = num / 10;
    }
    return count;
}

// פעולת עזר: מחזירה את סכום הספרות של מספר חיובי
public int SumDigits(int num)
{
    int sum = 0;
    while (num > 0)
    {
        sum = sum + num % 10;
        num = num / 10;
    }
    return sum;
}

public bool IsTwins(int num1, int num2)
{
    return CountDigits(num1) == CountDigits(num2) && SumDigits(num1) == SumDigits(num2);
}

שאלה 7 · סל קניות במאפייה – ערך שאינו נשמר בין לחיצות

לפניכם דף האינטרנט הבא (צד שרת) של מאפייה:

בדף שני כפתורים: לחם (12 ש"ח) ועוגה (45 ש"ח). מטרת התוכנית היא שבכל לחיצה על אחד הכפתורים יתווסף פריט לסל, והדף יציג את מספר הפריטים בסל ואת הסכום הכולל לתשלום על כל הפריטים, אולם התוכנית אינה מבצעת את הנדרש.

רשמו והסברו היכן התקלה וכיצד ניתן לתקנה.

HTML
<%@ Page Language="C#" %>
<script runat="server">
   public int total = 0;
   public void Page_Load(object sender, EventArgs e)
   {
       if (!IsPostBack)
       {
           Session["items"] = 0;
       }
   }
   void Bread_Click(object sender, EventArgs e)
   {
       total = total + 12;
       Session["items"] = (int)Session["items"] + 1;
   }
   void Cake_Click(object sender, EventArgs e)
   {
       total = total + 45;
       Session["items"] = (int)Session["items"] + 1;
   }
</script>
<html>
<head>
</head>
<body>
   <form id="form1" runat="server">
       <input type="button" runat="server" id="btnBread" value="לחם – 12 ש&quot;ח" onserverclick="Bread_Click" />
       <input type="button" runat="server" id="btnCake" value="עוגה – 45 ש&quot;ח" onserverclick="Cake_Click" />
       <div runat="server" id="div1">
           פריטים בסל: <% =Session["items"] %> , לתשלום: <% =total %> ש"ח
       </div>
   </form>
</body>
</html>

רשמו והסברו היכן התקלה וכיצד ניתן לתקנה.

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

פתרון

תשובה

הסכום נשמר בשדה של הדף (public int total = 0). בכל לחיצה (postback) נוצר אובייקט דף חדש ו-total מתחיל מ-0, ולכן מוצג רק מחיר הפריט האחרון (12 או 45). התיקון: לשמור את הסכום ב-Session – לאתחל Session["total"] = 0 בתוך if (!IsPostBack), בכל לחיצה Session["total"] = (int)Session["total"] + מחיר, ולהציג <% =Session["total"] %>.

מה נדרש – למצוא למה הדף אינו מציג את הסכום הכולל, ולתקן.

רעיון – כל לחיצה על כפתור עם runat="server" ו-onserverclick שולחת את הטופס לשרת (postback). בכל בקשה השרת יוצר אובייקט דף חדש, ולכן כל שדה של הדף (משתנה שמוגדר בתוך ה-script מחוץ לפעולות) מתחיל מחדש בערך ההתחלתי שלו. רק Session (או Application) שומר ערך בין בקשות.

פתרון

1.מה עובד – מספר הפריטים נשמר ב-Session["items"], מאותחל ל-0 רק בכניסה הראשונה (!IsPostBack) וגדל ב-1 בכל לחיצה – הוא מוצג נכון.
2.התקלה – הסכום נשמר בשדה public int total = 0;. בכל לחיצה נוצר אובייקט דף חדש ו-total מתחיל שוב מ-0, הפעולה מוסיפה לו רק את מחיר הפריט שנלחץ עכשיו, ולכן מוצג תמיד מחיר הפריט האחרון (12 או 45) ולא הסכום של כל הסל.

התיקון – לשמור את הסכום ב-Session: לאתחל Session["total"] = 0 בכניסה הראשונה, להוסיף את המחיר ל-Session["total"] בכל לחיצה (עם המרה (int)), ולהציג את Session["total"]. קטע הסקריפט המתוקן:

C#
public void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        Session["items"] = 0;
        Session["total"] = 0;
    }
}
void Bread_Click(object sender, EventArgs e)
{
    Session["total"] = (int)Session["total"] + 12;
    Session["items"] = (int)Session["items"] + 1;
}
void Cake_Click(object sender, EventArgs e)
{
    Session["total"] = (int)Session["total"] + 45;
    Session["items"] = (int)Session["items"] + 1;
}

ושורת התצוגה בדף:

HTML
<div runat="server" id="div1">
    פריטים בסל: <% =Session["items"] %> , לתשלום: <% =Session["total"] %> ש"ח
</div>

(השדה total כבר לא נחוץ, ואפשר למחוק אותו.)

בדיקה – הדמינו את מחזור החיים (אובייקט דף חדש בכל בקשה, אותו Session, Page_Load ואחריו פעולת הלחיצה):

בקשההדף המקוריהדף המתוקן
כניסה ראשונהפריטים בסל: 0 , לתשלום: 0פריטים בסל: 0 , לתשלום: 0
לחיצה על לחםפריטים בסל: 1 , לתשלום: 12פריטים בסל: 1 , לתשלום: 12
לחיצה על עוגהפריטים בסל: 2 , לתשלום: 45פריטים בסל: 2 , לתשלום: 57
לחיצה על לחםפריטים בסל: 3 , לתשלום: 12פריטים בסל: 3 , לתשלום: 69
לחיצה על עוגהפריטים בסל: 4 , לתשלום: 45פריטים בסל: 4 , לתשלום: 114

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

הקוד המלא
C#
public void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        Session["items"] = 0;
        Session["total"] = 0;
    }
}
void Bread_Click(object sender, EventArgs e)
{
    Session["total"] = (int)Session["total"] + 12;
    Session["items"] = (int)Session["items"] + 1;
}
void Cake_Click(object sender, EventArgs e)
{
    Session["total"] = (int)Session["total"] + 45;
    Session["items"] = (int)Session["items"] + 1;
}

פרק שלישי

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

שאלה 8 · הוספת רץ למרוץ בעזרת DataSet

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

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

<select name="dist" id="dist">
    <option value="5">5 ק"מ</option>
    <option value="10">10 ק"מ</option>
    <option value="21">21 ק"מ</option>
</select>

<input type="text" name="city" id="city" />

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

•fullName – משתנה מסוג טקסט
•distance – משתנה מסוג מספר שלם
•city – משתנה מסוג טקסט

דוגמה לטבלה:

fullNamedistancecity
Maya Levi10Haifa
Avi Cohen21Eilat

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

C#
protected void AddRunner(string connectionString)
{
    SqlConnection connection = new SqlConnection(connectionString);
    SqlCommand command = new SqlCommand();
    command.CommandText = "Select * From runners";
    command.Connection = connection;
    connection.Open();
    SqlDataAdapter adapter = new SqlDataAdapter(command);
    SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
    DataSet ds = new DataSet();
    adapter.Fill(ds);
    string runner = Request.Form["runner"];
    string dist = Request.Form["dist"];
    string city = Request.Form["city"];

            ************************************
            ************************************

    adapter.Update(ds);
    connection.Close();
}

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

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

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

פתרון

תשובה
C#
DataRow row = ds.Tables[0].NewRow();
row["fullName"] = runner;
row["distance"] = int.Parse(dist);
row["city"] = city;
ds.Tables[0].Rows.Add(row);

מה נדרש: להשלים את הקוד כך שהרץ החדש (השם, אורך המקצה והעיר שהגיעו מהטופס) יתווסף כשורה לטבלה runners.

רעיון: הקוד הנתון כבר התחבר למסד, ביצע Select * From runners, מילא את ה-DataSet (adapter.Fill(ds) – הטבלה נמצאת ב-ds.Tables[0]), יצר SqlCommandBuilder (שבונה עבור ה-adapter את פקודת ההוספה) וקרא את שלושת השדות מהטופס. adapter.Update(ds) בסוף שולח למסד את השינויים שנעשו ב-DataSet. לכן חסר רק להוסיף לטבלה שב-DataSet שורה חדשה:

1.ליצור שורה ריקה בתבנית של הטבלה: ds.Tables[0].NewRow().
2.למלא את שלוש העמודות. שימו לב: כל מה שמגיע מ-Request.Form הוא מחרוזת, אבל העמודה distance היא מסוג מספר שלם – לכן ממירים: int.Parse(dist).
3.להוסיף את השורה לטבלה: ds.Tables[0].Rows.Add(row).

פתרון – הקוד החסר (במקום הכוכביות):

C#
DataRow row = ds.Tables[0].NewRow();
row["fullName"] = runner;
row["distance"] = int.Parse(dist);
row["city"] = city;
ds.Tables[0].Rows.Add(row);

הפעולה המלאה – בלשונית C#.

בדיקה: טבלה עם השורות Maya Levi 10 Haifa ו-Avi Cohen 21 Eilat, כשהטופס שולח runner=Tamar Golan, dist=5, city=Ashdod. אחרי הקריאה בטבלה 3 שורות, והשורה החדשה היא Tamar Golan | 5 | Ashdod, כשהערך 5 נשמר כמספר שלם (Int32).

טעות נפוצה: לכתוב row["distance"] = dist; בלי המרה – מכניסים מחרוזת לעמודה מספרית. או ליצור שורה ב-NewRow() ולשכוח Rows.Add(row) – אז השורה לא שייכת לטבלה ו-Update לא ישמור אותה.

כתיבה מקוצרת: אפשר להוסיף את השורה גם בפקודה אחת, לפי סדר העמודות: ds.Tables[0].Rows.Add(runner, int.Parse(dist), city);

הקוד המלא
C#
protected void AddRunner(string connectionString)
{
    SqlConnection connection = new SqlConnection(connectionString);
    SqlCommand command = new SqlCommand();
    command.CommandText = "Select * From runners";
    command.Connection = connection;
    connection.Open();
    SqlDataAdapter adapter = new SqlDataAdapter(command);
    SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
    DataSet ds = new DataSet();
    adapter.Fill(ds);
    string runner = Request.Form["runner"];
    string dist = Request.Form["dist"];
    string city = Request.Form["city"];

    // ---- הקוד החסר ----
    DataRow row = ds.Tables[0].NewRow();
    row["fullName"] = runner;
    row["distance"] = int.Parse(dist);
    row["city"] = city;
    ds.Tables[0].Rows.Add(row);
    // --------------------

    adapter.Update(ds);
    connection.Close();
}

שאלה 9 · השלמת פעולה המציגה מתכונים ממסד הנתונים

באתר מתכונים יש במסד הנתונים טבלה בשם RecipesTable ובה ארבע עמודות: name (שם המתכון, טקסט), category (סוג המנה, טקסט), minutes (זמן ההכנה בדקות, מספר שלם) ו־calories (קלוריות למנה, מספר שלם).

דוגמה לטבלה:

namecategoryminutescalories
עוגת שוקולדקינוח60450
סלט ירקותסלט15120
מוס פירותקינוח20180
פשטידת תרדמאפה35320
כדורי תמריםקינוח40150
סלט פירותקינוח1090

עורכת האתר מעוניינת להציג טבלה של "קינוחים מהירים": כל המתכונים שסוג המנה שלהם הוא קינוח וזמן ההכנה שלהם קצר מ־40 דקות (לא כולל). הפעולה showQuickDesserts מקבלת מחרוזת התחברות למסד הנתונים connectionString, ומציגה בטבלה את שם המתכון, זמן ההכנה ומספר הקלוריות של המתכונים המתאימים.

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

C#
protected void showQuickDesserts(string connectionString)
{
    string resultStr = "";
    DataSet ds = _____(1)_____;
    SqlConnection connection = new SqlConnection(connectionString);
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "SELECT * FROM RecipesTable WHERE _____(2)_____";
    cmd._____(3)_____ = connection;
    connection._____(4)_____;
    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
    adapter.Fill(ds);
    connection.Close();
    resultStr += "<table border='1'><tr><th>שם המתכון</th><th>זמן הכנה</th><th>קלוריות</th></tr>";

    foreach (DataRow dr in _____(5)_____)
    {
        resultStr += "<tr>";
        resultStr += "<td>" + _____(6)_____ + "</td>";
        resultStr += "<td>" + dr["minutes"] + "</td>";
        resultStr += "<td>" + dr["calories"] + "</td>";
        resultStr += "_____(7)_____";
    }
    resultStr += "</table>";
    Response._____(8)_____(resultStr);
}

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

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

פתרון

תשובה

(1) new DataSet()
(2) category = 'קינוח' AND minutes < 40
(3) Connection
(4) Open()
(5) ds.Tables[0].Rows
(6) dr["name"]
(7) </tr>
(8) Write

מה נדרש – להשלים 8 ביטויים חסרים בפעולה שמתחברת למסד הנתונים, שולפת את השורות המתאימות ומציגה אותן בטבלת HTML.

רעיון – התבנית הקבועה של קריאה ממסד נתונים ב־ASP.NET:
יצירת DataSet → חיבור (SqlConnection עם מחרוזת ההתחברות) → פקודה (SqlCommand עם טקסט השאילתה והחיבור) → פתיחת החיבור → SqlDataAdapter שמקבל את הפקודה וממלא (Fill) את ה־DataSet → סגירת החיבור → מעבר על השורות של ds.Tables[0] ובניית מחרוזת HTML: שורה <tr>...</tr> לכל רשומה ותא <td>...</td> לכל ערך → שליחה לדפדפן עם Response.Write.

פתרון

מספרהביטוי החסרהסבר
(1)new DataSet()יצירת אובייקט DataSet חדש שיכיל את תוצאות השאילתה
(2)category = 'קינוח' AND minutes < 40שני התנאים יחד ⇒ AND; טקסט בין גרשיים בודדים; "לא כולל" ⇒ <
(3)Connectionהתכונה של הפקודה שמקשרת אותה לחיבור
(4)Open()פתיחת החיבור לפני הרצת השאילתה (עם סוגריים – זו קריאה לפעולה)
(5)ds.Tables[0].Rowsאוסף השורות של הטבלה הראשונה ב־DataSet
(6)dr["name"]שם המתכון מהשורה הנוכחית (העמודה name)
(7)</tr>סגירת השורה של הטבלה בסוף כל איטרציה
(8)WriteResponse.Write שולחת את מחרוזת ה־HTML לדפדפן

הפעולה המלאה אחרי ההשלמה:

C#
protected void showQuickDesserts(string connectionString)
{
    string resultStr = "";
    DataSet ds = new DataSet();
    SqlConnection connection = new SqlConnection(connectionString);
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "SELECT * FROM RecipesTable WHERE category = 'קינוח' AND minutes < 40";
    cmd.Connection = connection;
    connection.Open();
    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
    adapter.Fill(ds);
    connection.Close();
    resultStr += "<table border='1'><tr><th>שם המתכון</th><th>זמן הכנה</th><th>קלוריות</th></tr>";

    foreach (DataRow dr in ds.Tables[0].Rows)
    {
        resultStr += "<tr>";
        resultStr += "<td>" + dr["name"] + "</td>";
        resultStr += "<td>" + dr["minutes"] + "</td>";
        resultStr += "<td>" + dr["calories"] + "</td>";
        resultStr += "</tr>";
    }
    resultStr += "</table>";
    Response.Write(resultStr);
}

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

nameminutescalories
מוס פירות20180
סלט פירות1090

עוגת שוקולד (60 דקות) וכדורי תמרים (40 דקות בדיוק – "לא כולל") נפסלים בגלל זמן ההכנה; סלט ירקות ופשטידת תרד אינם קינוחים.

טעות נפוצה: ב־(2) לכתוב minutes <= 40 (אז יוצגו גם כדורי תמרים) או OR במקום AND (אז יוצגו כל הקינוחים, וגם סלט ירקות ופשטידת תרד). ב־(5) לכתוב ds.Rows – ל־DataSet אין Rows, רק לטבלה שבתוכו. ב־(4) לכתוב Open בלי סוגריים.

הקוד המלא
C#
protected void showQuickDesserts(string connectionString)
{
    string resultStr = "";
    DataSet ds = new DataSet();
    SqlConnection connection = new SqlConnection(connectionString);
    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = "SELECT * FROM RecipesTable WHERE category = 'קינוח' AND minutes < 40";
    cmd.Connection = connection;
    connection.Open();
    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
    adapter.Fill(ds);
    connection.Close();
    resultStr += "<table border='1'><tr><th>שם המתכון</th><th>זמן הכנה</th><th>קלוריות</th></tr>";

    foreach (DataRow dr in ds.Tables[0].Rows)
    {
        resultStr += "<tr>";
        resultStr += "<td>" + dr["name"] + "</td>";
        resultStr += "<td>" + dr["minutes"] + "</td>";
        resultStr += "<td>" + dr["calories"] + "</td>";
        resultStr += "</tr>";
    }
    resultStr += "</table>";
    Response.Write(resultStr);
}
טבלת התשובות
שאלהסעיףתשובה
1-

ב. השרת שולח לדפדפן הוראה לעבור לדף menu.aspx, והדפדפן שולח לשרת בקשה חדשה לדף זה

2-

ד. <tr>

3-

טבלה עם מסגרת, שורה אחת ו־7 תאים, משמאל לימין: 7, 60, 5, Tik, 3, 20, 1

4א

c

ב

עוטפים את הכיתוב בתגית קישור עם כתובת יחסית:
<td colspan="2"><a href="Pages/meron.html">הר מירון</a></td>

5-

(1) new DataSet()
(2) City = '" + city + "'
(3) conn
(4) "vol"
(5) t.Rows.Count
(6) (int)row["Hours"]
(7) "</table>"
(8) Response.Write(html)

6-

return CountDigits(num1) == CountDigits(num2) && SumDigits(num1) == SumDigits(num2); (שתי פעולות עזר: ספירת ספרות וסכום ספרות בלולאת while (num > 0) עם % 10 ו-/ 10)

7-

הסכום נשמר בשדה של הדף (public int total = 0). בכל לחיצה (postback) נוצר אובייקט דף חדש ו-total מתחיל מ-0, ולכן מוצג רק מחיר הפריט האחרון (12 או 45). התיקון: לשמור את הסכום ב-Session – לאתחל Session["total"] = 0 בתוך if (!IsPostBack), בכל לחיצה Session["total"] = (int)Session["total"] + מחיר, ולהציג <% =Session["total"] %>.

8-
C#
DataRow row = ds.Tables[0].NewRow();
row["fullName"] = runner;
row["distance"] = int.Parse(dist);
row["city"] = city;
ds.Tables[0].Rows.Add(row);
9-

(1) new DataSet()
(2) category = 'קינוח' AND minutes < 40
(3) Connection
(4) Open()
(5) ds.Tables[0].Rows
(6) dr["name"]
(7) </tr>
(8) Write

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

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

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