שפת C נתנאל גרינברגר תוכן עניינים משתנים 3 .................................. ................................ ................................ ................................ פעולות חשבוניות ולוגיות 4 ............ ................................ ................................ ................................ קלט /פלט 6 ................................ ................................ ................................ ................................ מבנה בסיסי 7 ............................. ................................ ................................ ................................ תווים 8 ...................................... ................................ ................................ ................................ בקרת זרימה 9 ............................ ................................ ................................ ................................ לולאות 11 .................................. ................................ ................................ ................................ פונקציות 14 ................................ ................................ ................................ ................................ מערכים 16 ................................. ................................ ................................ ................................ מחרוזות 18 ................................ ................................ ................................ ................................ מצביעים20 ................... ................................ ................................ ................................ pointer - חוברת זו אינה מיועדת ללימוד אלא לצורך חזרה והעמקה. יצירת קשר[email protected] : כל הזכויות שמורות © © Netanel Greenberger עמוד 2 משתנים בזכרון הנדיף ישנם בתים שבהם נשמרים נתונים במהלך התוכנית. משתנה הוא בית או מספר בתים בזכרון שבהם נשמרים הנתונים. ישנם מספר טיפוסי משתנים ,כל טיפוס משתמש במספר בתים בזכרון. טיפוס משתנה int מטרה מספר שלם shortמספר שלם קטן longמספר שלם גדול גודל בזכרון (מספר הבתים בד"כ) 4 float double מספר ממשי מספר ממשי גדול 4 8 char תו 1 הערות: .1 .2 .3 .4 .5 לא ניתן לתת שם למשתנה )או פונקציה וכדומה( המכילים: א .התחלה בספרה. ב .המכילים את התווים– ! # : ג .מילה שמורה )כגון .(if , while רצוי לתת שם בעל משמעות )גם לפונקציה(. יש הבדל בין אות גדולה לאות קטנה .נהוג לרשום רק באותיות קטנות. ניתן לאתחל את ערך המשתנה ,כאשר מצהירים עליו. נתונים שידוע שלא ישתנו במהלך התוכנית ,ניתן לשמור אותם בתור קבועים: ;const int age = 65 © Netanel Greenberger עמוד 3 פעולות חשבוניות ולוגיות סדר הפעולות ,כמו במתמטיקה )סוגרים כפל/חילוק חיבור/חיסור(. 7 567 19 ;num= 70-7*9 ;num= (70-7)*9 ;num= (70-7)-5*9+1 ככל שהמספר יהיה מדיוק יותר ,כך התוצאה תהיה באותו דיוק. 7+2=9 7+2.0=9.0 7*2=14 7*2.0=14.0 הפעולות .1 .2 .3 .4 .5 .6 .7 סוגרים( ) : השמה= : חיבור+ : חיסור- : כפל* : חילוק/ : חילוק שארית)מודלו(% : קיצורים .1הורדה /הוספה: א .שימוש במשתנה והפעולה עליוn++ : ב .פעולה עליו ושימוש במשתנה++n : Y 8 9 X 9 9 שורת קוד ;x=8 ; y = x++ ;x=8 ; y = ++x .2יתבצעו על הפעולות החשבוניות) :לדוגמא( ;a=a+2; a+=2 ;a=a*2; a*=2 ;a=a%2; a%=2 © Netanel Greenberger עמוד 4 ביטויים לוגים ישנם מספר פעולות הנמצאות בין שני ביטויים המביעות טענה מסוימת: א. ב. 5<3 5>3 הטענה יכולה להיות אמת.TRUE - או שקר.FALSE - הפעולות: קטן מ גדול מ שווה ל קטן או שווה ל גדול או שוווה ל שונה מ > < == => =< =! לאחר שהגענו לטענות מסוימות ,ניתן לבדוק את היחס בין הטענות האלו. לשם כך ישנם שלושה פעולות לוגיות: א. ב. ג. וגם -בודקת שטענת אמת מתקיימת בכל. או -בודקת שטענת אמת מתקיימת לפחות באחד. שלילה )היפוך( -הופכת טענת אמת לשקר /וטענת שקר לאמת. הפעולות: © Netanel Greenberger !a היפוך a||b או a&&b וגם b a 1 0 0 0 0 1 1 0 1 0 0 1 0 0 1 0 1 1 1 1 עמוד 5 קלט /פלט ישנם שני פונקציות הנמצאות בספריה > ,<stdio.hתפקידם הוא לקלוט ולהדפיס נתונים לתוכנית ומהתכונית. כל פונקציה מקבלת: א. ב. פורמט הדפסה /קליטה. הערך עצמו. קלט ;)Scanf("%d",&num פונקצית הקלט מקבלת שני ערכים: א. ב. פורמט קליטה -כלומר באיזה צורה הנתונים יקלטו לתוך המשתנה. המצביע למשתנה. פלט ;)Printf("%d",num פונקצית הפלט מקבלת שני ערכים: א. פורמט הדפסה -כלומר באיזה צורה הנתונים יודפסו על המסך. הנתונים יודפסו בצורה של תווים הנתונים יודפסו בצורה של מספרים ,כלומר מספר אסקיי של התו ב. ;char tav ;)scanf("%c",&tav ;)printf("%c\n",tav ;)printf("%d\n",tav המשתנה. פורמט הדפסה /קליטה מייצג פורמט הערות %dמספר שלם )(int %cתו %f %e %g %lf מספר ממשי )(double/float מספר ממשי )(double/float מספר ממשי )(double/float מספר ממשי )(double/float הצגה עשרונית הצגה עם מעריך הצגה יותר ברורה נועד לקליטה ב double הערות: ניתן להדפיס ולקלוט מספר משתנים בפונקציה אחת. בהדפסה ניתן לבצע את החישוב בתוך הקריאה לפונקציה. © Netanel Greenberger עמוד 6 מבנה בסיסי #include <stdio.h> int main() { int num; Scanf("%d",&num); Printf("%d",num); { #define - השימוש ב . הערך יקבע בתחילת התוכנית. שתייצג ערך מסוים,במהלך התוכנית ניתן לרשום מילה קבועה :למשל #define TRUE #define FALSE 7 עמוד 1 0 Netanel Greenberger © תווים קלט /פלט ישנם שני פונקציות המבצעות קלט ופלט של תו בודד. קליטת תו לתוך משתנה הדפסת תו למסך ;)(chgetchar ;)putchar(ch תווים מיוחדים ירידת שורה מעבר טאב קפיצת תווים בשורה באורך המספר המצוין © Netanel Greenberger \n\t%5d- עמוד 8 בקרת זרימה בד"כ תוכנית מבצעת את ההוראות ,שורה אחר שורה. לפעמים נרצה להתנות שורה/שורות מסוימות בתנאי ,אם התנאי מתקיים התוכנית תבצע את השורה ,אם לא היא תמשיך לשורה הבאה. משפט if-else התנאי יופיע בתוך סוגרים ,לדוגמא(x>y) : רגיל )if (x>y התנאי מתקיים // { הוראה // } else התנאי לא מתקיים // { הוראה // } כאשר יש יותר מהוראה אחת ,יש להכניס את ההוראות בסוגרים { }. מקונן )if (x>y התנאי מתקיים // { )if (a<b הוראה // else הוראה // הוראה if (c==d) // התנאי לא מתקיים // } else { הוראה // } כאשר מופיע ,elseהוא מתייחס אל ה ifהאחרון ,אלא אם כן הוא מופיע בתוך סוגרים מסולסלים )כמו בדוגמא האחרונה(. © Netanel Greenberger עמוד 9 משפט תנאי מקוצר ניתן לכתוב משפט תנאי מקוצר ,המקביל למשפט .if-else תחביר > במקרה ששקר< > :במקרה שאמת< ? >תנאי< ;)'(num>0)? printf("%c\n",'g'):printf("%c\n",'b > במקרה ששקר< > :במקרה שאמת< ? >תנאי והשמה < ;'ch=(num>0)? 'g':'b משפט switch ישנם תוכניות המכילות משפטי תנאי רבים ,והתוכנית נראת מסובכת וקשה לקריאה. במקרים מסוימים ניתן להמיר את משפטי התנאי למשפט .switch משפט switchבודק את ערכו של משתנה מסויים ומבצע את ההוראה בהתאם לערכו. דוגמא )switch (ch { case 'a': ;re++ ;break case 'b': ;re-- ;break default: ;re=0 } משפט switchיכול לבדוק את ערכו של משתנה שלם /תו בלבד. כאשר נמצא ערכו של המשתנה ,הוראות ה switchיובצעו מהמקום והלאה ,כדי למנוע זאת יש להשתמש בהוראת ,breakהיוצאת מה ,switchלאחר ביצוע ההוראה המבוקשת. אם לא נמצא התאמה ניתן להגדיר ערך ברירת מחדל שיובצע.defult - © Netanel Greenberger עמוד 01 לולאות לפעמים נרצה לחזור על הוראה מסוימת מספר פעמים. פעמים שנדע את מספר הפעמים שנרצה לחזור ,ופעמים שלא נדע ונצטרך להשתמש בתנאי. לשם כך ישנם שלושה סוגי לולאות.do while ,while ,for : משותף לכל הלולאות ,שבכל סוג נצטרך לבצע פעולה שתביא אותנו לסיום הלולאה )אחרת היא תהיה לולאה אינסופית( .ברוב המקרים נצטרך לאתחל את אינדקס הלולאה. אם גוף הלולאה הוא הוראה אחת ,אין צריך להכניסו לסוגריים { }. ניתן לבצע לולאות מקוננות. לולאת while כאשר נרצה לחזור על ביצוע הוראות מסוימות מספר פעמים לא ידוע ,נשתמש בלולאת .while סד"פ לולאה דוגמא )while (re>90 { ;)printf("%d\n",re ;re-=10 } © Netanel Greenberger עמוד 00 לולאת do while כמו לולאת ,whileאלא שתנאי הלולאה נמצא לאחר גוף הלולאה .כלומר -גוף הלולאה יבוצע לפחות פעם אחת. דוגמא: do { ;)printf("%d\n",re ;re-=10 } ;)while (re>90 לולאת for כאשר ידוע מראש מספר הפעמים שבו אנו רוצים לחזור על הוראות מסוימות ניתן להשתמש בלולאת .for מבנה )קידום אינדקס ; תנאי ; אתחול אינדקס( for סד"פ לולאה דוגמא )for (i=0; i<10; i++ { ;)printf("%d",i } ניתן לבצע מספר פקודות אתחול ,תנאי ,ועדכון. )for (i=0 , j=20 ; i<10 , j>10 ; i++ , j-- © Netanel Greenberger עמוד 02 break & continue לפעמים נרצה להפסיק /לקדם לולאה באמצע פעולתה ,בעקבות נתונים מסוימים שהגענו אליהם. break גורמת יציאה מתוך הלולאה הפנימית ביותר. )while (re>90 { ;)printf("%d\n",re ;if (re %9==0) break ;re-=2 } פקודה זו עובדת גם במשפט .switch continue מסיימת את הפעולה הנוכחית ,לאחר מכן בודקת את התנאי. )while (re>90 { ;)printf("%d\n",re )if (re %9==0 { ;re-=8 ;continue } ;re-=2 } © Netanel Greenberger עמוד 03 פונקציות תוכנית מורכבת מהוראות )= קוד( רבות ,ככל שההוראות רבות יותר נרצה לייעל את התוכנית: .1כדי שלא לחזור על הוראות דומות. .2כדי להבין מה הולך בתוכנית. לדוגמא ,אם נרצה להדפיס למסך ,אנו נצטרך לרשום שורות קוד רבות -דבר זה הופך את התוכנית למסורבלת ,במיוחד אם נרצה להדפיס מספר שורות .כדי למנוע את הבלגן הזה אנו נשתמש בפונקציה. פונקציה -קטע קוד :המקבל ערכים ,עושה חישובים ,ומחזיר תוצאות. כלומר במקום לרשום שורות קוד רבות ,נוכל לקרוא בשם של הפונקציה ,והיא תבצע את החישובים ותחזיר תוצאות ,וכל זה בשורות קוד מעטות. מבנה >פרמטרים<>שם<>טיפוס משתנה שיחזור לתוכנית הקוראת< ;)double power(int x,int y פרמטרים .1הפרמטרים המעוברים לפונקציה ,מוכרים אך ורק לאותה פונקציה. .2אפשר שלא להעביר פרמטרים לפונקציה ,אך יש לרשום ) (. טיפוס משתנה אם הפונקציה לא מחזירה ערך ,רושמים voidבמקום טיפוס המשתנה. קריאה והחזרה חייבים להעביר לפונקציה את כל הפרמטרים בהתאמה. הקריאה יכולה להתבצע מהפונקציה הראשית ומכל פונקציה אחרת. כאשר הפונקציה מחזירה ערך ,זה נעשה ע"י שימוש ב .return כאשר מגיעים ל returnהפונקציה סיימה את תפקידה ,למרות שיש עדין שורות קוד באותה פונקציה. ;)power(num1,num2 ;return x/y משתנים סוגי משתנים מקומיים -משתנים המוגדרים בפונקציה ,מוכרים רק באותה פונקציה. גלובליים -משתנים המוגדרים בתחילת הקובץ ,מוכרים בכל הפונקציות{ .לא מומלץ! עלול לעשות בעיות} © Netanel Greenberger עמוד 04 העברת ערכים אל הפונקציה עובר הערך של המשתנה -העתק שלו ,לא המשתנה עצמו .כלומר אין שינוי למשתנה בפונקציה הקוראת. הכרזה כל פונקציה תרשם לפני הפונקציה הקוראת לה. ניתן לרשום רק את כותר הפונקציה ואת מימוש הפונקציה לרשום בסוף הקובץ. כותר הפונקציה// ;) double power(int ,int מימוש הפונקציה// )double power(int x,int y { ;return x/y } אם התוכנית מורכבת ממספר קבצים ,המימוש יופיע בקובץ אחד ,וההכרזה בכל קובץ הקורא לפונקציה. שימוש בספריה ישנם ספריות רבות בשפת ,Cכל ספריה מכילה מספר פונקציות. הספריה הבסיסית ביותר שאנחנו מכירים היא >.<stdio.h הכרזה על שימוש בספריה תעשה בתחילת התוכנית: >שם הספריה< #include © Netanel Greenberger עמוד 05 מערכים כאשר יש לנו מספר משתנים שיש בהם מכנה משותף )בד"כ( ,נתייחס אליהם בתור משתנה אחד המחולק לתאים ,וכל תא מכיל ערך מסוים. לדוגמא :ציון מבחן של 10סטודנטים ,ניתן להגדיר 10משתנים ,אבל לא כדאי -זה יכול להיות ארוך מאוד. נגדיר מערך המחולק ל 10תאים ובכל תא נכניס את ציינו של סטודנט אחר. לכל מערך יש שם וגודל וכמובן סוג טיפוס. כל תא הוא משתנה ללא יוצא מן הכלל. גישה לאיבר במערך היא באמצעות אינדקס. המערך הוא רצף של תאים צמודים בזכרון. מבנה >גודל< >שם< >סוג טיפוס< הגדרה ;]int arr[3 לא חייבים לציין את מספר אברי המערך ,במקרה שרושמים את איבריו ב { }. ;}int arr[]={1,2,3 גודל המערך חייב להיות מספר קבוע ,ולא משתנה. בשורת ההגדרה מגדירים את גודל המערך .במהלך התוכנית המספור של התאים מתחיל מתא .0 כלומר ,מיקום התא האחרון = גודל המערך 1 - אתחול ניתן לאתחל בצורה של { } רק בשורת ההגדרה. הכנסת האיברים למערך תתבצע בהתאמה מהאיבר הראשון. עם האתחול לא מכסה את שאר המערך ,בשאר האיברים יוצב .0 ;}int arr[3]={1,2,3 ;}int arr[10]={1,2,3 © Netanel Greenberger עמוד 06 גישה במהלך התוכנית ,גישה למערך תעשה לגבי כל תא בנפרד .כלומר: oאסור לבצע השוואה ,קלט ,פלט ,איפוס של מערך שלם -בבת אחת ,כגון .arr = 0 oאלא ,גישה תהיה בד"כ ע"י לולאה ,ואינדקס הלולאה ישמש כאינדקס המערך. ;]int arr[10 ;for (i=0 ; i<10; i++) arr[i]=0 אסור לחרוג מגבולות המערך. העברת מערך לפונקציה מועברת לפונקציה כתובת המערך ,כלומר בשינוי ערכו של המערך בפונקציה ישתנה המערך המקורי. כדאי להעביר לפונקציה גם את גודל המערך. ;)void ini_array(int a[],int size אין צורך לרשום את גודל המערך בכותר הפונקציה. מערך קבוע ניתן בכותר לקבוע שהמערך המועבר לפונקציה יהיה קבוע ,ובכך להבטיח שהמערך לא ישתנה. לא ניתן להעביר מערך שהוגדר כקבוע ,לפונקציה שבה הוא לא קבוע. ;)void print_array(const int a[],int size מערכים רב -מימדים מייצגים מטריצות )טבלאות( ,או מימדים גבוהים יותר. מיוצגים ע"י שני אינדקסים )או יותר(. ההגדרה ,האיתחול והגישה אליו נשארים אותו דבר -רק עם שינוי קטן של הוספת אינדקס נוסף. במערך דו-מימדי ,האינדקס הראשון מייצג שורה ,והאינדקס השני מייצג עמודה. בהעברת מערך רב מימדי לפונקציה צריך לציין את גודל המימד השני והלאה. ;)void print_array(int a[][20],int size © Netanel Greenberger עמוד 07 מחרוזות מחרוזת היא מערך של תווים. ישנם פקודות ופונקציות בשפת Cשעוזרות לנו לעבוד עם מחרוזות בצורה פשוטה יותר. בכל סוף מחרוזת ,יופיע תו סיום מחרוזת.'\0' - אתחול ניתן לאתחל מערך תווים בהגדרה עם גרשיים כפולים " " ,סימון סוף מחרוזת יוכנס אוטומטית. ;"char str[]="Hellow קלט /פלט קלט ניתן לקלוט בדרך הרגילה ,הכנסת איברים למערך ע"י scanfאו ע"י )(.getchar במקום ניתן לקלוט כך: ;)scanf("%s",str הקלט יהיה עד רווח או ירידת שורה. סימון סוף מחרוזת יוכנס אוטומטית. אם נרצה להגביל את מספר התווים שיכולים להקלט נכתוב כך: ;)scanf("%15s",str ישנה עוד פקודת קלט , gets (str); -הקולטת מחרוזת שלמה .חסרון :לא ניתן להגביל את מספר התווים שיקלטו. פלט כמו בקלט ישנו קיצור ,וניתן לכתוב כך: ;)printf ("%s",str ההדפסה עצמה תתבצע עד להגעה לתו סיום מחרוזת. ישנה עוד פקודת פלט , puts (str); -המדפיסה עד לתו סיום מחרוזת ,ויורדת שורה. © Netanel Greenberger עמוד 08 שימוש במחרוזות כמו שבמערכים לא ניתן לבצע פעולות על מערך שלם בבת אחת ,כך גם במחרוזות. לשם כך נבנתה ספריה ><string.h המכילה פונקציות לעבודה עם מחרוזות. פונקציות מרכזיות: .1 .2 .3 .4 .5 .6 -Strlenמקבלת מחרוזת ,מחזירה את אורך המחרוזת. -Strcmpמקבלת שני מחרוזות ,מחזירה 0כאשר הם זהות לחלוטין ,מספר חיובי כאשר הראשונה גדולה יותר )ע"פ סדר הא"ב( ,מספר שלילי כאשר השנייה גדולה יותר. -Strcpyמקבלת מחרוזת מקור ,ומחרוזת יעד ,מעתיקה את המחרוזת מקור ליעד. -Strcatמקבלת שני מחרוזות ,משרשרת את השנייה לסוף של הראשונה. -Strchrמקבלת תו ומחרוזת ,מחזירה את מיקמו הראשון של התו במחרוזת. -Strstrמקבלת שני מחרוזות ,מחפשת את ההופעה )הראשונה( של המחרוזת השנייה בראשונה. ישנה עוד ספריה < >ctype.hהעובדת על תווים בודדים. © Netanel Greenberger עמוד 09 מצביעיםpointer - לכל כתובת/משתנה בזכרון יש כתובת וערך. בשפת Cניתן לתת שם נורמאלי לאותם כתובות בפונקציה מסוימת ,ולהכניס בהם ערכים ,לדוגמאx=4; : עד עכשיו עבדנו כך ,עכשיו נראה שאפשר לגשת גם לכתובות ולערכים ישר. גישה לכתובת אל הכתובת ניגשים ע"י הסימן & לפני שם המשתנה. לא ניתן לשנות כתובת של משתנה! לא קיים כתובת לקבועים וביטויים. גישה לערך כאשר נתונה לנו כתובת בזכרון ניתן להכניס לתוכה ערך ,ע"י הסימן *. מסוכן לשנות את ערכו של כתובת בזכרון ,כאשר הוא אינו מוכר לנו .לדוגמא: ;*(37693)= 700 משתנה מסוג מצביע למשתנה מסוג רגיל שהכרנו עד עכשיו ,יש שני פרמטרים -סוג וערך. למשתנה מסוג מצביע ,יש שני פרמטרים -סוג וערך של כתובת. הצהרה ;int *num שימוש במשתנה קבלת כתובת- ;num=&i שימוש בכתובת- ;*num=5 כאשר משתנה-מצביע ,לא מצביע לשום מקום ,נגדיר שהוא מצביע לריק. ;int *num=NULL קידוד הדפסה של כתובת בזכרון הוא באמצעות %p ;)printf("%p",&i © Netanel Greenberger עמוד 21 מצביעים ופונקציות פונקציה יכולה להחזיר ערך מסוג מצביע. אבל ,אין להחזיר מצביע של משתנה מקומי בתוך הפונקציה ,כי בסיום הפונקציה הוא נמחק. מצביעים ומערכים מערך בזכרון מורכב מתאים הצמודים זה לזה. שם המערך הוא בעצם המצביע לאיבר הראשון במערך. מצביע למערך הוא בעצם הכתובות לתא הראשון במערך) .דוגמאות שוקלות( ;arr_p= arr ;]arr_p= &arr[0 גישה לאיברי המערך ;)]1. printf("%d",arr[i ;))2. printf("%d",*(arr+i תזכורת :שמעבירים מערך לפונקציה ,מה שמעובר זה כתובת התא הראשון במערך. כותר פונקציה ,שמועבר אילה מערך: ;)void ini_arr(int *a © Netanel Greenberger עמוד 20
© Copyright 2024