נושא 1- הקדמה לשפת C

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 4

‫‪Dvir Ben Asuli‬‬ ‫‪11/03/2020‬‬

‫נושא ‪ -1‬הקדמה לשפת ‪C‬‬

‫תקן ‪ -ANSI C‬תקן אמריקאי לסטנדרט כתיבה בו נכתוב את הקוד שלנו בקורס‪.‬‬

‫פונקציית הדפסה )(‪-printf‬‬


‫לפונקציה נעביר את המשתנה שנרצה להדפיס כארגומנט שני‪ -‬והוא יהיה הפרמטר שנרצה להדפיס‪ .‬בארגומנט הראשון נעביר‬
‫כלשהו אינדיקטור של באיזה אופן נרצה שהמשתנה שנכניס כפרמטר יקרא ויודפס‪.‬‬
‫הארגומנט הראשון יהיה מחרוזת שבו יופיעו אחוזים )כלומר הסימן "‪ ("%‬ואחריו כלשהי אות‪ ,‬שהיא האינדיקטור‪.‬‬
‫אם נרשום ‪ -%c‬נרצה להדפיס את המשתנה שהעברנו כאות‪.‬‬
‫אם נרשום ‪ -%d‬נרצה להדפיס את המשתנה שהעברנו כמספר‪.‬‬
‫אם נרשום ‪ %f‬נרצה להדפיס את המשתנה שהעברנו כשבר עשרוני‪.‬‬
‫וכדומה‪.‬‬
‫בעצם מחרוזת הבקרה הנ"ל תכיל את הסימן ‪ %‬בצירוף עם אות כמספר הארגומנטים שנעביר כפרמטר לפקודת ההדפסה‪,‬‬
‫כך שכל אינדיקטור שכזה יהיה משויך לאחד מהפרמטרים לפי הסדר שלהם‪.‬‬
‫כמו כן מחרוזת הבקרה תיגמר ב"‪ -"\n‬תו ירידת שורה‪.‬‬
‫נזכור שכמחרוזת בינארית‪ ,‬גם תו מיוצג על ידי כלשהו מספר‪ -‬למשל התו ’‪ ‘a‬מיוצג על ידי המספר ‪ .97‬כאשר במשתנה מופיע‬
‫כרך מספרי מסוים‪ ,‬בעצם מחרוזת הבקרה למשל תגיד למחשב אם להדפיס את הערך המספרי של מחרוזת זו‪ ,‬או את התו‬
‫שמייצגת מחרוזת זו כאשר היא מתפקדת כ‪.char-‬‬

‫כלומר חשוב לזכור שכלל המשתנים‪ ,‬אם הם מספרים או תווים‪ ,‬מיוצגים בזיכרון המחשב על ידי מחרוזת בינארית‪ ,‬שמייצגת‬
‫מספר‪ .‬על פי הטיפוס שנייחס למשתנה המחשב ידע כיצד להתייחס למחרוזת זו )כלומר אם למחרוזת שמייצגת את המספר‬
‫'‪ '97‬לייחס את המספר ‪ 97‬או את האות '‪ ,('a‬ולכן גם בפקודת הדפסה‪ ,‬כאשר אנחנו רוצים שערך משתנה יפלט יש להגדיר‬
‫כיצד התוכנה תפרש את המחרוזת שמאוכסנת במשתנה זה‪.‬‬

‫קבועים מחרוזתיים‪ -‬אם יש למשל מחרוזת "‪ ,"abcd‬מבחינת הזיכרון יש סיקוונס של ‪ 5‬אותיות )‪ ‘a’,’b’,c’,’d’ :(Char‬ואז‬
‫התו ’‪ .‘/0‬לתו האחרון הזה יש חשיבות שכן הוא מסמל את הסיום של מחרוזת‪.‬‬
‫נשים לב להבדל חשוב‪ ‘a’ -‬זה טיפוס מסוג ‪ ,Char‬שבעצם מכיל את הערך המספרי ‪ 97‬ובהקשר המתאים התוכנה יודעת לפרש‬
‫אותו כאות ולא כערך המספרי הזה‪ .‬לעומתו "‪ "a‬זה רצף של מספר ‪ ,Chars‬שאחד מהם הוא אותו ’‪ ‘a‬והשני ’‪ .‘/0‬מדובר‬
‫בשני עצמים שונים לחלוטין‪.‬‬

‫‪1‬‬ ‫‪Tel-Aviv University‬‬


‫‪Dvir Ben Asuli‬‬ ‫‪11/03/2020‬‬

‫הצהרת פרמטרים‪ -‬בדומה לג'אווה‪ ,‬בעת יצירת משתנה יש להצהיר על הסוג שלו תחילה‪.‬‬
‫כמו כן ניתן לבצע ‪ casting‬של טיפוס מסוג אחד לסוג אחר‪ .‬למשל במשתנה מאוכסן המספר העשרוני ‪ 3.3‬כטיפוס ‪.double‬‬
‫במידה וניקח את המשתנה ונעשה לו קאסטינג ל‪ ,d-‬זה יעגל את המספר כלפי מטה וישמור במשתנה את הערך ‪.3‬‬

‫"טיפוס בוליאני" אינו קיים בשפת ‪ .C‬במקום זה‪ ,‬מה שמכיל את המספר ‪ 0‬ייחשב כמה שהכרנו ‪ ,False‬ומה שמכיל את‬
‫המספר ‪ 1‬ייחשב כמה שהכרנו כ‪.True -‬‬
‫אופרטורים בוליאניים קיימים כמו בג'אווה‪ .‬כאשר נכתוב ביטוי שכזה‪ ,‬תוך שימוש ב‪ && -‬או ||\ הביטוי יקבל ערך "‪ "0‬או‬
‫"‪ "1‬בהתאם לערך האמת של הפסוק‪.‬‬

‫פונקציות‪-‬‬
‫העברת פרמטרים לפונקציה בשפת ‪ C‬נעשית תמיד ‪ .by value‬כלומר‪ ,‬אנחנו מעבירים את הערך של משתנה מסוים לפריים‬
‫הספציפי של פונקציה וכעת הוא מאוכסן במשתנה פורמלי של הפונקציה הזו‪ -‬משתנה שחי ומת בפריים הגלובלי של‬
‫הפונקציה‪ .‬במידה ולמשל ניקח את המשתנה החיצוני המקורי ונשנה אותו לא יקרה כלום לזה שבפנים‪ ,‬וגם אפילו אם נשנה‬
‫את המשתנה הפורמלי בפנים מבלי ל ה ח ז י ר א ו ת ו ב א ו פ ן מ פ ו ר ש ‪ ,‬ע ר ך ה מ ש ת נ ה ה מ ק ו ר י ש ה י ה ל נ ו ב ח ו ץ ל א י ש ת נ ה כ ל ל ‪ .‬א ם‬
‫נרצה לשלוף את הערך שחישבנו בפונקציה אחרי כל השינויים לפריים הכללי‪ ,‬נצטרך להשתמש בפקודת ‪ Return‬ולשמור את‬
‫ערך זה במשתנה חדש )או אפילו לדרוס מפורשות את הישן(‪.‬‬
‫במילים אחרות כאשר מעבירים ארגומנט לפונקציה‪ ,‬מתבצעת העתקה של ערך המשתנה למשתנה מקומי של הפונקציה‪ ,‬כך‬
‫שאין שום קשר אמיתי בין השניים‪ .‬דבר זה נכון עבור כל טיפוס שהוא‪ ,‬ללא יוצא מן הכלל )בניגוד לבג'אווה ופייתון(‪.‬‬

‫כתיבת פרויקט בשפת ‪: C‬‬


‫ק ו ב ץ ע ם ס י ו מ ת ‪ c‬ה ו א ק ו ב ץ ר ג י ל ש כ ת ו ב ב ש פ ת ‪ .C‬ל מ ש ל א ם נ ר ש ו ם ת ו כ נ י ת ו נ כ ת ו ב א ו ת ה ב מ ס פ ר ק ב צ י ם ‪ ,‬כ ל ק ו ב ץ ה ו א ז ה‬
‫שנכנס לקומפיילר‪ ,‬שכמו בג'אווה בין השאר בודק את תקינות הקוד מכל מיני שגיאות‪ .‬לאחר מכן ייצור עבור כל אחד‬
‫מהקבצים הנ"ל קובץ ‪) Object‬סיומת ‪ .(o‬לאחר מכן לוקחים את כל קבצי ה‪ o-‬השונים המייצגים את התוכנים ועושים להם‬
‫‪ Link‬ליצירת קובץ ‪ Executable‬שניתן להריץ בפועל‪.‬‬

‫הצהרת ‪ -Static‬עבור משתנים ופונקציות‪ ,‬בדומה לג'אווה‪ ,‬אם נגדיר משהו כ‪ Static -‬הוא יאוחסן בזיכרון באופן אחר‪.‬‬
‫משתנה סטטי חי בתוך ה‪ Scope -‬של הפונקציה בו הוא מוגדר בלבד‪ ,‬אך הוא נשאר קבוע לאורך כל זמן ריצת התוכנית‪ .‬כך‬
‫למשל אם נאתחל משתנה סטטי בתוך פונקציה‪ -‬הערך שלו יאותחל בקריאה הראשונה לפונקציה והוא לא "יידרס" לערך‬
‫התחלתי זה כל פעם שנפעיל את הפונקציה‪ .‬תמיד הוא יהיה שמור ברקע עם הערך העכשווי שלו‪ ,‬וגם ניתן יהיה לשנות אותו‬

‫‪2‬‬ ‫‪Tel-Aviv University‬‬


‫‪Dvir Ben Asuli‬‬ ‫‪11/03/2020‬‬

‫באופן אקטיבי במהלך התוכנית )אם נרצה למשל לעשות לו פלוס ‪ 2‬בכל פעם שנעשה משהו ספציפי בפונקציה למשל(‪ -‬אך‬
‫האתחול שלו יתבצע רק בפעם הראשונה‪.‬‬
‫המילה ‪ Static‬כאמור יכולה להיצמד גם להצהרה של פונקציה‪ .‬המשמעות של זה בהקשר הזה זה שלפונקציות אלו ניתן‬
‫לקרוא אך ורק מאותו הקובץ ולא מקבצים אחרים )ניתן להסתכל על זה כמו על הצהרת ‪ Private‬על פונקציה בג'אווה(‪.‬‬

‫‪Prototype‬‬
‫הקומפיילר של שפת ‪ C‬הוא עצלן ועובר על התוכנית רק פעם אחת‪ .‬לכן‪ ,‬בניגוד לבג'אווה או פייתון למשל‪ ,‬לא נוכל להשתמש‬
‫בפונקציה ‪ V1‬אם הגדרנו אותה רק בשורה יותר תחתונה לאיפה שקראנו אליה‪ .‬כלומר על מנת‬
‫להשתמש בפונקציה‪ ,‬חייבת להיות הצהרה עליה בכלשהי שורה מעל השורה שבה קראנו לה‪ .‬נשים לב‬
‫שתנאי זה מחייב אך ורק לקומפילציה‪ .‬לכן‪ ,‬ניתן לפתור בעיה זו על ידי יצירת ‪.Prototype‬‬
‫במקרה הרגיל‪ ,‬היינו מגדירים פונקציה ואז משתמשים בה‪ .‬אם נרצה לממש פיזית את הפונקציה‬
‫מאוחר יותר‪ ,‬אך להשתמש בה בשורות עליונות יותר בקוד עוד לפני שכתבנו אותה‪ ,‬נוכל לרשום‬
‫‪ Prototype‬לפונקציה זו שהוא פשוט הצהרה ריקה על הפונקציה והארגומנטים שהיא מקבלת מבלי‬
‫להיכנס למימוש הספציפי‪ -‬רק להגיד שפונקציה שכזו עם חתימה שכזו קיימת בפריים של התוכנית‪.‬‬
‫כעת נוכל לרשום ו"להפעיל" את ‪ V1‬כמה פעמים שנרצה‪ ,‬למרות שעדיין לא כתבנו את המימוש שלה‪,‬‬
‫ורק באיזושהי שורה מתחת לכתוב את המימוש הקונקרטי של ‪ .V1‬בצורה זו הקומפיילר לא יתקל‬
‫בבעיה‪ ,‬והתוכנית תתקמפל באופן רגיל‪ -‬ולאחר הקומפילציה בקובץ ה‪ Exe-‬שמסתכל על התמונה‬
‫הכוללת ייחשב גם אותו מימוש לפונקציה שכתוב במקום מאוחר יותר בתוכנית‪ ,‬ואז בכל קריאה של‬
‫‪ V1‬המחשב ידע מה הוא צריך לעשות‪.‬‬

‫פקודת ‪:Import‬‬

‫על מנת לייבא כלשהו קובץ לתוכנית שלנו נרשום‬


‫”‪#include “filename‬‬
‫במידה והוא נמצא באותו מיקום של הקובץ הנוכחי שבו אנחנו עובדים או‬
‫>‪#include <path‬‬
‫עבור קובץ שנמצא בכלשהי כתובת במחשב‪.‬‬
‫לאחר שייבאנו קובץ ‪ ,c‬זה שקול לאם היינו מעתיקים את כל הקוד שבקובץ שייבאנו לקוד שלנו בשורה שבה כתבנו את פקודת‬
‫הייבוא‪ .‬כלומר‪ ,‬ניתן יהיה להשתמש בכל הפונקציות השונות שכתובות ומוגדרות בו‪.‬‬
‫נשים לב שעלולה להיווצר בעיה‪ -‬שאם למשל נייבא לקובץ מסוים קודים מקובץ ספציפי ובקובץ אחר נייבא את אותם קודים‬
‫מאותו קובץ ספציפי‪ ,‬ואז נכניס את שלושת הקבצים ל‪ ,Linker-‬תיווצר בעיה כי אותם קודים מופיעים מספר פעמים באותה‬
‫תוכנית‪.‬‬
‫לכן על מנת לפתור את הבעיה הזאת‪ ,‬נשים למשל את קובץ ‪ ,A.c‬ממנו נרצה לייבא את הקודים שנשתמש בהם בקבצים‬
‫אחרים‪ ,‬ביחד עם כל הקבצים שנקמפל בתוכנית שלנו‪ .‬כמו כן ניצור קובץ נוסף‪ ,A.h ,‬שיכיל אך ורק הצהרות ריקות לאותם‬
‫פונקציות שאנחנו רוצים להשתמש בהם מ‪) H-‬קצת דומה למנשק(‪ .‬כעת‪ ,‬בכל קוד אחר שנרצה להשתמש בפקודות האלה לא‬
‫נייבא את קובץ ‪ ,A.c‬אלא נייבא את קובץ ‪ A.h‬עם ההצהרות‪ .‬כעת‪ ,‬בעת גם בזמן הקומפילציה הכל יהיה תקין‪ ,‬כי הצהרנו‬
‫על קיום כלשהן פונקציות )גם אם אין עדיין מימוש ספציפי שלהם(‪ ,‬אבל אז כשנעשה ‪ Link‬גם לא תהיה בעיה עם כפילות וגם‬
‫כל הקבצים ישתלבו לתוכנית אחת‪ -‬ואז מעבר להצהרות הריקות שרשמנו גם יהיו מימושים לפונקציות אלו בתוכנית והמחשב‬
‫ידע את מה ממש להריץ בעת השימוש בהם‪.‬‬

‫‪3‬‬ ‫‪Tel-Aviv University‬‬


‫‪Dvir Ben Asuli‬‬ ‫‪11/03/2020‬‬

‫פקודת ‪-Scanf‬‬

‫פקודה שבאמצעותה ניתן לקלוט קלט מהמשתמש בזמן ריצה‪ .‬התחביר שלה דומה מאד לתחביר של ‪ ,Printf‬כלומר תחילה‬
‫רושמים עם מחרוזת בקרה )כלומר עם ה‪ (%-‬את סוג המשתנים שרוצים להכניס ואז מגדירים את הפרמטרים שיעביר‬
‫המשתמש‪.‬‬
‫נשים לב שאת הפרמטרים שאנו קובעים שיושמו בהם הערכים נרשום תחילה עם &‪ ,‬כלומר אנחנו רוצים שבמשתנה בעל‬
‫ה כ ת ו ב ת ש ל ה מ ש ת נ ה ‪ a‬י ו ש ם ה ע ר ך ש ר צ י נ ו ל ש י ם ‪ .‬ח ש ו ב ל ז כ ו ר ש ע ל מ נ ת ב א מ ת ל ב צ ע ה ש מ ה ש ל ע ר כ י ם מ ה מ ש ת מ ש במשתנים‬
‫ספציפיים יש לאתחל אותם קודם‪.‬‬

‫‪4‬‬ ‫‪Tel-Aviv University‬‬

You might also like