typedef struct node{ int val; struct node *left, *right; node; שאלה עצים בינאריים נתונה ההגדרה הבאה: תרגול חזרה כתוב פונקציה length), node *recreate_tree(int *in, int *post, int אשר מקבלת כפרמטרים מצביע למערך של שלמים in שמכיל את ערכי סריקת עץ בינארי בשיטת,inorder מצביע למערך של שלמים post שמכיל את ערכי סריקת אותו העץ בשיטת,postorder ומספר האיברים שבעץ.length הפונקציה בונה מחדש את העץ הבינארי ומחזירה את שורשו. node *recreate_tree(int *in, int *post, int length){ node * temp; int i; תשובה: if (!length) return NULL; temp = (node*) malloc (sizeof(node)); temp->val = post[length-]; for (i=; in[i]!= post[length-]; i++); temp->left = recreate_tree(in, post, i); temp->right = recreate_tree(in+i+, post+i, length-i-); return temp;
שאלה - קבצים כתוב פונקציה ) makefiles( void היוצרת מספר קבצים בצורה הבאה: הפונקציה קוראת מקובץ הנקרא start.txt המורכב משתי שורות בדיוק בפורמט הבא: start.txt name=<some name> count=<number> הפונקציה קוראת שני משתנים מהקובץ count) (name, ולפיהם יוצרת count קבצים חדשים, כששם כל קובץ מורכב מ- name ומספר סידורי בין ל- count, ותוכן כל קובץ מכיל.count שורה בין ל- ומספר שורות כשכל שורה בנויה מ- name count לדוגמא: אם קובץ ה- start.txt היה: start.txt name=yosi count=3 yosi.txt yosi אזי הפונקציה הייתה יוצרת את הקבצים הבאים: yosi.txt yosi yosi yosi3.txt yosi yosi yosi3
3 שאלה - 3 קבצים נתונים שני קבצים: ) קובץ נתוני הסטודנטים של הקורס שלנו, כל שורה בקובץ מכילה את הפרטים הבאים: תווים - שם הסטודנט - תווים - כתובת - 9 ספרות - מספר ת.ז. - 3 ספרות - קוד מחלקה - 3 ספרות - ציון סופי בקורס - הקובץ מסודר לפי מספר ת.ז. בסדר עולה. ) קובץ פרטי כל המחלקות של האוניברסיטה, כל שורה בקובץ מכילה את הפרטים הבאים: - תווים שם המחלקה - - 3 ספרות קוד מחלקה - שם ראש המחלקה - תווים - הקובץ מסודר לפי קוד מחלקה בסדר עולה. האוניברסיטה החליטה לפרסם שמות הסטודנטים המצטיינים בקורס שלנו. סטודנט מצטיין הוא סטודנט שקיבל את הציון הגבוה ביותר במחלקה שלו. באותה מחלקה יכולים להיות כמה סטודנטים מצטיינים. כתוב פונקציה excellent שמקבלת כפרמטרים שני מצביעים לקבצים הנ"ל ויוצרת קובץ חדש בשם excellent.dat" של כל הסטודנטים המצטיינים, כל שורה בקובץ מכילה: ספרות - שם המחלקה - 3 ספרות - קוד המחלקה - תווים - שם הסטודנט - 9 ספרות - מספר ת.ז. - הקובץ מסודר לפי קוד מחלקה בסדר עולה. הגבלה: אין להעתיק קובץ למבנה נתונים אחר (מערך, רשימה משורשרת,...) 3
4 תשובה: void excellent(file* student, FILE* department){ FILE* excel; char name[],id[], dp_name[]; int cod_s, cod_d, grade, max; rewind(department); if((excel=fopen("excellent.dat","w"))== NULL){ printf("error in access to file department\n");exit(); while(fscanf(department,"%[^$]%3d%*c",dp_name,&cod_d)==){ max = -; rewind(student); while(fscanf(student,"%*49c%3d%3d%*c",&cod_s,&grade)==) if(cod_s==cod_d && grade>max) max = grade; if(max == -)continue; rewind(student); while(fscanf(student,"%[^$]%*c%9s%3d%3d%*c", name,id,&cod_s, &grade)==4) if(cod_s==cod_d && grade==max) fprintf(excel,"%s%3d%s%s\n",dp_name,cod_d,name,id); if(fclose(excel)== EOF){ printf("error closing file excellent.dat\n"); exit(); 4
5 שאלה - 4 קבצים לאור הביקוש הרב החליטה האוניברסיטה לאפשר לסטודנטים להנדסה לעבור למחלקה למדעי המחשב על סמך הציונים בקורסי C ו-.JAVA סטודנט מהנדסה יוכל לעבור רק אם נבחן בשני הקורסים הנ"ל וקיבל בשני הקורסים ציון מעל 9.נתון קובץ של כל הסטודנטים של הפקולטה להנדסה, כל שורה בקובץ מכילה את הפרטים הבאים: תווים - שם הסטודנט - תווים - כתובת - 9 ספרות - מספר ת.ז. - - אות אחת שנה - 3 ספרות - קוד מחלקה - 5 תווים - שם מחלקה - הקובץ מסודר לפי מספר ת.ז. בסדר עולה. נתונים גם שני קבצים של הציונים של כל הסטודנטים (מכל האוניברסיטה ולא רק מהנדסה) שנבחנו ב- C וב- JAVA. כל שורה בכל קובץ מכילה את הפרטים הבאים: תווים - שם הסטודנט - 9 ספרות - מספר ת.ז. - 5 ספרות - מס' נבחן - 3 ספרות - ציון - הקבצים מסודרים לפי מספר ת.ז. בסדר עולה. (יש סטודנטים בהנדסה שלא נבחנו ב- C או ב- JAVA ) כתוב פונקציה change_dpt שמקבלת כפרמטרים שלושה מצביעים לקבצים הנ"ל, ומחרוזת שהיא השם של הקובץ חדש שהפונקציה יוצרת. הקובץ החדש הוא הקובץ של הסטודנטים הזכאים לעבור למחלקה למדעי המחשב עם ציון מעל 9 ב- C וב- JAVA. כל שורה בכל קובץ מכילה: תווים - שם הסטודנט - 9 ספרות - מספר ת.ז. - 3 ספרות - קוד מחלקה - 3 ספרות - ציון ב- C - - 3 ספרות ציון ב- JAVA - הקובץ מסודר לפי מספר ת.ז. בסדר עולה. הגבלה: אין לקרוא קובץ יותר מפעם אחת. רשימה משורשרת,קובץ, עץ...) אין להעתיק קובץ למבנה נתונים אחר (מערך, 5
6 תשובה: void change_dpt(file *eng, FILE *c, FILE *java, char *filename){ FILE* fnew; char name[]; long ide,idc,idj; int cod,gradec,gradej,flage,flagc,flagj; if(!(fnew=fopen(filename,"w"))) exit(); flage=fscanf(eng,"%[^\n]%*c%ld%*c%d%*6c",name,&ide,&cod); flagc=fscanf(c,"%*c%9ld%*5c%d%*c",&idc,&gradec); flagj=fscanf(java,"%*c%9ld%*5c%d%*c",&idj,&gradej); while(flage==3 && flagc== && flagj==){ if(ide<idc ide<idj){ flage=fscanf(eng,"%[^\n]%*c%ld%*c%d%*6c", name,&ide,&cod); continue; if(idc<ide idc<idj){ flagc=fscanf(c,"%*c%9ld%*5c%d%*c",&idc,&gradec); continue; if(idj<ide idj<idc){ flagj=fscanf(java,"%*c%9ld%*5c%d%*c",&idj,&gradej); continue; if(gradec>9&&gradej>9) fprintf(fnew,"%s%9d%3d,%3d%3d\n", name,ide,cod,gradec,gradej); flage=fscanf(eng,"%[^\n]%*c%ld%*c%d%*6c", name,&ide,&cod); flagc=fscanf(c,"%*c%9ld%*5c%d%*c",&idc,&gradec); flagj=fscanf(java,"%*c%9ld%*5c%d%*c",&idj,&gradej); if(fclose(fnew)==eof) exit(); 6
7 שאלה - 5 קבצים נתונים קבצים של כל האורחים לחתונה (אחד של אורחי הכלה ואחד של אורחי החתן). 5 תווים 5 תווים 3 ספרות (מ- עד ) 3 תווים (מלל חפשי) כל שורה בקבצים מכילה את הפרטים הבאים: שם פרטי שם משפחה גיל הערות הקבצים ממוינים לפי שם משפחה בסדר אלפבית ועבור אותו שם משפחה לפי שם פרטי גם לפי סדר אלפבית. (שימו לב שבקבצים שם המשפחה מופיע אחרי השם הפרטי). כתוב פונקציה filename) guest(file* f, FILE* f, char* filename, char* שמקבלת כארגומנטים שני מצביעים לקבציים הנ"ל ושתי מחרוזות שהן השמות של הקבצים החדשים שהפונקציה יוצרת. שני הקבצים החדשים הם במבנה זהה לשני הקבצים הנתונים. הקובץ החדש הראשון מכיל את רשימת האורחים שמופיעים באחד בלבד משני הקבצים, והקובץ החדש השני מכיל את רשימת האורחים המשותפים לחתן ולכלה. שני הקבצים החדשים גם ממוינים לפי שם משפחה ושם פרטי. הגבלה: אין לקרוא קובץ יותר מפעם אחת. אין להעתיק קובץ למבנה נתונים אחר (מערך, רשימה משורשרת, עץ,קובץ אחר...) 7
8 תשובה: void guests(file* f, FILE* f, char *filename, char *filename ){ char first[6],last[6], name[3], details[34], first[6], last[6], name[6], details[34]; FILE *twice, *once; int flag, flag; if(!(once = fopen(filename, "w"))){ puts(" The program cannot open file"); exit(); if(!(twice = fopen(filename, "w"))){ puts(" The program cannot open file"); exit(); flag=fscanf(f, "%5[^$]%5[^$]%[^\n]*c",first,name,details); if(flag==3){ strcpy(name,last); strcat(name,first); flag=fscanf(f, "%5[^$]%5[^$]%[^\n]*c",first, name, details); if(flag==3){ strcpy(name,last); strcat(name,first); while(flag==3 flag==3) if(flag==3 && flag==3 &&!strcmp(name,name)){ fprintf(twice,"%5s%5s%33s\n",first,name,details); flag=fscanf(f, "%5[^$]%5[^$]%[^\n]*c", first,name,details); if(flag==3){ strcpy(name,last); strcat(name,first); flag= fscanf(f, "%5[^$]%5[^$]%[^\n]*c", first, name, details); if(flag==3){ strcpy(name,last); strcat(name,first); else if(flag!=3 flag==3 && strcmp(name,name)<){ fprintf(once,"%5s%5s%33s\n",first,name,details); flag= fscanf(f, "%5[^$]%5[^$]%[^\n]*c", first, name, details); if(flag==3){ strcpy(name,last); strcat(name,first); else{ fprintf(once,"%5s%5s%33s\n",first,name,details); flag= fscanf(f, "%5[^$]%5[^$]%[^\n]*c", first, name, details); if(flag==3){ strcpy(name,last); strcat(name,first); fclose(once); fclose(twice); 8
9 typedef struct node{ int value; struct node* next; Node; שאלה - 6 רשימות נתונה ההגדרה הבאה: הפונקציה הבאה מחפשת את האמצע של הרשימה ושם חוצה את הרשימה לשתי רשימות. Node* middle(node* source){ Node *fast, *slow, *source; if (source==null???? ) return NULL; slow = source; fast =???? ; while (?? 3??) { fast = fast->next; if (?? 4?? ) { slow = slow->next; fast = fast->next; source = slow->next; slow->next =?? 5?? ; return?? 6?? ; השלם בדף התשובות את הקטעים החסרים. פתרון: Node* middle(node* source){ Node *fast, *slow, *source; if (source==null source->next==null) return NULL; slow = source; fast = source->next; while (fast) { fast = fast->next; if (fast) { slow = slow->next; fast = fast->next; source = slow->next; slow->next = NULL ; return source; 9
שאלה - 7 רשימות נתונות ההגדרה הבאה שמאפשרת להגדיר מבנה של רשימה משורשרת: typedef struct item{ int digit; struct item *next; item; ניתן לייצג מספר טבעי גדול ע"י רשימה משורשרת. כל איבר ברשימה מכיל סיפרה כך שלמשל המספר 3456789 מיוצג ע"י הרשימה הבאה: 9 8 7 6 5 4 3 NULL שימו לב שהאיבר הראשון מכיל את ספרת היחידות של המספר, השני ספרת ההעשרות,... והאיבר האחרון מצביע ל- NULL. המספר אפס מיוצג פשוט ע"י רשימה ריקה.NULL כתוב פונקציה num) void add(item* num, item* המקבלת את העוגן של שתי רשימות משורשרות שמייצגות שני מספריים טבעיים גדולים. הפונקציה משנה את הרשימה הראשונה כך שהיא תייצג את סכום שני המספרים המיוצגים ע"י הארגומנטים. ידוע שהמספר ש- num מייצג גדול מהמספר ש- num מייצג.
שאלה - 8 רשימות typedef struct node{ int val; struct node *next; node; להלן הגדרה : עבור רשימה מעגלית השלם את החלק החסר בקוד הבא כך שהפונקציה תמחק את כל איברים הכפולים שברשימה. (עבור האיברים הכפולים הפונקציה משאירה רק את ההופעה הראשונה). void single(node* first){ node *temp, *p, *del; int i; temp = first; while(????!=first){ p = temp; while(????!=first){ if(?? 3?? == temp->val){ del =?? 4??;?? 5?? = del ->next;?? 6??; else p = p -> next;?? 7??; לדוגמה, אחרי הביצוע של הפונקציה הנ"ל הרשימה הראשונה תהפוך לשניה:
typedef struct item{ int val; struct item * next; item; שאלה 9 רקורסיה ורשימות נתונה ההגדרה הבאה: והפונקציה הבאה: item* what(item* list, item* list) { if(!list) return list; if(!list) return list; if(list->val == list->val) list->next = what(list->next, list->next); else list->next = what(list->next, list); return list; אם list ו- list מצביעים כל אחד על ראש רשימה משורשרת: עבור שתי הרשימות הבאות צייר בדף התשובות לאן מצביע ההחזר של הפונקציה ואת מצב הרשימות אחרי הקריה לפונקציה הנ"ל.
3 שאלה - רקורסיה ניתן לייצג תמונה באמצעות מפת ביטים.(bitmap) המפה היא למעשה מערך דו מימדי של תאים פיקסלים pixel) קיצור של.(picture cell כל פיקסל נושא צבע. לשם הפשטות החלטנו לייצג את הצבעים השונים באמצעות מספרים שלמים.(integers) יש לכתוב פונקציה רקורסיבית : void paint(int**map, int size, int x, int y, int color) המדמה "צביעת שטח" בתוך תמונה (דומה לשימוש בדלי הצבע בתוכנת הצייר). הפונקציה מקבלת חמישה פרמטרים : size מספר שלם חיובי map מערך דו מימדי בגודל size x size המייצג את מפת הפיקסלים של ממנה מורכבת התמונה. קואורדינטות x, y מייצגות קואורדינאטות נקודה. color פרמטר המייצג את הצבע החדש שאיתו צריך למלא את השטח המתאים. צביעת השטח מתפשטת החוצה החל מהנקודה שנבחרה, לכל ארבעת התאים מסביב שיש להם אותו צבע. לדוגמא נתונה המפה הבאה: 6 9 6 5 4 3 8 4 6 7 לאחר הפעלת paint עם color=5,=x,=y נקבל: 6 9 6 5 4 3 8 5 5 5 4 6 7 5 void paint(int**map, int size, int x, int y, int color){ int oldcolor; oldcolor=map[y][x]; map[y][x]=color; if(x> && map[y][x-]==oldcolor) paint(map,size,x-,y,color); if(x<size- && map[y][x+]==oldcolor) paint(map,size,x+,y,color); if(y> && map[y-][x]==oldcolor) paint(map,size,x,y-,color); if(y<size- && map[y+][x]==oldcolor) paint(map,size,x,y+,color); פתרון: 3
4 שאלה - רקורסיה כתוב פונקציה רקורסיבית letter) void startbychar(char *string, char אשר מקבלת מחרוזת ותו, ומדפיסה את כל הסיומות של המחרוזת המתחילות בתו הזה. ידפסו השורות הבאות: abcbabcbdbabca abcbdbabca abca a לדוגמה עבור המחרוזת babcbabcbdbabca" והתו a פתרון: void startbychar(char string[ ], char letter){ if (!*string) return; if (*string==letter) puts(string); startbychar(string+); 4
5 שאלה רקורסיה ועצים #include <stdio.h> #include <stdlib.h> typedef struct item item; struct item{ int data, data ; item *left, *right; ; מה הפלט של התכנית הבאה: int what(item* here, item* that){ if(!that) return ; return (here->data == that->data) +what(here, that->left)+what(here, that->right); void what(item *head){ if(!head)return; head->data = what(head, head); what(head->left); what(head->right); item *insert(item *root, item *leaf){ if (!root)return leaf; if(leaf->data < root->data) root->left=insert(root->left, leaf); else root->right=insert(root->right, leaf); return root; void print(item *root){ if(!root)return; print(root->left); printf("%d %d\n",root->data, root->data); print(root->right); void main(){ item *root=null, *temp; int a[]= { 5,,4,9,,,7,3,,6,8,, b[]= {,3,,3,3,33,,,,,3,,i; for(i=; i<; i++){ temp=(item*)malloc(sizeof(item)); temp->left=temp->right=null; temp->data=a[i]; temp->data=b[i]; root=insert(root,temp); what(root); print(root); Answer: What changes every node s data to the number of nodes in both its subtrees having the same data value. 5
6 typedef struct node { struct { int key; char value[3]; info; struct node *left, *right; node; שאלה 3 עצים ורקורסיה כדי לממש עץ חיפוש בינארי, הוגדר המבנה הבא : node* What(node* root, int a, int b) { node *new = root; if (root) { if (root->info.key < a) new = What (root->right, a, b); else if (root->info.key > b) new = What (root->left, a, b); נתונה הפונקציה הבאה : else if ((new = (node*) malloc(sizeof(node)))) { new->info = root->info; new->left = What (root->left, a, b); new->right = What (root->right, a, b); else new = NULL; return new; סעיף א ( נקודות) מצביע על השורש שלו root: בהינתן העץ הבינארי הבא ש - ( root,, What( צייר את העץ שהפונקציה תחזיר לאחר הקריאה : סעיף ב (5 נקודות) הסבר בקצרה מה יעודה של הפונקציה.What The What function returns a new tree which is a subtree of the original tree, and for every value x of the new tree, a<=x<=b. 6
7 שאלה - 4 רשימות נתונה רשימה מקושרת רגילה מוגדרת ע"י שני הפוינטרים הבאים: הראשון מצביע על האיבר הראשון ברשימה והשני מצביע על האיבר האחרון ברשימה. השלם ב- 7 הקטעים המסומנים ב-???? כך שהפונקציה enqueue תכניס איבר חדש ברשימה. typedef struct Queue { item *head, *tail; Queue; typedef struct item item; struct item { int value; item *next; ; Queue enqueue(queue q, int number) { item *temp =???? ; temp->value =???? ; temp->next =?? 3?? ; if (?? 4?? ) q.head = q.tail =?? 5?? ; else {?? 6?? ; q.tail =?? 7?? ; return q; פתרון:???? = (item*) malloc(sizeof(item))???? = number?? 3?? = NULL?? 4?? =!q.tail או!q.head או!q.tail&&!q.head?? 5?? = temp?? 6?? = q.tail->next = temp?? 7?? = temp 7
8 שאלה - 5 רשימות פונקצית single מקבלת את העוגן של רשימה משורשרת רגילה,head הפונקציה משחררת מהרשימה את כל המבנים שהערך שבהם הופיע מקודם ברשימה. (הפונקציה משאירה כל ערך פעם כך שהפונקציה תבצע את הנדרש. typedef struct item{ int value; struct item *next; item; void single(item *head){ item *prev, *temp; while( head ){ prev = head; temp = head -> next; while( temp ) if(???? ){???? = temp -> next; free(?? 3?? ); temp =?? 4?? ; else{ prev =?? 5?? ; temp =?? 6?? ;?? 7?? ; אחת ברשימה). השלם בדפי התשובות את 7 הקטעים המסומנים ב-???? void single(item *head){ item *prev, *temp; while( head ){ prev = head; temp = head -> next; while( temp ) if( head ->value == temp->value ){ prev -> next = temp -> next; free( temp ); temp = prev -> next; else{ prev = temp ; temp = temp-> next; head = head -> next; פתרון: 8
9 שאלה 6 קבצים Clang5a בהתאחדות הכדורסל הישראלית החליטו לנהל תוצאות משחקי העונה באופן ממוחשב. נתון קובץ ראשי של כל השחקנים שמשחקים בעונה הזאת עם פרטים מעודכנים עד לשבוע האחרון. כל שורה בקובץ שמכילה את הפרטים הבאים: תווים שם השחקן 9 ספרות או תווים מס. ת.ז. או דרכון מספר הקבוצה של השחקן ספרות ספורות מספר השחקן סה"כ נקודות בעונה 4 ספרות הקובץ ממוין לפי מספר הקבוצה בסדר עולה ובתוך אותה קבוצה לפי מספר שחקן גם בסדר עולה. כל שבוע, ההתאחדות מקבלת מספר קבצי עדכון בשם GAMESn.TXT עם נתוני המשחקים שהתקיימו באותו שבוע, באשר n הוא מספר המשחק (לכל משחק קוד ייחודי בין ל- 9 ) כל שורה GAMESn.TXT הבאים: בקבצים מייצגת פעולה במשחק ומכילה את הפרטים ספרות ספרות 3 ספרות מספר הקבוצה של השחקן מספר השחקן מספר נקודות כל קבצי העדכון ממוינים לפי מספר הקבוצה בסדר עולה ובתוך אותה קבוצה לפי מספר שחקן גם בסדר עולה. כתוב פונקציה *filename) void results(file* fp, char שמקבלת כארגומנטים מצביע לקובץ הראשון ומחרוזת שהיא השם של הקובץ החדש שהפונקציה יוצרת. הקובץ החדש הוא במבנה זהה לקובץ הראשי והוא למעשה הקובץ הראשי מעודכן בהתאם לנתונים של כל הקבצים שהתקבלו באותו שבוע. לא ידוע כמה קבצים התקבלו (ז"א n שמופיע בשם הקובץ אינו ידוע). ניתן להניח שכל הקבצים תקינים, ז"א שכל השחקנים שרשומים בקבצים GAMESn.TXT רשומים כולם גם בקובץ הראשי. הגבלה: אין לקרוא קובץ יותר מפעם אחת. אין להעתיק קובץ למבנה נתונים אחר (מערך, רשימה משורשרת, עץ,קובץ אחר...) FILE int *arr[]; eof[]; רמז: מומלץ להשתמש במערכי עזר שהוגדרו באופן הבא: 9
פתרון: void results(file* fp, char *filename){ char details[3], nameg[]="games*.txt"; int id, point, idg[], pointg[], eof[]={, i; FILE *arr[], *newf; if(!(newf = fopen(filename, "w"))){ printf(" The program cannot open file %s\n", filename); exit(); for(i=; i<; i++){ nameg[5]=''+i; if(arr[i]=fopen(nameg,"r")) eof[i]= fscanf(arr[i],"%4d%3d%*c",idg+i,pointg+i); while(fscanf(fp, "%9[^$]%4d%4d%*c",details,&id,&point)==3){ for(i=; i<; i++) while(eof[i]== && idg[i]==id){ point += pointg[i]; eof[i]= fscanf(arr[i],"%4d%3d%*c",idg+i,pointg+i); fprintf(newf,"%9s%4d%4d\n",details,id,point); fclose(newf); for(i=; i<; i++) if(arr[i])fclose(arr[i]);
שאלה 7 קבצים clangb מסכמת את המכירות של סוכניה. אם סה"כ המכירות בסוף כל שנה חברת "פוקסי בע"מ" של סוכן מסוים קטן מסכום מינימאלי שנקבע מראש החברה תבדוק המשך פעילותו של הסוכן ואם סה"כ המכירות של הסוכן מעל סכום מקסימאלי שנקבע הסוכן מועמד לקידום. נתון קובץ ראשי של כל הסוכנים של החברה, כל שורה בקובץ מכילה: תווים שם הסוכן ספרות מספר הסניף 3 ספרות מספר הסוכן תווים אזור פעילות הקובץ ממוין לפי מספר סניף בסדר עולה ובתוך אותו סניף לפי מספר סוכן גם בסדר עולה. עבור כל חודש לחברה קובץ עם נתוני המכירות של הסוכנים שעבדו באותו חודש. כל שורה בכל קובץ מכילה את הפרטים הבאים: ספרות מספר הסניף 3 ספרות מספר הסוכן 7 ספרות מכירות הקבצים ממוינים לפי מספר סניף בסדר עולה ובתוך אותו סניף לפי מספר סוכן גם בסדר עולה. כתוב פונקציה void report(file* agent, FILE* fp[], int min, int max, char* name, char* name) שמקבלת כארגומנטים: agent מצביע לקובץ הראשי של פרטי הסוכנים, fp מערך של מצביעים לקבציי המכירות החודשיים, min ו- max סכומים מינימאלי ומקסימאלי שנקבעו מראש name שם של קובץ חדש שהפונקציה יוצרת. הקובץ החדש הוא קובץ הסוכנים שסה"כ המכירות שלהם קטן מ- min. הקובץ במבנה דומה לקובץ הראשי עם בסוף כל שורה סה"כ המכירות השנתיות של אותו סוכן (9 ספרות), name שם של קובץ חדש שהפונקציה יוצרת. הקובץ החדש הוא קובץ הסוכנים שסה"כ המכירות שלהם גדול מ- max. הקובץ במבנה דומה לקובץ הראשי עם בסוף כל שורה סה"כ המכירות השנתיות של אותו סוכן (9 ספרות), כל שורה בקובץ מכילה: ספרות מספר הסניף 3 ספרות מספר הסוכן תווים שם הסוכן 9 ספרות סה"כ מכירות שימו לב: בכל הקבצים אין תווי הפרדה בין השדות אין לעבור על קובץ יותר מפעם אחת. אין להעתיק קובץ שלם למבנה נתונים אחר (מערך, רשימה משורשרת, עץ,קובץ אחר...)
#include<stdio.h> #include<stdlib.h> void report(file *agent, FILE* fp[], int min, int max, char* name, char* name){ FILE *f, *f; int i,eof[], id[], idmain; long sales[], total; char name[]; if(!(f=fopen(name,"w"))) exit(); if(!(f=fopen(name,"w"))) exit(); for(i=;i<;i++) eof[i]=fscanf(fp[i],"%5d%7ld*c",id+i,sales+i); while(fscanf(agent, "%[^$]%5d%**c",name, &idmain)==){ total=; for(i=;i<;i++) if(eof[i]!=eof && id[i]==idmain){ total += sales[i]; eof[i]=fscanf(fp[i],"%5d%7ld*c", id+i, sales+i); if(total < min) fprintf(f, "%5d%s%9d\n", idmain, name, total); else if(total >= max) fprintf(f, "%5d%s%9d\n", idmain, name, total); fclose(f); fclose(f);
3 שאלה 8 קבצים פתרון: Clangb חברת הרכבות מעוניינת לשפר את זמני הנסיעה של הרכבות על ידי מציאת נקודות "מפגש הרכבות" שקיימות. נקודת "מפגש רכבות" היא נקודה שבה קיימת מסילה אחת בין שתי נקודות ושתי רכבות מעוניינות לעבור באותה המסילה (לכיוונים שונים כמובן) באותו הזמן בדיוק, אחת הרכבות נאלצת להמתין עד שהרכבת השנייה תעבור. לכל רכבת קיים קובץ מסלול יומי עם המבנה הבא: בשורה הראשונה : o מספר קטר 3 ספרות מהשורה השנייה ואילך: o שעת הגעה למסילה 4 ספרות במבנה hhmm בפורמט של 4 שעות (השעה 8:3 מיוצגת 83) תווים תווים 4 ספרות ספרה אחת (- מסילה יחידה, - מסילה כפולה) (אם המסילה כפולה אז אין בעיה של מפגש רכבות). o o o o נקודת התחלתית נקודת סיום קוד מסילה סוג מסילה כל קובצי הרכבות ממוינים בסדר עולה לפי שעת יציאה מנקודת המוצא. כתוב פונקציה *outfile) void trainreport(file *trainarray[ ], int trainnum, char המקבלת trainarray מערך של מצביעים לקבצים של נתוני מסלולי הרכבות, trainnum גודלו של המערך, outfile שם של קובץ חדש שהפונקציה יוצרת. בקובץ החדש רשום מידע על "מפגשי רכבות" מבין כל הקבצים. כמובן שלא יכולים להגיע לאותה מסילה באותה שעה יותר משתי רכבות. בקובץ החדש כל שורה מכילה את הנתונים הבאים: 4 ספרות במבנה hhmm שעת יציאה 4 ספרות קוד מסילה 3 ספרות, הקטר עם המספר היותר קטן מספר קטר 3 ספרות, הקטר עם המספר היותר גדול מספר קטר הקובץ החדש מוין בסדר עולה לפי שעת יציאה מנקודת המוצא ומיון משנה לפי מספר מסילה. שימו לב: בכל הקבצים אין תווי הפרדה בין השדות כמובן שלא יכולים להגיע לאותה מסילה באותה שעה יותר משתי רכבות. הגבלות: אין לעבור על קובץ יותר מפעם אחת. אין להעתיק קובץ שלם למבנה נתונים אחר (מערך, רשימה משורשרת, עץ,קובץ אחר...) 3
4 #include<stdio.h> #include <stdlib.h> typedef struct train{ int eof, loco, time, num; train; void trainreport(file *trainarray[ ], int trainnum, char *outfile){ train *arr; FILE * fout; int i, way, mintime=5, ind, ind=-; if(!(fout=fopen(outfile,"w"))) exit(); arr = (train*)malloc(sizeof(train)*trainnum); if(!arr)exit(); for(i=; i<trainnum; i++){ fscanf(trainarray[i], "%d", &arr[i].loco); // search for the first line with way== in the file of trainarray[i] do arr[i].eof = fscanf(trainarray[i],"%4d%*c%4d%d", &arr[i].time, &arr[i].num, &way); while(way== && arr[i].eof==3); while(){ for(i=; i<trainnum; i++){ if(arr[i].eof!=3) continue; if(arr[i].time > mintime) continue; if(arr[i].time < mintime ){ mintime = arr[i].time; ind = i; ind=-; continue; /* case of arr[i].time == mintime */ if(arr[i].num > arr[ind].num) continue; // search for the minimal railway number if(arr[i].num < arr[ind].num){ ind = i; ind=-; continue; /* case of arr[i].time == mintime && arr[i].num == arr[ind].num */ if(arr[i].loco < arr[ind].loco){ ind = ind; ind = i; else ind = i; // for if(mintime == 5) break; // case of eof in all the files 4
5 if(ind >=){ // locomotives on the same railway found fprintf(fout, "%4d%4d%3d%3d\n", mintime, arr[ind].num, arr[ind].loco, arr[ind].loco); do arr[ind].eof = fscanf(trainarray[ind],"%4d%*c%4d%d", &arr[ind].time, &arr[ind].num, &way); while(way== && arr[ind].eof==3); ind = -; do arr[ind].eof = fscanf(trainarray[ind],"%4d%*c%4d%d", &arr[ind].time, &arr[ind].num, &way); while(way== && arr[ind].eof==3); mintime = 5; free(arr); fclose(fout); 5
6 שאלה -9 רקורסיה Clang9a Clangb נתון מערך דו מימדי של מספרים שלמים וחיוביים F[N][M] int,מערך של מספרים שלמים וחיוביים S[M] int ומספר שלם k.אנו נרצה לבדוק האם קיימות לכל היותר k שורות של המערך ) F כך שאיחודם מכיל את כל המספרים שבמערך S. F = 5 7 3 9 3 S = 7 3 לדוגמה: עבור =k אנו נקבל תשובה חיובית כי: שורה מספר ושורה מספר 3 במערך F (בעלי האינדקסים ו- ) מכילות את המספרים:,5,7,,3 המכילות את כל מספרי המערך S. אולם עבור נקבל כי התשובה שלילית, כיוון שאין שורה אחת במערך F שמכילה כל אברי המערך S. הניח שיש ברשותך את הפונקציות הבאות: int all_zero(int x[m]) ; void x_zero( int x[m],int y[m]) ; void copy(int dest[m], int src[m]); מחזירה אם כל M אברי המערך הם אפס אחרת מחזירה מאפסת את כל איברי המערך x אשר מופיעים במערך y מעתיקה את תוכן המערך src למערך dest השלם את הפונקציה הרקורסיבית covers המחזירה אם ניתן לכסות את כל המערך S ע"י לכל היותר k שורות מהמערך F כאשר מתחילים מהשורה ה- i תי-. int covers( int F[N][M], int S[M], int i, int k){ int temp[m] = {; if (????)???? ; if (???? )?? 3?? ;?? 4???? 5?? ;?? 6?? ;?? 8?? ;?? 8?? ; int covers(int F[N][M],int S[M],int i,int k){ int temp[m]={; if( all_zero(s)) return ; if( k== i==n ) return ; if(covers(f,s,i+,k)) return ; copy(temp,s); x_zero(temp,f[i]); return covers(f,temp,i+,k-); פתרון: 6
7 מוגדר מערך bricks[3]={,,3. int שאלה רקורסיה נתון מערך של אורכי לבנים. למשל עבור לבנים באורך של, ו- 3.bricks ברצוננו לבנות פס באורך נתון מהלבנים של המערך הפונקציה width) int HowManySets( int *bricks, int size, int מקבלת כארגומנטים : bricks - מערך של אורכי הלבנים, המערך ממוין בסדר עולה, - גודל המערך, size width - אורך הפס הנדרש. הפונקציה מחזירה את מספר האפשרויות לבנות פס באורך width מהלבנים של המערך bricks אינו מוגבל..bricks מספר הלבנים מכל אורך שרשום במערך 7 width שווה 4 הפונקציה מחזירה למשל עבור מערך הדוגמה ו- כי הסידורים האפשריים הם: 3 3 השלימו בדף התשובות הקטעים החסרים המסומנים ב -?? N??. int HowManySets (int *bricks, int size, int width){ int res=,i; if(????) return ; for(???? ) if(?? 3?? >=bricks[i])?? 4?? += HowManySets (?? 5??,?? 6??,?? 7??); return?? 8??; פתרון: int HowManySets (int *bricks, int size, int width){ int res=,i; if(! width ) return ; for( i=; i<size; i++ ) if( width >=bricks[i]) res += HowManySets (bricks, size, widthbricks[i]); return res ; 7
8 שאלה רקורסיה clanga נתונה התכנית הבאה: void what(char *s, char *s, char *temp, int index){ if (*s == '\'){ strcpy(temp+index, s); printf("%s\n", temp); return; if (*s == '\'){ strcpy(temp+index, s); printf("%s\n", temp); return; temp[index] = *s; what(s+, s, temp, index+); temp[index] = *s; what(s, s+, temp, index+); int main(){ char *str = "AB"; char *str = "xyz"; char *temp= (char *)malloc(strlen(str)+strlen(str)+); what(str, str, temp, ); סעיף א'. מה הפלט של התכנית? סעיף ב'. הסבר בקצרה מה מטרתה של הפונקציה?what פתרון: ABxyz AxByz AxyBz AxyzB xabyz xaybz xayzb xyabz ayazb xyzab סעיף א ( נקודות ( סעיף ב (5 נקודות ( הפונקציה מדפיסה את כל הצירופים האפשריים בין שתי המחרוזות שהיא מקבלת תוך כדי שמירת סדר האותיות היחסי של כל אחד מהמחרוזות המקוריות. 8
9 שאלה רקורסיה prog4a כתוב פונקציה רקורסיבית col) void shablul(int** ar, int row, int col, int row, int שממלאת את המערך הדו-מימדי ar במספרים עולים החל מ- בצורת שבלול. הפונק' מקבלת מצביע למערך,ar מס' שורה (row) ועמודה (col) של התא השמאלי עליון של המערך ומס' שורה (row) ועמודה (col) של התא הימני תחתון של המערך. אין להגדיר פונקציה נוספת. לדוגמא עבור 4) shablul(ar,,, 3, 3 4 5 נקבל: 4 5 6 7 6 3 9 8 7 9 8 #include <stdio.h> #include <string.h> #include <stdlib.h> פתרון: #define ROWS 4 #define COLS 5 void shablul(int** ar, int row, int col, int row, int col) { int i; static int num = ; if (row<=row && col<=col) { /*Filling top row:*/ 3 4 5 for (i=col; i<=col; i++) 4 5 6 7 6 ar[row][i] = num++; 3 9 8 7 /*Filling right column: */ 9 8 for (i=row+; i<=row; i++) ar[i][col] = num++; /*Filling bottom row: */ if (row>row)/*only when the array has more than one row. */ for (i=col-; i>=col; i--) ar[row][i] = num++; /*Filling left column:*/ if (col>col)/*only when the array has more than one column. */ for (i=row-; i>row; i--) ar[i][col] = num++; shablul(ar, row+, col+, row-, col-); 9
3 את השורה את העמודה הימנית, העקרון הוא למלא במספרים את השורה העליונה, התחתונה ואת העמודה השמאלית ואחר כך לקרוא לרקורסיה שתפתור לנו את הבעיה שנשארת ללא התאים שמלאנו. למשל, אחרי הקריאה הרקורסיבית הראשונה נשאר אם הבעיה: shablul(,,,3) 5 6 7 9 8 void main() { int i,j; int **arr; תוכנית ראשית שממחישה את השימוש בפונקציה: if(!(arr=(int **)malloc(rows*sizeof(int *)))) { printf("error allocating memory! Exitting "); return; for(i=;i<rows;i++) { if(!(*(arr+i)=(int *)malloc(cols*sizeof(int)))) { printf("error allocating memory! Exitting "); return; shablul(arr,,,rows-,cols-); /*Print the shablul array:*/ for(i=;i<rows;i++) { for(j=;j < COLS;j++) printf("%d\t",arr[i][j]); printf("\n"); 3
3 שאלה 3 רקורסיה clang3a כתוב פונקציה רקורסיבית lines) void V(int שמדפיסה את האות V בכוכביות ב- lines שורות. לדוגמא עבור (5)V יודפס: * * * * * * * * * void V( int lines ){ static int firstspace=; int i; הכוכבית הראשונה חייבת להופיע בתחילת השורה הראשונה. אין להגדיר פונקציה נוספת. for (i=; i < firstspace; i++) printf(" "); printf ("*"); if (lines == ){ printf("\n"); firstspace =; return ; for (i=; i< ((*lines-3)) ; i++) printf(" "); printf("*\n"); firstspace ++; פתרון : V(lines-); פתרון (עבור lines מוגבל) void V(int lines){ static int start=; char str[]=" "; str[start]=str[*lines-+start++]='*'; puts(str); if(n==){ start=; return; V(lines-); 3
3 שאלה 4 רקורסיה prog3a כתוב פונקציה רקורסיבית lines) void X(int שמדפיסה את האות X בכוכביות ב- lines שורות ) lines נתון אי-זוגי). * * * * * * * * * * * * * * * * * לדוגמא עבור (9)X יודפס: הכוכבית הראשונה חייבת להופיע בתחילת השורה הראשונה. אין להגדיר פונקציה נוספת. פתרון: void X(int lines){ int static blank; int i; if (lines < ) return; for (i=; i<blank; i++) putchar(' '); putchar('*'); if(lines==){ puts(""); return; for (i=; i<lines-; i++) putchar(' '); puts("*"); blank++; X(lines -); blank--; for (i=; i<blank; i++) putchar(' '); putchar('*'); for (i=; i<lines-; i++) putchar(' '); puts("*"); 3
33 שאלה - 5 קבצים נתון קובץ שבו פרטי עובדי החברה. כל שורה בקובץ מכילה את הפרטים הבאים: 3 תווים 9 ספרות ספרות - - - שם העובד ת.ז. מחלקה הקובץ ממוין לפי ת.ז. כתוב פונקציה doublesort שמקבלת מצביע לקובץ הנ"ל ומצביע לקובץ חדש. הפונקציה מעתיקה לקובץ החדש את כל השורות של הקובץ המקורי אבל ממויין לפי מספר מחלקה ובתוך אותה מחלקה ממוין לפי ת.ז. אין להעתיק את הקובץ למבנה נתונים אחר. void doublesort(file *old, FILE *new){ int dept, i; char details[4]; תשובה: for (i = ; i <; i++) { rewind(old); while(fscanf(old, %39[^$]%d%*c,details,&dept) ==) if (dept==i) fprintf(new, %s%d\n, details, dept); 33
34 שאלה 5 קבציםClanga אגף התנועה של משטרת ישראל התקין לאחרונה לאורך "הכבישים האדומים" מצלמות מהירות גלויות ונסתרות ומצלמות רמזור. לכל מצלמה קובץ שבו מתועדים נתוני העברות, הקבצים ממוספרים מ- עד number - number הוא מספר המצלמות שהותקנו - ולכל אחד שם מתאים מ-.txt עד כל הקבצים במבנה דומה: בשורה הראשונה של הקובץ מופיעים: מיקום המצלמה - תווים סוג מצלמה - תווים.number.txt ובהמשך כל שורה בקובץ מכילה את פרטי העברות הבאים: 6 ספרת yymmdd) לדוגמה התאריך של היום מקודד 6) תאריך 4 ספרות hhmm) לדוגמה השעה 9: מקודדת (9 שעה 3 ספרת מהירות 7 ספרות מס' הרכב שם קובץ תמונה תווים הקבצים ממוינים בסדר כרונולוגי (מיון ראשי לפי תאריך, ומיון משנה לפי שעה) שימו לב שאותו מספר רכב יכול להופיע מספר פעמים באותו קובץ ואפילו ברצף. על מנת לעזור למשטרת ישראל נכתוב פונקציה number) int radar(int שמקבלת number מספר המצלמות שהותקנו. עבור כל עבריין תנועה הפונקציה יוצרת קובץ ששמו מספר הרכב עם סיומת.dat כל שורה בקובץ מכילה: 6 ספרת yymmdd) לדוגמה התאריך של היום מקודד 6) תאריך 4 ספרות hhmm) לדוגמה השעה 9: מקודדת (9 שעה 4 ספרות מס' מצלמה תווים מיקום המצלמה 3 ספרת מהירות שם קובץ תמונה תווים הקבצים ממוינים בסדר כרונולוגי (מיון ראשי לפי תאריך, ומיון משנה לפי שעה) במקרה וארעה שגיאה בפתיחה או סגירה של אחד הקבצים הפונקציה תחזיר, אחרת. לב: שימו בכל הקבצים אין תווי הפרדה בין השדות אין לעבור על קובץ יותר מפעם אחת. אין להעתיק קובץ למבנה נתונים אחר (מערך, רשימה משורשרת, עץ,קובץ אחר...) 34
35 תשובה: typedef struct camera{ FILE *fp; int eof; char place[], time[]; camera; int radar( int number){ camera *arr; FILE *fp; char filename[], *mintime="993", photo[]; int i, index=-, speed, car,; if(!(arr=(camera*)malloc(sizeof(camera)*number)))exit(); for(i=; i<number; i++){ sprintf(filename, "%d.txt", i+); if(!(arr[i].fp=fopen(filename, "r")))return ; fscanf(arr[i].fp, "%[^$]%*c", arr[i].place); arr[i].eof=fscanf(arr[i].fp, "%s", arr[i].time); while(){ for(i=; i<number; i++) if(arr[i].eof==&& strcmp(arr[i].time, mintime)<){ mintime = arr[i].time; index = i; if(index==-) break; arr[index].eof = fscanf(arr[index].fp, "%3d%7d%[^$]%*c", &speed, &car, photo); sprintf(filename, "%d.dat", car); if(!(fp=fopen(filename, "a")))return ; fprintf(fp, "%s%4d%s%3d%s\n", mintime, index, arr[index].place, speed, photo); if(fclose(fp)==eof) return ; arr[index].eof=fscanf(arr[index].fp,"%s", arr[index].time); index=-; mintime="993"; for(i=; i<number; i++) if(fclose(arr[i].fp)==eof) return ; free(arr); return ; 35
36 #define M 8 #define N 8 שאלה (6 6 נקודות) נתונות שתי הפונקציות הבאות: void What( int mat[][m], int i, int j, int c){ int di, dj; if (i < i > N j < j > M- mat[i][j]) return; mat[i][j] = c; for (di = -; di<= ; di++) for (dj = - ; dj<= ; dj++) What(mat, i+di, j+dj, c); int What(int mat[][m]) { int count=, i, j; for (i=; i < N; i++) for (j=; j < M; j++) if (mat[i][j] == ) { count++; What(mat, i, j, count); return count ; סעיף א (6 נקודות) יהי mat המערך הבא : צייר את המערך mat לאחר הקריאה ל- ( What(mat,,3, 36
37 37 (תודוקנ 6) ב ףיעס יהי :אבה ךרעמה mat ךרעמה תא רייצ mat -ל האירקה רחאל What(mat).הריזחמ היצקנופהש ךרעה תאו ףיעס (תודוקנ 4) ג רבסה תויצקנופה תושוע המ הרצקב.What -ו What :ןורתפ א ףיעס What(mat, 3,, ) ב ףיעס ףיעס ג היצקנופה הדוקנהמ "תעבוצ" what לש שוגבש םינכשה םיאתה לכ תא map[i][j] map[i][j] עבצל םיספא םיליכמש.(paintbrush-ב fill-ל המודב).c היצקנופה "תעבוצ" what עבצהמ רחא עבצב שוג לכ -ב fill-ל המודב).ועבצש םישוגה רפסמ ריזחמו.(paintbrush 3 3 4 3 3 4 5 5 5 5 5 5 5 5 5 5