תכנות מערכות בשפת c

23
תתתתת תתתתתת תתתתC אאא- אאאאא אאאא אאא אאאא אאאאאא[email protected] 10.09.14 אאאאאאאא אאאאאא

Upload: dara-dodson

Post on 04-Jan-2016

66 views

Category:

Documents


0 download

DESCRIPTION

מכללת אורט כפר-סבא. תכנות מערכות בשפת C. פונקציות מערכים. 10.09.14. אורי וולטמן. [email protected]. מציאת המחלקים של מספר נתון. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: תכנות מערכות בשפת  C

תכנות מערכות Cבשפת

מכללת אורט כפר-סבא

אורי וולטמן

[email protected]

10.09.14

פונקציות

מערכים

Page 2: תכנות מערכות בשפת  C

מציאת המחלקים של מספר נתוןכתבו פונקציה שכותרתה

void print_divisors (int num)

, ומציגה 1המקבלת כפרמטר מס' שלם חיובי גדול מ-כפלט על המסך את רשימת מחלקיו של המספר

הנתון. המחלקים של מס' טבעי נתון הם כל המס' הטבעיים

המחלקים אותו ללא שארית. למשל, עבור הזימוןprint_divisors(6) יוצג על

.1, 2, 3, 6המסך הפלט: מה יהיה הפלט עבור

print_divisors(12)? print_divisors(29)? print_divisors(30)?

Page 3: תכנות מערכות בשפת  C

1רעיון לפתרון: נסרוק את תחום המספרים שבין לבין המספר הנתון, ונבדוק עבור כל מספר בתחום

ללא שארית.numאם הוא מחלק את הפרמטר

את משפט התנאי ניתן היהלהחליף ב-

if (!(num % i))

אין טיפוס Cכזכור, בשפת 0נתונים בוליאני, ולכן הערך

' וכל ערך שונהfalseנחשב ''.trueמאפס נחשב '

מציאת המחלקים של מספר נתון

void print_divisors (int num)

{

int i;

for (i=1; i<=num; i++)

if ((num % i) == 0)

printf (“%d “, i);

}

Page 4: תכנות מערכות בשפת  C

אחד המאפיינים של חלוקה בשלמים הוא שהמחלקים N )למעט N/2, אינם גדולים מ-Nשל כל מספר טבעי

עצמו(. 12למשל: המחלקים של=N וכולם 1,2,3,4,6,12 הם ,

.N/2=12/2=6 עצמו( אינם גדולים מ-12)למעט .נשתמש בתכונה זו ונפתח לולאה יעילה יותרvoid print_divisors (int num)

{

int i;

for (i=1; i<=num ; i++)

if ((num % i) == 0)

printf (“%d “, i);

}

מציאת המחלקים של מספר נתון

printf (“%d”, num);

i<=num/2

Page 5: תכנות מערכות בשפת  C

(math.hפונקציות מתמטיות ) בקובץmath.h :מוגדרות מספר פונקציות מתמטיות

sqrt – מקבלת מס' ממשי ומחזירה את השורש הריבועי

שלו.floor – מקבלת מס' ממשי ומחזירה אותו מעוגל כלפי

מטה.ceil – מקבלת מס' ממשי ומחזירה אותו מעוגל כלפי

מעלה.

:כתבו פונקציה שכותרתהתרגיל int sqrt_is_int (int

num) המקבלת כפרמטר מספר שלם חיובי אם השורש שלו הוא מס' שלם, 1)טבעי(, ומחזירה

אחרת. 0ו- :לדוגמאsqrt_is_int(36), sqrt_is_int(9) יחזירו

.0 יחזירו sqrt_is_int(3), sqrt_is_int(15), ואילו 1

Page 6: תכנות מערכות בשפת  C

כתבו פונקציה שכותרתה void f (int n)

, ומציגה כפלט את כל nהמקבלת כפרמטר מס' טבעי והשורש שלהם nהמס' הטבעיים אשר אינם גדולים מ-

שלם. למשל, עבור הזימוןf(50) :4, 1 יוצג על המסך הפלט ,

9 ,16 ,25 ,36 ,49.-1הרעיון האלגוריתמי: נסרוק את כל המס' הטבעיים מ

, נזמן עבור כל אחד מהם את הפונקציה nועד sqrt_is_int שכתבנו קודם(, ואם הפונקציה(

אז נציג כפלט את המספר.1מחזירה

Page 7: תכנות מערכות בשפת  C

void f (int n)

{

int i;

for (i=1; i<=n; i++)

if (sqrt_is_int(i))

printf (“%d “, i);

} האם ניתן לפתח אלגוריתם אשר

הריצה זמן הריצה שלו יהיה קצר מזמן של אלגוריתם זה?

נפתח פונקציה המשתמשת ברעיון ע"י "ייצור" אלגוריתמי אחר, הפותרת את הבעיה

העלאה בריבוע מספרי הפלט באמצעות השלמים אשר של כל המספרים

.nריבועם קטן מ-

void f (int n)

{

int i;

for (i=1; i<=sqrt(n); i++)

printf (“%d “, i*i);

}

Page 8: תכנות מערכות בשפת  C

בדיקת ראשוניותכתבו פונקציה שכותרתה

int is_prime (int n)

אם הוא 1, ומחזירה 1המקבלת כפרמטר מס' טבעי גדול מ- אם הוא פריק.0ראשוני, ו-

( מספר ראשוניprime number-הוא מספר טבעי הגדול מ )1 אשר לא מתחלק באף אחד מהטבעיים שקטנים ממנו )פרט

(.1ל- הגדרה נוספת למספר ראשוני: מספר טבעי שיש לו בדיוק

(.1שני מחלקים )הוא עצמו, ו-( מספר פריקcomposite number הוא מספר שאיננו )

ראשוני.?מה יהיה הרעיון האלגוריתמי מאחורי הפתרון

Page 9: תכנות מערכות בשפת  C

int is_prime (int n)

{

int i;

for (i=2; i<=n-1; i++)

if (n % i == 0)

return 0;

return 1;

}-1 ולא מ-2מדוע הלולאה מתחילה מ?-ומדוע היא מסתיימת בn-1-ולא ב n?האם אפשר לנצל רעיון מאחת הבעיות

הקודמות בכדי לייעל את הלולאה?נשפר את האלגוריתם על-די קביעת

.n/2הגבול העליון של הלולאה ב-

int is_prime2 (int n)

{

int i;

for (i=2; i<=n/2; i++)

if (n % i == 0)

return 0;

return 1;

}

Page 10: תכנות מערכות בשפת  C

בדיקת ראשוניות הקטנו את הגבול העליון של הלולאה בחצי )במקום

N-1 מגיעים רק עד N/2.אבל ניתן לצמצם עוד ,)

מספרמחלקים

(5,8( ,)4,10( ,)2,20)40

41ראשוני

(3,14( ,)2,21)42

43ראשוני

(4,11( ,)2,22)44

(5,9( ,)3,15)45

(2,23)46

47ראשוני

מחלקים באיםבזוגות.

ככל שמחלק גדוליותר, כך "בן זוגו"

קטן יותר. איך אפשר

להשתמש בעובדה זו לשיפור הלולאה?

Page 11: תכנות מערכות בשפת  C

בדיקת ראשוניות:אם טענה N אינו ראשוני, אז יש לו מחלק שקטן או שווה לשורש

N.:נניח בשלילה שכל המחלקים של הוכחה N גדולים משורש N .

, שמכפלתם שווה N אז קיימים שני מחלקים גדולים משורש N נרשום כל-אחד מהם בתור שורש .N מס' חיובי, ואז אם +

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

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

Page 12: תכנות מערכות בשפת  C

int is_prime4 (int n)

{

int i;

if (n = = 2) return 1;

if (n % 2 = = 0) return 0;

for (i=3; i<=sqrt(n); i+=2)

if (n % i == 0)

return 0;

return 1;

}

int is_prime2 (int n)

{

int i;

for (i=2; i<=n/2; i++)

if (n % i == 0)

return 0;

return 1;

}

int is_prime3 (int n)

{

int i;

for (i=2; i<=sqrt(n); i++)

if (n % i == 0)

return 0;

return 1;

} מה ניתן לומר על המחלקים הזוגיים של מס' לא-ראשוניN? ברור שאם מס' זוגי כלשהו מחלק אתN מחלק את 2, אזי גם N.?איך אפשר לנצל עובדה זו כדי לשפר את יעילות האלגוריתם אםN-אין טעם לבדוק מס' זוגיים נוספים כמחלקים 2 אינו מתחלק ב ,

אפשריים: 2אם = N.אזי הוא ראשוני , אםN-אזי הוא אינו ראשוני.2 הוא מס' זוגי שונה מ , עבור יתר המקרים – אין צורך לבדוק מחלקים זוגיים, אלא רק מחלקים

אי-זוגיים.

Page 13: תכנות מערכות בשפת  C

משתנים מטיפוס שלם בשפתC משתנה מטיפוס שלם מוגדר בד"כ להיות ,int או long ,

וההבדל ביניהם הוא בגודל המשתנה )מס' הבתים בזיכרון שהמשתנה תופס(.

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

( מס' הבתיםbytes שכל טיפוס תופס בזיכרון, משתנה מסביבת )עבודה אחת לשנייה.

אם, למשל, גודלו שלint בתים, אז טווח הערכים שלו הוא 2 הוא 32,767 ... +32,768.-

אם גודלו שלlong בתים, אז טווח הערכים שלו הוא 4 הוא 2,147,483,647 ... +2,147,483,648.-

נוכל לברר כמה בתים תופס כל טיפוס בסביבת העבודה שלנו, על-ידי:sizeofשימוש בפונקציה

printf (“%d %d”, sizeof(int), sizeof(long))

Page 14: תכנות מערכות בשפת  C

משתנים מטיפוס שלם על-ידי הוספת המילה השמורהunsigned ,לפני שם הטיפוס

נוכל להגדיר משתנה נטול סימן )כלומר, אי-שלילי בלבד(.-בעוד שint 32,768+ ... 32,767 הוא - unsigned int 0+ ... 65,535 הוא-ובעוד שlong 2,147,483,648+ ... 2,147,483,647 הוא-unsigned long 0 + ... 4,294,967,295 הוא

-בדוגמאות הנ"ל הנחנו שsizeof)int(=2-ו ,sizeof)long(=4 . אפשר להוסיףsigned לפני שם של משתנה, בכדי להדגיש

שמדובר במשתנה שיכול לקבל גם ערכים שליליים )כלומר, (, אבל signed long או signed intלהגדיר אותו להיות מטיפוס

אין חובה לעשות זאת. לא ניתן לרשוםsigned/unsigned.לפני משתנה מטיפוס ממשי

Page 15: תכנות מערכות בשפת  C

היפוך מספר שלםכתבו פונקציה שכותרתה

, ומחזירה את המספר xהמקבלת כפרמטר מספר שלם וחיובי )טבעי(

, אך בסדר הפוך.xהמורכב מספרותיו של למשל, עבור הזימוןreverse(1293), 3921יוחזר המספר. עבור הזימוןreverse(34), 43יוחזר המספר. עבור הזימוןreverse(10), 1יוחזר המספר. עבור הזימוןreverse(3), 3יוחזר המספר. מדוע שלא נגדיר גם את הערך המוחזר של הפונקציה להיותunsigned

int?כמו הפרמטר , עבור הזימוןreverse(59999), 99995יוחזר המספר. נניח והגדרנו את הערך המוחזר להיותunsigned int במקום unsigned

long מהו הערך הקטן ביותר של הפרמטר, שעבורו הפונקציה תחזיר ערך . בתים בזיכרון המחשב(2 גודלו intשגוי? )הניחו ש-

unsigned long reverse (unsigned int x)

Page 16: תכנות מערכות בשפת  C

שזירת מספריםכתבו פונקציה שכותרתה

, b ו-aהמקבלת כפרמטרים שני מס' שלמים וחיוביים )טבעיים(

, באופן b ו-aומחזירה את המספר המורכב מספרותיהם של , a, ולימינה ספרה של b, ולימינה ספרה של aהבא: ספרה של

, וכך הלאה.bולימינה ספרה של למשל, עבור הזימוןmerge(1293,3456), יוחזר המספר

13249536. עבור הזימוןmerge(415,34), 43145יוחזר המספר. עבור הזימוןmerge(27,1009), 217009יוחזר המספר.:השתמשו בפונקציה רמז reverse.שכתבתם בתרגיל הקודם

unsigned long merge (unsigned int a, unsigned int b)

Page 17: תכנות מערכות בשפת  C

Cמערכים בשפת בשפתC:מצהירים על מערך באופן הבא

int grades[30]float height[20]int A[8]

המיספור של מערך בשפתCולא אפס מתחיל מ ,.1מ-

."הערך ההתחלתי של כל תא במערך הוא "זבללחרוג מגבולות המערך!אסור

Page 18: תכנות מערכות בשפת  C

תרגיל ראשון במערכים :נתונה הצהרת המערךint temp[10] כתבו תכנית

מחשב ובה - בכל אחד מאיברי המערך.0לולאה להשמת הערך .לולאה לקליטת עשרה נתוני קלט באיברי המערך-את ערכו של כל איבר במערך.2לולאה להכפלה ב .לולאה להצגה כפלט של כל איברי המערך

Page 19: תכנות מערכות בשפת  C

תרגיל במערכים נתון המערךA איברים מטיפוס שלם, ונתון המשתנה 100 בן

i.מטיפוס שלם :תאר את מטרת הלולאה הבאה

:תאר את מטרת הלולאה הבאה

?האם שתי הלולאות מבצעות את אותה המשימה.החלף את הלולאה השנייה בלולאה יעילה יותר

for (i=0; i<=99; i++)

if (A[i] % 5 == 0)

printf (“%d “, A[i]);

for (i=0; i<=99; i++)

if (i % 5 == 0)

printf (“%d “, A[i]);

Page 20: תכנות מערכות בשפת  C

תרגיל במערכים נתון המערךA שהצהרתו היא int A[8]:וערכי איבריו הם ,

עבור אילו מארבע הלולאות הבאות תהיה חריגה מגבולותהמערך?

?מה יהיו ערכי המערך אחרי ביצוע הלולאה הבאה

for (i=0; i<=7; i++)

A[i] = A[i+1];

for (i=0; i<=6; i++)

A[i] = A[i-1];

for (i=0; i<=6; i++)

A[i] = A[i]*2;

for (i=0; i<=6; i++)

A[i] = A[i*2];

for (i=1; i<=7; i++)

A[i-1] = A[i];

Page 21: תכנות מערכות בשפת  C

תרגיל במערכים ציונים )כל ציון הוא מספר 120כתבו תכנית המקבלת כקלט

(, ומציגה כפלט את מספר הציונים 100 ל-0שלם בטווח בין <include <stdio.h#הגבוהים מהממוצע.

#define SIZE 120

int main()

{

int grades[SIZE], sum = 0, counter = 0, i;

float average;

for (i=0; i<SIZE; i++) {

scanf (“%d”, &grades[i]);

sum += grades[i];

}

average = (float)sum/SIZE;

for (i=0; i<SIZE; i++)

if (grades[i] > average) counter++;

printf (“The number of above average grades is %d”, counter);

return 0;

}

Page 22: תכנות מערכות בשפת  C

תרגיל במערכים – פתרון המשתמש <include <stdio.h#בפונקציות

#define SIZE 120

void read_array (int ar[], int n)

/* :טענת כניסה ar הוא מערך של שלמים שגודלו n תאים */

/* טענת יציאה: הפונקציה קולטת ערכים ושומרת במערך */

{

int i;

for (i = 0; i < n; i++)

scanf (“%d”, &ar[i]);

}

int sum_array (int ar[], int n)

/* :טענת כניסה ar הוא מערך של שלמים שגודלו n תאים */

/* טענת יציאה: הפונקציה מחזירה את סכום איברי המערך */

{

int sum = 0, i;

for (i = 0; i < n; i++)

sum += ar[i];

return sum;

}

Page 23: תכנות מערכות בשפת  C

תרגיל במערכים – פתרון המשתמש int num_of_elements_above_bound (int ar[], int n, float bound)בפונקציות

/* :טענת כניסה ar הוא מערך של שלמים שגודלו n תאים */

/* bound טענת יציאה: הפונקציה מחזירה את מספר האיברים במערך שגדולים מ-*/

{

int i, counter = 0;

for (i = 0; i < n; i++)

counter += (ar[i] > bound);

return counter;

}

int main()

{

int grades[SIZE], above_avg;

float average;

read_array(grades,SIZE);

average = (float)sum_array(grades,SIZE) / SIZE;

above_avg = num_of_elements_above_bound(grades,SIZE,average);

printf (“The number of above average grades is %d”, above_avg);

return 0;

}