מתכונת 3 במדעי המחשב - תכנות באינטרנט 899372
נבחנים אקסטרניים · שאלון 899372 · 9 שאלות · 2 שעות · פתרון מלא לכל סעיף
מבחן מתכונת במדעי המחשב, תכנות באינטרנט, במבנה של בחינת הבגרות. כל שאלה בו בנויה כמו שאלה מבגרות אחרת. לכל סעיף יש תשובה ופתרון מלא, וכל קוד מופיע ב-Java וב-C#. פתרו בזמן של הבחינה, ורק אחר כך פתחו את הפתרונות.
הוראות הבחינה
א. משך הבחינה: שעתיים.
ב. מבנה השאלון ומפתח הערכה: בשאלון זה שלושה פרקים.
פרק ראשון — (10x3) — 30 נקודות
פרק שני — (20x2)+(10x1) — 50 נקודות
פרק שלישי — (20x1) — 20 נקודות
סך הכול — 100 נקודות
ג. חומר עזר מותר בשימוש: כל חומר עזר, חוץ ממחשבון שיש בו אפשרות תכנות.
יש לכתוב במחברת הבחינה בלבד, יש לרשום "טיוטה" בראש כל עמוד המשמש טיוטה.
כתיבת טיוטה בדפים שאינם במחברת הבחינה עלולה לגרום לפסילת הבחינה.
השאלות בשאלון זה מנוסחות בלשון רבים, אף על פי כן על כל תלמידה וכל תלמיד להשיב עליהן באופן אישי.
בהצלחה!
פרק ראשון
ענו על שלוש השאלות 3-1 (לכל שאלה – 10 נקודות).
שאלה 1 · שליחת טופס בשיטת get
בדף HTML מוגדר טופס החיפוש הזה:
<form action="search.aspx" method="get">
<input type="text" name="city" />
<input type="submit" value="חפש" />
</form>מה קורה לנתוני הטופס כאשר המשתמש לוחץ על הכפתור "חפש"?
העתיקו למחברת הבחינה את התשובה הנכונה מבין האפשרויות א–ד שלפניכם.
א. הנתונים נשמרים בדפדפן בלבד ואינם נשלחים לשרת
ב. הנתונים נשלחים לשרת בגוף הבקשה, ואינם נראים בשורת הכתובת של הדפדפן
ג. הנתונים נשלחים לשרת כחלק מכתובת ה-URL (אחרי הסימן ?), ובצד השרת קוראים אותם בעזרת Request.QueryString
ד. הנתונים נשלחים ישירות למסד הנתונים, בלי לעבור בדף search.aspx
העתיקו למחברת הבחינה את התשובה הנכונה מבין האפשרויות א–ד.
◂ פתרון מלא לשאלה 1
פתרון
ג. הנתונים נשלחים לשרת כחלק מכתובת ה-URL (אחרי הסימן ?), ובצד השרת קוראים אותם בעזרת Request.QueryString
מה נדרש: להבין מה עושה הדפדפן עם נתוני טופס שהשיטה שלו (method) היא get.
רעיון: בלחיצה על כפתור submit הדפדפן שולח בקשה לדף שכתוב ב-action (כאן search.aspx). השיטה קובעת איפה יהיו הנתונים:
method="get" – הנתונים מצורפים לכתובת אחרי ? בצורה name=value (כמה שדות מופרדים ב-&). בשרת קוראים אותם ב-Request.QueryString["city"].method="post" – הנתונים נשלחים בגוף הבקשה ואינם נראים בכתובת. בשרת קוראים אותם ב-Request.Form["city"].פתרון: התשובה הנכונה היא ג. אם המשתמש הקליד חיפה, הדפדפן יבקש את הכתובת search.aspx?city=חיפה (האותיות העבריות מקודדות בכתובת), ובקוד השרת של search.aspx:
string city = Request.QueryString["city"]; // "חיפה"בדיקה – למה האחרות שגויות:
דוגמה: מהטופס נבנית הכתובת search.aspx?city=%D7%97%D7%99%D7%A4%D7%94, ופענוח החלק שאחרי ? (מה ש-Request.QueryString עושה) מחזיר בדיוק "חיפה".
טעות נפוצה: להחליף בין get ל-post, או לקרוא נתוני get בעזרת Request.Form (מתקבל null).
שאלה 2 · מהו DataSet
מהו DataSet?
(1) טבלה בבסיס הנתונים שבה נשמרים פרטי המשתמשים הרשומים באתר.
(2) אובייקט בצד השרת המחזיק בזיכרון עותק של נתונים (טבלה אחת או יותר) שנשלפו מבסיס הנתונים, וניתן לעבור עליו גם לאחר סגירת החיבור לבסיס הנתונים.
(3) פקודת SQL הבוחרת שורות מטבלה לפי תנאי.
(4) אובייקט בצד הלקוח השומר בדפדפן את הנתונים שהמשתמש הקליד בטופס.
מהו DataSet?
◂ פתרון מלא לשאלה 2
פתרון
(2)
מה נדרש – לבחור את ההגדרה הנכונה של DataSet.
רעיון – לזכור את שלבי העבודה עם בסיס הנתונים בצד השרת: פותחים חיבור (SqlConnection), מגדירים פקודה (SqlCommand), ממלאים DataSet בעזרת SqlDataAdapter (Fill), סוגרים את החיבור – ורק אז עוברים על הנתונים.
פתרון
DataSet הוא אובייקט ב-C# (בצד השרת) שמחזיק בזיכרון עותק של הנתונים שנשלפו: טבלה אחת או יותר (ds.Tables[0]), ובכל טבלה שורות (ds.Tables[0].Rows[i]) ועמודות (Rows[i]["title"]). מכיוון שזה עותק בזיכרון, אפשר לסגור את החיבור לבסיס הנתונים ועדיין לקרוא ממנו.
| תשובה | נכון/לא נכון | למה |
|---|---|---|
| (1) | ✘ | DataSet אינו טבלה בבסיס הנתונים, אלא עותק בזיכרון של השרת. |
| (2) | ✔ נכון | זו ההגדרה. |
| (3) | ✘ | זה תיאור של שאילתת SELECT ... WHERE. ה-DataSet מקבל את התוצאה של שאילתה כזו. |
| (4) | ✘ | DataSet הוא בצד השרת, ואינו קשור לטופס בדפדפן. |
התשובה: (2).
בדיקה – דוגמה ב-C#: ממלאים DataSet בטבלה Books עם שתי שורות, סוגרים את החיבור, ואחר כך עוברים בלולאה על ds.Tables[0].Rows ומקבלים את שתי השורות (Alef:120, Bet:340) – הנתונים נשארים זמינים אחרי סגירת החיבור.
שאלה 3 · פלט של פעולת שרת – טבלת סכומים
לפניכם פעולה בשם Show הכתובה בצד שרת. העתיקו למחברתכם את מה שיוצג בדפדפן לאחר הרצת הפעולה Show עם הפרמטר k = 5.
public void Show (int k) {
string str = "<table border = '1'>";
int sum = 0;
for (int i = 1; i <= k; i++)
{
sum += i;
str += "<tr><td>" + i + "</td>";
if (sum % 2 == 0)
str += "<td>" + sum + "</td></tr>";
else
str += "<td><b>Odd</b></td></tr>";
}
str += "</table>";
Response.Write (str);
}העתיקו למחברתכם את מה שיוצג בדפדפן לאחר הרצת הפעולה Show עם הפרמטר k = 5.
◂ פתרון מלא לשאלה 3
פתרון
טבלה עם מסגרת, 5 שורות ו־2 עמודות: (1, Odd), (2, Odd), (3, 6), (4, 10), (5, Odd); המילה Odd מוצגת בכתב מודגש
מה נדרש – לתאר את הטבלה שהדפדפן מציג (לא את קוד ה-HTML).
רעיון – בכל סיבוב של הלולאה (i מ־1 עד 5) נוספת שורה (<tr>) עם שני תאים: בתא הראשון הערך של i, ובתא השני – לפי הזוגיות של הסכום המצטבר sum = 1 + 2 + ... + i. אם sum זוגי נכתב sum, ואחרת נכתבת המילה Odd בתוך <b>, כלומר בכתב מודגש. לכן מתקבלת טבלה עם 5 שורות ו־2 עמודות.
פתרון – מעקב:
| i | sum | sum % 2 == 0 ? | השורה שנוספה |
|---|---|---|---|
| 1 | 1 | לא | <tr><td>1</td><td><b>Odd</b></td></tr> |
| 2 | 3 | לא | <tr><td>2</td><td><b>Odd</b></td></tr> |
| 3 | 6 | כן | <tr><td>3</td><td>6</td></tr> |
| 4 | 10 | כן | <tr><td>4</td><td>10</td></tr> |
| 5 | 15 | לא | <tr><td>5</td><td><b>Odd</b></td></tr> |
המחרוזת שנשלחת לדפדפן:
<table border = '1'><tr><td>1</td><td><b>Odd</b></td></tr><tr><td>2</td><td><b>Odd</b></td></tr><tr><td>3</td><td>6</td></tr><tr><td>4</td><td>10</td></tr><tr><td>5</td><td><b>Odd</b></td></tr></table>מה יוצג בדפדפן – טבלה עם מסגרת, חמש שורות ושתי עמודות (Odd מודגש):
| 1 | Odd |
| 2 | Odd |
| 3 | 6 |
| 4 | 10 |
| 5 | Odd |
בדיקה – עבור k = 5 מתקבלת בדיוק המחרוזת שלמעלה – חמישה <tr>, בכל אחד שני תאים.
טעות נפוצה: לבדוק את הזוגיות של i במקום של sum (למשל לכתוב Odd בשורה 3 ו־2 בשורה 2), או לשכוח ש-sum מצטבר ואינו מתאפס בכל סיבוב.
פרק שני
ענו על שלוש שאלות: על שאלה 4 (חובה – 10 נקודות) ועל שתיים מן השאלות 7-5 (לכל שאלה – 20 נקודות).
שאלה 4 · טבלת HTML – rowspan/colspan וקישור פנימי
מיכל, תלמידת מדעי המחשב, בנתה אתר לשכבה שלה, ובו טבלה של מערכת השעות בשבוע הטיול השנתי.
<!DOCTYPE html>
<html lang="he">
<meta charset="utf-8"/>
<table style="width: 260px" border=2px dir="ltr">
<tr>
<td colspan=3 align="center">מערכת שעות</td>
</tr>
<tr>
<td>Sun</td>
<td>Math</td>
<td rowspan=2>Lab</td>
</tr>
<tr>
<td>Mon</td>
<td>History</td>
</tr>
<tr>
<td>Tue</td>
<td colspan=2 align="center">Trip</td>
</tr>
</table>
</html>כיצד יוצג הדף? כתבו במחברת הבחינה את אות התשובה הנכונה מבין האפשרויות (a-d).

הוסיפו לקוד ה-HTML את מה שנדרש כך שלחיצה על המילה Trip תעביר לדף trip.html, הנמצא באותה תיקייה שבה נמצא דף זה.
◂ פתרון מלא לשאלה 4
סעיף א
b
מה נדרש: לבנות בראש את הטבלה מתוך הקוד ולבחור את התמונה המתאימה.
רעיון: עוברים שורה-שורה (<tr>) וסופרים את העמודות שכל תא תופס (colspan) ואת השורות (rowspan). כאן dir="ltr", ולכן התא הראשון בכל שורה נמצא בצד שמאל.
פתרון – בניית הטבלה (3 עמודות, משמאל לימין):
| שורה | עמודה שמאלית | עמודה אמצעית | עמודה ימנית |
|---|---|---|---|
| 1 | "מערכת שעות" – colspan=3, ממורכז | ← | ← |
| 2 | Sun | Math | Lab – rowspan=2 (שורות 2–3) |
| 3 | Mon | History | (ממשיך Lab) |
| 4 | Tue | Trip – colspan=2, ממורכז | ← |
שימו לב: בשורה 3 כתובים בקוד רק שני תאים (Mon, History), כי העמודה הימנית כבר תפוסה על ידי Lab משורה 2. בשורה 4 Lab כבר הסתיים, ולכן Trip תופס את העמודה האמצעית והימנית. זו בדיוק תמונה b.
למה לא האחרות:
rowspan=2.dir="rtl".rowspan=2 ו-Trip הוא colspan=2.תשובה: b.
בדיקה: רשת התאים לפי rowspan/colspan: 4 שורות ו-3 עמודות, Lab תופס את שורות 2–3 בעמודה הימנית, ו-Trip תופס את שתי העמודות האחרונות בשורה 4. את ארבע התמונות יצרנו בדפדפן, ותמונה b נוצרה מהקוד שבשאלה עצמו.
טעות נפוצה: לחשוב שבשורה 3 חסר תא ולכן יהיה בה חור (תמונה a) – התא החסר "מכוסה" על ידי ה-rowspan של Lab.
סעיף ב
<td colspan=2 align="center"><a href="trip.html">Trip</a></td>
מה נדרש: להפוך את המילה Trip לקישור לדף אחר באותו אתר.
רעיון: קישור נוצר בתגית <a href="...">. כשהדף נמצא באותה תיקייה, מספיק לכתוב ב-href את שם הקובץ בלבד (כתובת יחסית) – אין צורך בכתובת מלאה עם https://. עוטפים את המילה Trip בתגית <a> בתוך התא הקיים, ומשאירים לתא את colspan=2 ואת היישור.
פתרון – מחליפים את השורה
<td colspan=2 align="center">Trip</td>בשורה:
<td colspan=2 align="center"><a href="trip.html">Trip</a></td>הדף המלא אחרי השינוי – בלשונית HTML.
בדיקה: מבנה הטבלה לא משתנה (עדיין כמו בתמונה b – Trip תופס שתי עמודות וממורכז), והמילה Trip היא עכשיו קישור ל-trip.html.
טעות נפוצה: למחוק בטעות את colspan=2 כשמשכתבים את התא – אז Trip יתפוס עמודה אחת בלבד וייווצר חור בטבלה.
שאלה 5 · ניתוב בין דפים לפי משתני Session – אתר תרגול תאוריה
באתר לתרגול מבחן התאוריה "דרך צלחה", בסוף כל סבב תרגול האתר מחליט לאיזה דף להעביר את התלמיד. לשם כך האתר משתמש במספר משתני Session:
בהתבסס על משתנים אלה, המשתמש עובר לדף מתאים לפי החוקיות הבאה:
– אם score גדול או שווה ל-90 וגם finished_all הוא true וגם sign_mistakes שווה ל-0, התלמיד מועבר לדף "מוכן למבחן" readyForTest.aspx.
– אחרת, אם score גדול או שווה ל-70 או ששני התנאים הבאים מתקיימים יחד:
finished_all הוא true וגם sign_mistakes קטן או שווה ל-2,
התלמיד מועבר לדף תרגול נוסף morePractice.aspx.
– שאר התלמידים מועברים לדף השיעורים lessons.aspx.
כתבו קוד המתאים לדרישות.
כתבו קוד המתאים לדרישות.
◂ פתרון מלא לשאלה 5
פתרון
קוראים את שלושת משתני ה-Session עם המרה (int)/(bool), ואז: if (score >= 90 && finished && signs == 0) Response.Redirect("readyForTest.aspx"); else if (score >= 70 || (finished && signs <= 2)) Response.Redirect("morePractice.aspx"); else Response.Redirect("lessons.aspx");
מה נדרש: קוד צד שרת (C#) שמעביר את התלמיד לאחד משלושה דפים לפי ערכי שלושה משתני Session.
רעיון:
(int) למספרים ו-(bool) לבוליאני.&&) נכתב בתוך סוגריים. (ב-C# && קודם ל-|| ולכן גם בלי סוגריים התוצאה זהה, אבל הסוגריים מבהירים את הכוונה.)Response.Redirect("שם הדף").פתרון (בקובץ ה-code behind של הדף):
protected void Page_Load(object sender, EventArgs e)
{
int score = (int)Session["score"];
bool finished = (bool)Session["finished_all"];
int signs = (int)Session["sign_mistakes"];
if (score >= 90 && finished && signs == 0)
Response.Redirect("readyForTest.aspx");
else if (score >= 70 || (finished && signs <= 2))
Response.Redirect("morePractice.aspx");
else
Response.Redirect("lessons.aspx");
}בדיקה: בכל הצירופים של הערכים הקוד מפנה לדף הנכון, לפי הכללים שבשאלה. כמה דוגמאות:
| score | finished_all | sign_mistakes | הדף |
|---|---|---|---|
| 95 | true | 0 | readyForTest.aspx |
| 95 | true | 1 | morePractice.aspx (טעות בתמרורים, אבל ציון ≥ 70) |
| 75 | false | 5 | morePractice.aspx (מספיק ש-score ≥ 70) |
| 60 | true | 2 | morePractice.aspx (ציון נמוך, אבל סיים הכול ועד 2 טעויות) |
| 60 | true | 3 | lessons.aspx |
| 90 | false | 0 | morePractice.aspx (לא סיים את כל הפרקים) |
טעות נפוצה:
score > 90 במקום score >= 90 ("גדול או שווה").Session["score"] >= 90 בלי המרה ל-int – לא עובר הידור.protected void Page_Load(object sender, EventArgs e)
{
int score = (int)Session["score"];
bool finished = (bool)Session["finished_all"];
int signs = (int)Session["sign_mistakes"];
if (score >= 90 && finished && signs == 0)
Response.Redirect("readyForTest.aspx");
else if (score >= 70 || (finished && signs <= 2))
Response.Redirect("morePractice.aspx");
else
Response.Redirect("lessons.aspx");
}שאלה 6 · JavaScript – חילוץ שם ספק הדואר מכתובת
כתובת דואר אלקטרוני בנויה משני חלקים המופרדים בתו @:
א. שם המשתמש (user) – לפני התו @. שם המשתמש עשוי להכיל את התו נקודה (.).
ב. שם השרת (host) – אחרי התו @. שם השרת מתחיל בשם ספק הדואר (provider), ואחריו סיומת אחת או יותר. החלקים של שם השרת מחוברים באמצעות התו נקודה (.).
לדוגמה:
dana@walla.co.il
yossi.cohen@gmail.com
כתבו בשפת JavaScript פונקציה בשם getProvider המקבלת מחרוזת המייצגת כתובת דואר אלקטרוני תקינה ומחזירה מחרוזת המכילה את שם ספק הדואר (provider). לדוגמה:
◂ פתרון מלא לשאלה 6
פתרון
function getProvider(email) { var host = email.split("@")[1]; return host.split(".")[0]; }
מה נדרש – פונקציית JavaScript שמחזירה את החלק שבין התו @ לבין הנקודה הראשונה שאחריו.
רעיון – מפרקים בשני שלבים:
email.split("@") מחזיר מערך של שני חלקים: שם המשתמש ושם השרת. שם השרת הוא האיבר באינדקס 1."." – שם הספק הוא האיבר הראשון (אינדקס 0).אסור לפרק את כל הכתובת לפי נקודה, כי גם בשם המשתמש יכולות להיות נקודות.
פתרון
function getProvider(email) {
var host = email.split("@")[1]; // the part after @, e.g. "walla.co.il"
var parts = host.split("."); // ["walla", "co", "il"]
return parts[0];
}פתרון חלופי עם indexOf ו־substring – מוצאים את מקום ה־@, ואז את הנקודה הראשונה שאחריו (החיפוש מתחיל ממקום at + 1):
function getProvider(email) {
var at = email.indexOf("@"); // position of @
var dot = email.indexOf(".", at + 1); // first dot AFTER the @
return email.substring(at + 1, dot);
}בדיקה – שתי הגרסאות:
getProvider("dana@walla.co.il") → wallagetProvider("yossi.cohen@gmail.com") → gmaila.b.c@bezeqint.net → bezeqint, noa@012.net.il → 012.טעות נפוצה: לכתוב email.split(".")[0] או לחפש את הנקודה הראשונה במחרוזת כולה (email.indexOf(".")). עבור yossi.cohen@gmail.com זה נותן yossi, כי הנקודה הראשונה נמצאת בשם המשתמש. לכן חייבים להתחיל מהתו @.
שאלה 7 · מונה לייקים בתחרות צילום – Session או Application
לפניכם דף האינטרנט הבא (צד שרת) מתוך אתר של תחרות צילום:
הדף מציג תמונה וכפתור "אהבתי". מטרת התוכנית היא להציג את מספר הלייקים שהתמונה קיבלה מכל הגולשים באתר יחד, ולהגדיל אותו באחד בכל לחיצה על הכפתור, אולם התוכנית אינה מבצעת את הנדרש.
רשמו והסברו היכן התקלות וכיצד ניתן לתקנן.
<%@ Page Language="C#" %>
<script runat="server">
public void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Session["likes"] = 0;
}
}
void Like_Click(object sender, EventArgs e)
{
Session["likes"] = Session["likes"].ToString() + 1;
}
</script>
<html>
<head>
</head>
<body>
<form id="form1" runat="server">
<img src="sunset.jpg" alt="שקיעה בכנרת" />
<input type="button" runat="server" id="btnLike" value="אהבתי" onserverclick="Like_Click" />
<div runat="server" id="div1">
מספר הלייקים: <% =Session["likes"] %>
</div>
</form>
</body>
</html>רשמו והסברו היכן התקלות וכיצד ניתן לתקנן.
◂ פתרון מלא לשאלה 7
פתרון
(1) Session["likes"].ToString() + 1 משרשר מחרוזות: מוצג 0, 01, 011... – צריך המרה למספר: (int)...+1. (2) המונה נשמר ב-Session, שהוא נפרד לכל גולש – צריך Application, שמשותף לכל הגולשים. באתחול: לאתחל Application["likes"] = 0 רק אם הוא null (ולא בכל כניסה של גולש חדש), ובלחיצה Application["likes"] = (int)Application["likes"] + 1 (עם Lock/UnLock), ולהציג <% =Application["likes"] %>.
מה נדרש – למצוא למה המונה אינו עובד כנדרש, ולתקן.
רעיון – לבדוק שני דברים: (1) מה קורה לערך בכל לחיצה – מה הטיפוס שלו ואיזו פעולה מתבצעת עליו; (2) איפה הערך נשמר – Session הוא נפרד לכל גולש, ואילו Application משותף לכל הגולשים באתר.
פתרון
Session["likes"].ToString() + 1 הוא מחרוזת ועוד מספר, ולכן ב-C# זה שרשור: "0" + 1 = "01", ואחר כך "011", "0111"... במקום 1, 2, 3. צריך להמיר למספר: (int) או Convert.ToInt32.if (!IsPostBack) Application["likes"] = 0;, אז כל גולש חדש שנכנס לדף יאפס את המונה של כולם. לכן מאתחלים רק אם המונה עדיין לא קיים (== null), כלומר פעם אחת מאז שהאתר עלה.התיקון – קטע הסקריפט המתוקן (Lock/UnLock מונעים ששני גולשים ישנו את המונה בדיוק באותו זמן):
public void Page_Load(object sender, EventArgs e)
{
Application.Lock();
if (Application["likes"] == null) // only the first visitor since the site started
{
Application["likes"] = 0;
}
Application.UnLock();
}
void Like_Click(object sender, EventArgs e)
{
Application.Lock();
Application["likes"] = (int)Application["likes"] + 1;
Application.UnLock();
}ושורת התצוגה בדף:
<div runat="server" id="div1">
מספר הלייקים: <% =Application["likes"] %>
</div>(אפשר גם לאתחל את Application["likes"] פעם אחת ב-Application_Start שבקובץ Global.asax.)
בדיקה – הדמינו שני גולשים (שני Session נפרדים ו-Application משותף), כשבכל בקשה נוצר אובייקט דף חדש:
| בקשה | הדף המקורי | הדף המתוקן |
|---|---|---|
| גולש א' נכנס | 0 | 0 |
| גולש א' לוחץ | 01 | 1 |
| גולש א' לוחץ | 011 | 2 |
| גולש ב' נכנס | 0 | 2 |
| גולש ב' לוחץ | 01 | 3 |
| גולש א' לוחץ | 0111 | 4 |
טעות נפוצה: לתקן רק את ההמרה למספר – אז כל גולש סופר לעצמו; או לעבור ל-Application אבל להשאיר את האיפוס ב-!IsPostBack – אז כל כניסה של גולש חדש מאפסת את המונה.
public void Page_Load(object sender, EventArgs e)
{
Application.Lock();
if (Application["likes"] == null) // only the first visitor since the site started
{
Application["likes"] = 0;
}
Application.UnLock();
}
void Like_Click(object sender, EventArgs e)
{
Application.Lock();
Application["likes"] = (int)Application["likes"] + 1;
Application.UnLock();
}פרק שלישי
ענו על שאלה אחת מן השאלות 9-8.
שאלה 8 · ASP.NET ומסד נתונים – קבלה למרפאה (השלמת קוד)
בעמדת קבלה ממוחשבת במרפאה נדרש המטופל להזין את מספר המטופל שלו ואת שם הרופא שאליו הוא הגיע:
<input type="text" name="patientId" id="patientId"/>
<input type="text" name="doctor" id="doctor"/>במסד הנתונים של המרפאה קיימת טבלה בשם appointments ובה שתי עמודות:
patientId (טקסט), מספר המטופל
doctor (טקסט), שם הרופא שאצלו נקבע התור
לכל מטופל עשויים להיות כמה תורים להיום, אצל רופאים שונים, ולכן מספר מטופל יכול להופיע בטבלה ביותר משורה אחת.
דוגמה לתוכן הטבלה:
| patientId | doctor |
|---|---|
| 311 | Katz |
| 311 | Peretz |
| 522 | Katz |
לפניכם קטע קוד חלקי של פעולה בשם CheckAppointment שמטרתה לבדוק את הנתונים שהוזנו על ידי המטופל. בהתאם לתוצאות הבדיקה, יש להפנות את המטופל לעמוד מתאים לפי הכללים הבאים:
עליכם להשלים את הקוד החסר.
protected void CheckAppointment(string connectionString)
{
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand();
DataSet ds = new DataSet();
command.CommandText = string.Format(
"SELECT * FROM appointments WHERE patientId = '{0}'",
Request.Form["patientId"]);
command.Connection = connection;
connection.Open();
SqlDataAdapter adapter = new SqlDataAdapter(command);
adapter.Fill(ds);
connection.Close();
// *************** השלימו כאן ***************
}עליכם להשלים את הקוד החסר.
◂ פתרון מלא לשאלה 8
פתרון
לולאה על ds.Tables[0].Rows שמחפשת שורה עם doctor == Request.Form["doctor"] (found = true); אם Rows.Count == 0 ⇐ noAppointments.aspx, אחרת אם !found ⇐ wrongDoctor.aspx, אחרת ⇐ checkIn.aspx.
מה נדרש – להשלים את סוף הפעולה: לפי השורות שהשאילתה החזירה ל-ds, להפנות לאחד משלושת העמודים.
רעיון
ds.Tables[0].Rows.Count הוא 0 ⇐ noAppointments.aspx.Rows[i]["doctor"].ToString() שווה ל-Request.Form["doctor"]; אם נמצאה – מסמנים found = true.פתרון – הקוד להשלמה (במקום ההערה "השלימו כאן"):
bool found = false;
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
if (ds.Tables[0].Rows[i]["doctor"].ToString() == Request.Form["doctor"])
found = true;
}
if (ds.Tables[0].Rows.Count == 0)
Response.Redirect("noAppointments.aspx");
else if (!found)
Response.Redirect("wrongDoctor.aspx");
else
Response.Redirect("checkIn.aspx");(כשאין שורות הלולאה לא מתבצעת כלל, found נשאר false, והבדיקה הראשונה מפנה ל-noAppointments.aspx.)
בדיקה – ההשלמה עם DataSet שמולא בתוצאת השאילתה, על טבלת הדוגמה בתוספת תור שלישי למטופל 311 אצל Levin:
| patientId | doctor שהוזן | שורות שהוחזרו | דף |
|---|---|---|---|
| 311 | Katz | Katz, Peretz, Levin | checkIn.aspx (השורה הראשונה) |
| 311 | Peretz | Katz, Peretz, Levin | checkIn.aspx (שורה אמצעית) |
| 311 | Levin | Katz, Peretz, Levin | checkIn.aspx (השורה האחרונה) |
| 311 | Amsalem | Katz, Peretz, Levin | wrongDoctor.aspx |
| 522 | Katz | Katz | checkIn.aspx |
| 522 | Peretz | Katz | wrongDoctor.aspx |
| 700 | Katz | אין | noAppointments.aspx |
השאילתה: עבור '311' מוחזרות שתי שורות (Katz, Peretz), עבור '522' – שורה אחת, ועבור '700' – אין שורות.
טעות נפוצה: לבדוק רק את Rows[0] – אז מטופל 311 שהגיע ל-Peretz יופנה בטעות ל-wrongDoctor.aspx. טעות נוספת: לבצע Response.Redirect("wrongDoctor.aspx") בתוך הלולאה ברגע ששורה אחת לא מתאימה, לפני שבדקו את כל השורות.
bool found = false;
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
if (ds.Tables[0].Rows[i]["doctor"].ToString() == Request.Form["doctor"])
found = true;
}
if (ds.Tables[0].Rows.Count == 0)
Response.Redirect("noAppointments.aspx");
else if (!found)
Response.Redirect("wrongDoctor.aspx");
else
Response.Redirect("checkIn.aspx");שאלה 9 · השלמת פעולה המציגה טבלת סרטים
במסד הנתונים של מועדון קולנוע יש טבלה בשם Movies ובה ארבע עמודות: title (שם הסרט, טקסט), genre (סוגה, טקסט), minutes (אורך הסרט בדקות, מספר שלם), year (שנת יציאה, מספר שלם).
דוגמה לטבלה:
| year | minutes | genre | title |
|---|---|---|---|
| 2014 | 169 | מדע בדיוני | מסע בין כוכבים |
| 2003 | 100 | אנימציה | הדג הקטן |
| 1978 | 120 | קומדיה | הלהקה |
| 2001 | 178 | פנטזיה | שר הטבעות |
| 2019 | 95 | דרמה | הבית בהר |
מנהל המועדון מעוניין להפיק טבלה ובה כל פרטי הסרטים שאורכם יותר מ-120 דקות.
הפונקציה showLongMovies מקבלת מחרוזת התחברות למסד הנתונים – connectionString – ומציגה בטבלת HTML את כל פרטי הסרטים המתאימים (כפי שהם מופיעים בטבלה Movies).
בפונקציה חסרים חמישה ביטויים המסומנים במספרים בין סוגריים עגולים. כתבו במחברת הבחינה את מספרי הביטויים החסרים (1) – (5), בסדר עולה, וכתבו ליד כל מספר את הביטוי החסר שהוא מייצג.
protected void showLongMovies(string connectionString)
{
string html = "";
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select * from _____(1)_____ where _____(2)_____";
cmd.Connection = _____(3)_____;
conn.Open();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds);
conn.Close();
html += "<table border='1'><tr><th>title</th><th>genre</th><th>minutes</th><th>year</th></tr>";
foreach (DataRow row in _____(4)_____)
{
_____(5)_____
}
html += "</table>";
Response.Write(html);
}כתבו במחברת הבחינה את מספרי הביטויים החסרים (1) – (5), בסדר עולה, וכתבו ליד כל מספר את הביטוי החסר שהוא מייצג.
◂ פתרון מלא לשאלה 9
פתרון
Moviesminutes > 120connds.Tables[0].Rowshtml += "<tr><td>" + row["title"] + "</td><td>" + row["genre"] + "</td><td>" + row["minutes"] + "</td><td>" + row["year"] + "</td></tr>";מה נדרש: להשלים חמישה ביטויים בפונקציה ששולפת מהמסד את הסרטים שאורכם יותר מ-120 דקות ובונה מהם טבלת HTML.
רעיון – מעבר על הפונקציה לפי הסדר:
Movies.minutes > 120.conn (ולא connection) ⇐ conn.ds.Tables[0].Rows.html שורת טבלה <tr> עם ארבעה תאים <td>, לפי סדר הכותרות (title, genre, minutes, year):html += "<tr><td>" + row["title"] + "</td><td>" + row["genre"] + "</td><td>" + row["minutes"] + "</td><td>" + row["year"] + "</td></tr>";(אפשר גם לפי מספרי עמודות: row[0] … row[3].)
פתרון – תשובה במחברת:
Moviesminutes > 120connds.Tables[0].Rowshtml += "<tr><td>" + row["title"] + "</td><td>" + row["genre"] + "</td><td>" + row["minutes"] + "</td><td>" + row["year"] + "</td></tr>";הפונקציה המלאה – בלשונית C#.
בדיקה:
select * from Movies where minutes > 120 על טבלת הדוגמה מחזירה 2 סרטים – מסע בין כוכבים (169) ושר הטבעות (178). הלהקה (120 בדיוק) לא הוחזר, כי 120 אינו יותר מ-120.<tr><td>שר הטבעות</td><td>פנטזיה</td><td>178</td><td>2001</td></tr>.טעות נפוצה: בסעיף (2) לכתוב minutes >= 120 – אז גם הלהקה יוצג. בסעיף (3) לכתוב connection – אין משתנה כזה בפונקציה. בסעיף (5) לשכוח את <tr>/</tr> – אז כל התאים יופיעו באותה שורה.
protected void showLongMovies(string connectionString)
{
string html = "";
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select * from Movies where minutes > 120";
cmd.Connection = conn;
conn.Open();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds);
conn.Close();
html += "<table border='1'><tr><th>title</th><th>genre</th><th>minutes</th><th>year</th></tr>";
foreach (DataRow row in ds.Tables[0].Rows)
{
html += "<tr><td>" + row["title"] + "</td><td>" + row["genre"] + "</td><td>" + row["minutes"] + "</td><td>" + row["year"] + "</td></tr>";
}
html += "</table>";
Response.Write(html);
}טבלת התשובות
| שאלה | סעיף | תשובה |
|---|---|---|
| 1 | - | ג. הנתונים נשלחים לשרת כחלק מכתובת ה-URL (אחרי הסימן ?), ובצד השרת קוראים אותם בעזרת Request.QueryString |
| 2 | - | (2) |
| 3 | - | טבלה עם מסגרת, 5 שורות ו־2 עמודות: (1, Odd), (2, Odd), (3, 6), (4, 10), (5, Odd); המילה Odd מוצגת בכתב מודגש |
| 4 | א | b |
| ב |
| |
| 5 | - | קוראים את שלושת משתני ה-Session עם המרה (int)/(bool), ואז: if (score >= 90 && finished && signs == 0) Response.Redirect("readyForTest.aspx"); else if (score >= 70 || (finished && signs <= 2)) Response.Redirect("morePractice.aspx"); else Response.Redirect("lessons.aspx"); |
| 6 | - | function getProvider(email) { var host = email.split("@")[1]; return host.split(".")[0]; } |
| 7 | - | (1) Session["likes"].ToString() + 1 משרשר מחרוזות: מוצג 0, 01, 011... – צריך המרה למספר: (int)...+1. (2) המונה נשמר ב-Session, שהוא נפרד לכל גולש – צריך Application, שמשותף לכל הגולשים. באתחול: לאתחל Application["likes"] = 0 רק אם הוא null (ולא בכל כניסה של גולש חדש), ובלחיצה Application["likes"] = (int)Application["likes"] + 1 (עם Lock/UnLock), ולהציג <% =Application["likes"] %>. |
| 8 | - | לולאה על ds.Tables[0].Rows שמחפשת שורה עם doctor == Request.Form["doctor"] (found = true); אם Rows.Count == 0 ⇐ noAppointments.aspx, אחרת אם !found ⇐ wrongDoctor.aspx, אחרת ⇐ checkIn.aspx. |
| 9 | - | •(1) Movies•(2) minutes > 120•(3) conn•(4) ds.Tables[0].Rows•(5) html += "<tr><td>" + row["title"] + "</td><td>" + row["genre"] + "</td><td>" + row["minutes"] + "</td><td>" + row["year"] + "</td></tr>"; |