יום רביעי, 8 בפברואר 2017

שפת C - עוד על define ו enum

define מתקדם

כפי שלמדנו כבר, define מגדיר קבוע. לאורך כל התוכנית כשהקבוע יופיע הקומפיילר יתייחס אליו כרצף התווים שבחרנו.

-השם הרשמי להגדרות כאלו הוא "מאקרו" (macro).
-נראה היום שאפשר לעשות פעולות מתקדמות יותר עם define. בדומה לפונקציות:
#include <stdio.h>
#define p(a) printf("%d\n",a)
void main(){
 int x=3,y=8;
 p(x);
 p(y);
}

כאן הגדרנו את p כישות שדומה לקבוע. כל מקום שיש בתוכנית:  (מספר או תווים כלשהם)p
זה יוחלף ל:
printf("%d\n",מספר)



גם תווים:
#include <stdio.h>
#define p(a) printf("%c\n",a+1)
void main(){
 p('e');
 p('E');
}






נראה שdefine יכול להיות דומה מאוד לפונקציות:
#include <stdio.h>
#define M(a) a*a
void main(){
 int x=3, y=2, c;
 c = M(x);  // c = 9
 c = M(y);  // c = 4

אבל אסור להתבלבל, define זה לא "פונקציה". הוא רק מחליף תווים:
 c = M(x+y);  // c = 11
}
c שווה 11 ולא 20. אף על פי ש:
(2+3)*(2+3) = 20              
:עדיין
2+3*2+3 = 11                   






שימושי מאוד לעשות פעולות כאלה:
-תזכורת: האופרטורים : ?

#include <stdio.h>
#define M(a,b) (a>b)? a : b  // יחזיר תמיד את הגדול מבניהם
void main(){
 int    x=3, y=2, c=11;
 double r=10,t=100,w=100;
 
 printf("%d\n",M(x,y)); // 3
 printf("%d\n",M(y,x)); // 3
 
 printf("%lf\n",M(r,t)); // 100.000000
 printf("%lf\n",M(t,w)); // 100.000000
 
 printf("%lf\n",M(r,c)); // 10.000000
}


ראה חומר מתקדם: וויקיספר





enum

enum משמשת אך ורק כדי להקל את קריאת התוכנית עבור המתכנת.
enum דומה בעיקר ל define ול struct. אפשר להתייחס אליה כמין שילוב בין השניים.
-בפשטות enum יוצר סוג חדש של משתנים (בדומה ל typedef) כשאותם משתנים נועדו לקבל רק ערכים שהם המצבים
  שאנו מגדירים לאותו enum.
- יוצרים enum למעלה, בדומה למשתנים גלובאלים ו define.

מבנה כללי:
enum    מצב3 , מצב2 , מצב1 }   שם ..... };                    



לדוגמה נגדיר למעלה (מחוץ לכל פונקציה):
enum status {success, fail};                                     
וניצור משתנים מסוג status כך:
void main ( ){
enum status test1, test2 = success ;
    .
    .
    .
}
יצרנו 2 משתנים מסוג status שנקראים test1 ו test2. הם נועדו להכיל רק את המצבים success או fail.
בנוסף שמנו  success ב test2.

-המשתנים מתנהגים כמו int ותופסים 4 בתים בזיכרון.-




enum שימושי מאוד כשרוצים שפונקציה תחזיר לנו האם היא הצליחה או נכשלה:
ניצור enum שבו שני מצבים, של הצלחה או של כישלון. הפונקציה היא מסוג ה enum שלנו וכך מחזירה רק אחד משני המצבים. מה שיותר קריא. (בניגוד לכתיבה הפחות ברורה למתכנת שהפונקציה מחזירה 1 עבור הצלחה או 0 עבור כישלון.)


מאחורי הקלעים כל אחד מהמצבים (נקראים גם "תת תחומים") של ה enum שלנו הוא קבוע (define).
כלומר בהגדרה:
enum status {success, fail};
ה success וה fail הם קבועים.
ברירת המחדל היא שהראשון יהיה 0, וכל קבוע נוסף יהיה +1 מהקבוע לפניו. (כך שfail הוא 1, וכן הלאה...).




יש אפשרות (לא שימושית כמעט) לכפות על הקבועים ערך אחר:
enum Day { SUN=1, MON, TUE, WED, THU, FRI, SAT};
עכשיו הקבוע הראשון הוא מאחורי הקלעים 1. כל קבוע הוא +1 של הקבוע לפניו. לכן MON יהיה2 ו TUE יהיה 3 וכן הלאה... 




מותר (אך לא נהוג) להשתמש בקבועים גם עבור מטרות נוספות:
#include <stdio.h>
enum status{good,bad,very_good};
void main(){
 int x;
 printf("%d\n",good); // ידפיס 0
 x=bad+very_good// שווה שלוש x
}





מנגנון ה enum הוא כלי עזר למתכנת, אך לא חובה על משתנה להיות מוגבל רק למצבים שניתנו.
לדוגמה:
#include <stdio.h>
enum status{good,bad,very_good,very_bad};
void main(){
 int x=2;
 enum status y = bad,z;
 z = x+y;
 
 if (y == 1) printf("y = bad\n");      // יודפס
 if (z == very_bad) printf("z = 3\n"); // יודפס
}




בנוסף אפשר לקצר הגדרת משתנים מסוג של enum ע"י typedef (כמו ב struct)
כך:
#include <stdio.h>
typedef enum { FALSE=0, TRUE=1 } Boolean;
void main(){
          Boolean flag = FALSE;
}


או אפילו עם 2 שמות: (בדיוק כמו ב struct)
#include <stdio.h>
typedef enum BOOLFALSETRUEBoolean;
void main(){
 Boolean flag1 = FALSE;
 enum BOOL flad2 = TRUE;
 printf("%d  %d\n",flag1,flad2);  // 0  1  :ידפיס
}






חשוב שתעיפו מבט על המושגים כאן
(ראו שם גם "אופרטורים הפועלים על סיביות (bitwise operators)" שהם: AND , OR , XOR , >>  , << )

וראו גם: וובמאסטר




אין תגובות:

הוסף רשומת תגובה