שפת C/פעולות חשבוניות: הבדלים בין גרסאות בדף
תוכן שנמחק תוכן שנוסף
מ ←השמה |
אין תקציר עריכה |
||
שורה 8:
שפת C מאפשרת לחבר (ע"י +), לחסר (ע"י -), להכפיל (ע"י *), לחלק (ע"י /), ולמצוא שארית (ע"י %). להלן מספר דוגמאות:
<source lang = "cpp">
int x = 2, y = 3;
שורה 23 ⟵ 22:
/* Prints 2 % 3 = 0. */
printf("%d * %d = %d\n" % x, y, x % y);
</
אפשר לבצע פעולות חשבוניות על מספרים, משתנים, או כל שילוב של משתנים ומספרים:
<source lang = "cpp">
int x = 2, y = 3;
printf("%d\n" % x + y + 5);
</
==סדר פעולות החשבון==
סדר פעולות החשבון בשפת C הוא המקובל
ב[[אלגברה תיכונית/חוקי החשבון/חוקי פעולות החשבון#הסכם סדר הפעולות|אלגברה בסיסית]], ולכן כפל (*), לדוגמה, מבוצע לפני חיבור (+). השורה הבאה, לדוגמה, תדפיס 17
<source lang = "cpp">
printf("%d\n" % 2 + 3 * 5);
</
בדיוק כבאלגברה בסיסית, ניתן להשתמש בסוגריים כדי לציין סדר פעולות שונה. השורה הבאה, לדוגמה, תדפיס 25
<source lang = "cpp">
printf("%d\n" % (2 + 3) * 5);
</
==השמת ערכים==
===השמה ואתחול===
כפי שראינו ב[[שפת C/משתנים|משתנים]], אפשר להשתמש בסימן = להשמה ואתחול.
<source lang = "cpp">
int x = 2, y = 3;
int z = x + y + 5;
</
חשוב להבין מה קורה כאן בשורה השניה. ראשית מעריכים את הביטוי x + y + 5 (ערכו כאן 10). משימים ערך זה למשתנה z. אפשר גם להשים למשתנה ערך חדש שתלוי בערכו הקודם. נתבונן לדוגמה בשורה
<source lang = "cpp">
</
הכוונה איננה ל[[אלגברה תיכונית|משוואה אלגברית]] על x (שאגב, נטולת פתרון). הכוונה היא להעריך את ערכו של הביטוי x + 2, ולהשים ערך זה חזרה לx (דבר זה ידרוס את הערך הקודם).
===סימני קיצור בהשמה עצמית===
כפי שראינו,
<source lang = "cpp">
</
משמעו השמה עצמית של x לערכו הקודם ועוד משהו (2 במקרה זה). בפועל, סוג זה של השמה עצמית נפוץ מאד. שפת C ידועה בקצרנותה הרבה לביטויים נפוצים. אפשר לכתוב את הביטוי הקודם גם באופן הבא, הקצר יותר:
<source lang = "cpp">
</
המשמעות כאן זהה לחלוטין: מעריכים את x + 2, ומשימים את הערך לx.
שפת C כוללת סימונים מקוצרים להשמות עצמיות לכל חמש [[שפת C/פעולות חשבוניות#הפעולות הבסיסיות|פעולות החשבון הבסיסיות]]:
<source lang = "cpp">
/* x = x + 1 */
x += 1;
שורה 93 ⟵ 82:
/* p = p % 2 */
p %= 2;
</
==הגדלה עצמית והקטנה עצמית==
===הגדלה עצמית===
נניח שאנו רוצים לקדם את x ב1. כבר ראינו שאפשר לרשום זאת כך:
<source lang = "cpp">
x = x + 1
</
או, באופן קצר יותר, כך:
<source lang = "cpp">
x += 1;
</
כשנגיע ל[[שפת C/תנאים ולולאות#לולאות|לולאות]], נראה שהגדלה עצמית משתנה דווקא ב1 (כלומר, שהמשתנה מקבל את ערכו הקודם ועוד 1) היא פעולה נפוצה במיוחד. פעולה זו, הגדלה עצמית (increment) יכולה להיכתב כך:
<source lang = "cpp">
x++;
</
או כך:
<source lang = "cpp">
++x;
</
(נעמוד על ההבדלים בין שתי הצורות ב[[שפת C/פעולות חשבוניות#הגדלה עצמית והקטנה עצמית לכתחילה ובדיעבד|כאן]].)
שורה 127 ⟵ 107:
באותו אופן כהגדלה עצמית, ניתן להוריד 1 מערך משתנה כך:
<source lang = "cpp">
x--;
</
או כך:
<source lang = "cpp">
--x;
</
===הגדלה עצמית והקטנה עצמית לכתחילה ובדיעבד===
לעתים, קיים ביטוי בו משתנה הן מקודם והן מוערך. נניח, לדוגמה, שx מכיל את הערך 3, ונתבונן בשורה:
<source lang = "cpp">
z = x++;
</
שני דברים מתבצעים כאן:
* x מקודם ב1
* z מקבל ערך כלשהו
השאלה היא, אבל, מה קודם למה. אם קודם x מקודם, אז בסיום השורה, z יכיל את הערך 4. מצד שני, אם קודם z מקבל ערך, אז בסיום השורה, z יכיל את הערך 3 (כי x קודם ל4 רק אחרי שz קיבל את ערכו הקודם). לצורך כך מכילה שפת C הן הגדלה עצמית לכתחילה, והן הגדלה עצמית בדיעבד. משמעות הגדלה עצמית בדיעבד (post-increment)
<source lang = "cpp">
x++
</
היא הערך את x ורק אז קדם אותו. לעומת זאת, משמעות הגדלה עצמית לכתחילה (pre-increment)
<source lang = "cpp">
++x
</
היא קדם את x והערך את התוצאה. הדבר דומה להקטנה עצמית בדיעבד (post-decrement)
<source lang = "cpp">
x--
</
לעומת הקטנה עצמית לכתחילה
(pre-decrement)
<source lang = "cpp">
--x
</
==פעולות חשבוניות על שלמים ונקודות צפות==
שורה 179 ⟵ 145:
כבר ראינו ב[[שפת C/משתנים|משתנים]] על ההבדלים בין שלמים לנקודות צפות. כדאי לשים לב לנקודה, שכן בלעדיה נוכל לקבל תוצאות מפתיעות. נתבונן בקטע הקוד הבא:
<source lang = "cpp">
int x = 3, y = 8;
printf("The average is %f\n" % (x + y) / 2);
</
אם נהדר ונריץ את הקוד, נראה שהממוצע המודפס הוא
5.0000, ולא
שורה 203 ⟵ 167:
נתבונן בקטע הקוד הבא:
<source lang = "cpp">
char x = 3;
int y = x;
</
בשורה הראשונה מושם הערך 3 למשתנה x, שהוא מסוג תו. השורה הבאה משימה את ערכו של x לתוך המשתנה y, שהוא מסוג שלם. האם מידע יכול לאבוד כאן? לא, מפני שתחום הערכים שיכול להכיל int כולל את תחום הערכים שיכול להכיל char. המרה זו נטולת בעיות, מפני שאנו ממירים ערך במשתנה בעל תחום קטן, במשתנה בעל תחום רחב יותר.
שורה 217 ⟵ 179:
נתבונן בקטע הקוד הבא:
<source lang = "cpp">
int x = 3;
char y = x;
</
כאן יש בעיה פוטנציאלית, משום שאנו ממירים ערך במשתנה בעל תחום גדול, במשתנה בעל תחום צר יותר. חלק מהמידע ילך לאיבוד.
שורה 231 ⟵ 191:
כאשר המהדר מבצע חישובים על מספר ערכים מסוגים שונים, הוא עורך המרות מרחיבות במידת הצורך עד שהחישוב פועל על ערכים מאותו סוג. לדוגמה, נתבונן בקטע הקוד הבא:
<source lang = "cpp">
int x = 2, y = 3;
printf("The average is %f\n", (x + y) / 2.0);
</
קטע קוד זה מדפיס שהממוצע הוא 2.5, כנדרש. היות ש2.0 הוא משתנה נקודה צפה, המהדר יבצע המרה מרחיבה כך שx + y יהיה נקודה צפה, על אף שהן x והן y שלמים (ועל כן סכומם אמור היה להיות שלם).
שורה 245 ⟵ 203:
נניח שc מייצג טמפרטורה נתונה במעלות בשיטת [[w:en:Celsius|Celsius]], ואנו רוצים למצוא את f, המעלות בשיטת [[w:en:Fahrenheit|Fahrenheit]]. על פי נוסחה ידועה, f הוא {{משמאל לימין|9 / 5 * c + 32}}. נניח גם שהדיוק אינו חשוב לנו במיוחד, ואנו מוכנים לעבוד במספרים שלמים (על אף שגיאת העיגול). להלן תכנית המקבלת כקלט מעלה בFahrenheit, ומדפיסה אותו בCelsius:
<source lang = "cpp">
#include <stdio.h>
שורה 262 ⟵ 219:
return 0;
}
</
להפתעתנו (או לא), התוכנית פשוט תפלוט תמיד את {{משמאל לימין|c + 32}} - שגיאה שחורגת בהרבה מסתם שגיאת עיגול. מדוע הדבר קורה? ראינו ב[[שפת C/פעולות חשבוניות#פעולות חשבוניות על שלמים ונקודות צפות|פעולות חשבוניות על שלמים ונקודות צפות]] שכל פעולה על טיפוסים שלמים מניבה תמיד תוצאה מסוג שלם. {{משמאל לימין|9 / 5}}, לכן, מתורגם ל1, ולכן מקבלים {{משמאל לימין|1 * c + 32}} בפועל.
נוכל לתקן זאת על ידי כך שנחליף את {{משמאל לימין|9 / 5}} ב1.8, שהוא מספר נקודה צפה:
<source lang = "cpp">
f = 1.8 * c + 32;
</
כעת מדובר בחישוב מעורב, והשלמים בצד ימין של הסימן = יומרו במספרי נקודה צפה. לאחר החישוב, הערך יושם בf שהוא מספר שלם, ורק החלק העשרוני יאבד (כלומר, נקבל רק שגיאת עיגול).
|