1 / 8

תכנות מערכות בשפת C

מכללת אורט כפר-סבא. תכנות מערכות בשפת C. כתיבת מאקרו הפקודה assert. 11.12.13. אורי וולטמן. uri.weltmann@gmail.com. חידה לחימום. ברשותך עשר שקיות שבכל אחת מהן עשרה מטבעות. משקלו של כל מטבע עשרה גרם, אך אחת השקיות מכילה מטבעות מזויפים, שמשקל כל אחד מהם תשעה גרם בלבד.

chinue
Download Presentation

תכנות מערכות בשפת C

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. מכללת אורט כפר-סבא תכנות מערכות בשפת C כתיבת מאקרו הפקודה assert 11.12.13 אורי וולטמן uri.weltmann@gmail.com

  2. חידה לחימום • ברשותך עשר שקיות שבכל אחת מהן עשרה מטבעות. משקלו של כל מטבע עשרה גרם, אך אחת השקיות מכילה מטבעות מזויפים, שמשקל כל אחד מהם תשעה גרם בלבד. • ברשותך מאזניים שמראים את המשקל המדויק (בגרמים) של המטבעות המונחים עליהם. • איך תוכל לדעת, באמצעות שקילה אחת בלבד, באיזו שקית נמצאים המטבעות המזויפים?

  3. חידה לחימום • במדינה זרה, יש שלושה סוגי מטבעות: • מטבע נחושת שערכו 6 שקלים • מטבע כסף שערכו 10 שקלים • מטבע זהב שערכו 15 שקלים • על השולחן נמצאים מספר מטבעות, אשר ערכם הכולל הוא 47 שקלים. • כמה מטבעות יש מכל סוג על השולחן? (יש למצוא את כל התשובות האפשריות)

  4. מאקרו • ניתן להשתמש בקדם-מעבד על מנת להגדיר מאקרו (Macro), שזו התנהגות של הקדם-מעבד שפועלת על הקוד, ומחקה התנהגות של פונקציה. • לדוגמא, נכתוב מאקרו בשם F2C המקבל טמפרטורה במעלות פרנהייט, וממיר אותה לטמפרטורה במעלות צלזיוס: #define F2C(F) (((F)-32)*(5/9.0)) • ואז אם נכתוב: printf (“%d”, F2C(100)); • אחרי פעולת הקדם-מעבד, שורה זו תקומפל כך: printf (“%d”, (((100)-32)*(5/9.0))); • דוגמא נוספת: מאקרו המקבל זווית ברדיאנים, וממיר אותה לזווית במעלות: #define RAD_TO_DEG(x) ((x)*57.29578) • כשמגדירים מאקרו, פתיחת הסוגריים (עבור הפרמטר) חייבת להיות צמודה לשם המאקרו.

  5. מאקרו • דוגמא למאקרו המקבל פרמטר ומעלה אותו בריבוע: #define SQR(x) ((x)*(x)) מדוע זקוקים לכל זוגות הסוגריים הללו? • נניח והיינו רושמים את המאקרו כך (עם זוג הסוגריים החיצוניים, אך ללא שתי זוגות הסוגריים הפנימיים): #define SQR(x) (x*x) מה היה קורה אם מישהו היה כותב איפשהו בקוד את הביטוי SQR(2+3)? • זה היה מתורגם ל: (2+3*2+3), וזה, כמובן, לא מה שהיינו רוצים לקבל. • ונניח והיינו רושמים את המאקרו כך (עם שתי זוגות הסוגריים הפנימיים, אך ללא זוג הסוגריים החיצוניים): #define SQR(x) (x)*(x) הייתה נוצרת בעיה עבור ביטוי כגון זה: 1.0 / SQR(5) . • זה היה מתורגם ל: 1.0 / (5) * (5) , כלומר: זה היה קודם מבצע את החלוקה בחמש, ורק לאחר מכן את הכפל (בניגוד לכפי שהיינו מעוניינים שיקרה).

  6. מאקרו • ניתן להגדיר מאקרו על פני יותר משורה אחת, על-ידי שימוש בתו \ : #define PRINTME(x) printf(“the number \ received is %d”, (x)) • מדוע לדעתכם לא כתבנו ; (נקודה פסיק) בסוף השורה השנייה בהגדרת המאקרו? • ניתן להגדיר גם מאקרו המקבל יותר מפרמטר אחד: #define MAX(a,b) ((a) > (b) ? (a) : (b)) • נשים לב שבמאקרו הזה ישנם פרמטרים המופיעים בגוף המאקרו יותר מפעם אחת. זה עשוי ליצור בעיות, למשל במקרה של זימון כגון: MAX(++num1,num2) • שיתורגם לביטוי: ((++num1) > (num2) ? (++num1) : (num2)) • עלולה להתרחש כאן הגדלה של המשתנה num1 ב-2, וברור שלא לזה התכוונו. • כאשר כותבים מאקרו, חשוב להיזהר מפני סכנות (hazards) כגון אלו, ובמידת הצורך לתעד אותן בהערות, על מנת שמתכנתים שעושים שימוש במאקרו זה ידעו להימנע מהן.

  7. אחת מיחידות הספרייה הסטנדרטיות של שפת C היא יחידת הספרייה assert.h, המכילה מאקרו בשם assert. זהו מאקרו דמוי-פונקציה, המקבל כפרמטר ביטוי, ובודק האם הביטוי הוא שקרי (כלומר – שווה לאפס). במידה והביטוי אינו שקרי – דבר אינו קורה. במידה והביטוי שקרי – התכנית עוצרת את ריצתה באמצע, ומודפסת הודעת שגיאה (הנשלחת ל-stderr) המפרטת מהו הביטוי שכשל, באיזה קובץ קוד מקור זה אירע, ובאיזה שורה בקובץ. ניתן להשתמש במאקרו זה בעת ניפוי שגיאות מתכנית, כדי לוודא האם ערכי משתנים אינם כפי שהיינו רוצים שיהיו. לדוגמא: נניח שאנו כותבים תוכנה לניהול חשבונות, ואחת לכמה זמן אנחנו מבחינים כי התוכנה מציגה ערכים שגויים. לאחר בדיקה, ההשערה שלנו היא שהמשתנה interest_rate, שאמור תמיד להיות אי-שלילי, מקבל איכשהו ערך שלילי. כדי לבדוק זאת, נכניס את ההוראה הבאה למקומות בתוכנה, לפני שעושים שימוש במשתנה: assert (interest_rate >= 0); אם אי פעם נגיע לנקודה זו, וערכו של המשתנה יהיה שלילי, אז המאקרו יעצור את ריצת התכנית, והודעה מתאימה תוצג. זה יאפשר לנו לדבג את התכנית, ולחפש את הסיבה לכך שהמשתנה קיבל ערך שלילי, דבר שלא היה אמור לקרות. assert

  8. דוגמא לשימוש ב-assert: #define NDEBUG #include <stdio.h> #include <assert.h> int main() { int x; scanf ("%d", &x); assert(x >= 0); printf ("\nYou've entered %d", x); return 0; } assert • כדי "לכבות" את המאקרו assert, ניתן להכליל בראש התכנית, לפני ההוראה #include <assert.h>, את ההגדרה של הקבוע NDEBUG. • הדבר מאותת ל-assert.h כי איננו מעוניינים כרגע לנפות שגיאות, ולכן המאקרו assert יהיה נטול השפעה. • הדבר שימושי כדי להפסיק בבת אחת את פעולת כל הזימונים של המאקרו assert ברחבי הקוד, מבלי שנצטרך לסרוק את הקוד ולמחוק.

More Related