c programming tutorial - בקלות C++
מדריכי תכנות

שיעור 17: פונקציות עם רשימות ארגומנטים באורך משתנה

ייתכן שהיית רוצה שתהיה לך פונקציה שתקבל כל מספר של ערכים ואז תחזיר את הממוצע. אתה לא יודע כמה ארגומנטים יועברו לפונקציה. דרך אחת ליישם את הפונקציה תהיה לקבל מצביע למערך. דרך אחרת תהיה לכתוב פונקציה שיכולה לקבל כל מספר של ארגומנטים. כך שתוכל לכתוב avg (4, 12.2, 23.3, 33.3, 12.1); או שתוכל לכתוב avg(2, 2.3, 34.4);. יש פונקציות ספריה שיכולות לקבל רשימה משתנה של ארגומנטים (כמו printf).

כדי להשתמש בפונקציה עם מספר משתנה של ארגומנטים, או ליתר דיוק, פונקציה ללא מספר קבוע של ארגומנטים, תשתמש בקובץ הכותרת stdarg.h. יש ארבעה חלקים נחוצים: va_list, שמאחסן את הרשימה של הארגומנטים, va_start, שמאתחל את הרשימה, va_arg, שמחזיר את הארגומנט הבא ברשימה, ו va_end, שמנקה את רשימת הארגומנטים המשתנה. בכל פעם שפונקציה מוצהרת לקבל רשימה לא קבועה של ארגומנטים, במקום הארגומנט האחרון אתה צריך לשים שלוש נקודות (שנראות כך '…'), כך ש int a_function(int x, …); יאמר למהדר שהפונקציה צריכה לקבל כל מספר של ארגומנטים בהם המתכנת משתמש, כל עוד המספר הוא לפחות אחד, שהוא הראשון, x.

va_list הוא כמו כל משתנה אחר. לדוגמא va_list a_list;.

va_start היא מאקרו שמקבל שני ארגומנטים, va_list אחד, ושם המשתנה שבא לפני השלוש נקודות. כך שבפונקציה a_function, כדי לאתחל את a_list באמצעות va_start, תכתוב va_start(a_list, x);.

va_arg לוקחת את va_list וטיפוס משתנה, ומחזירה את הארגומנט הבא ברשימה בצורה של טיפוס המשתנה שנאמר לה. לאחר מכן היא עוברת ברשימה לארגומנט הבא. לדוגמא, va_arg(a_list, double) תחזיר את הארגומנט הבא, בהנחה שהוא קיים, בצורה של double. בפעם הבאה שהיא נקראת היא תחזיר את הארגומנט שבא אחרי המספר המוחזר האחרון, אם קיים אחד כזה.

כדי להראות איך כל אחד מהחלקים עובד, קח פונקציה לדוגמא:

#include <stdarg.h>
#include <iostream.h>
double average(int num, ...)
{
  va_list arguments;        //A place to store the list of arguments
  va_start(arguments, num); //Initializing arguments to store all values
  int sum=0;		     // passed in after num    
  for(int x=0; x<num; x++)   //Loop until all numbers are added
    sum+=va_arg(arguments, double); //Adds the next value in argument 
				    //list to sum.
  va_end(arguments);      //Cleans up the list
  return sum/(double)num;    //Returns some number (typecast prevents 
			     //trunctation)
}

int main()
{
  cout<<average(3, 12.2, 22.3, 4.5)<<endl;
  cout<<saverage(5, 3.3, 2.2, 1.1, 5.5, 3.3)<<endl;
  return 0;
}

זה לא בהכרח רעיון טוב להשתמש ברשימת ארגומנטים משתנה בכל פעם, כיוון שקיים פוטנציאל להנחה שמשתנה הוא מטיפוס מסוים בעוד שלמעשה הוא מטיפוס אחר, למשל כשמניחים שמצביע ל NULL הוא מספר שלם. לכן יש להשתמש ברשימות משתנות של ארגומנטים בצמצום.




לדף הראשון

<< לדף הקודם