1 / 17

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

מכללת אורט כפר-סבא. תכנות מערכות בשפת C. מחרוזות. 02.11.14. אורי וולטמן. uri.weltmann@gmail.com. חידה לחימום. נתונות שתי ערימות של קוביות, כשבכל ערימה מספר הקוביות ההתחלתי הוא אקראי.

Download Presentation

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

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. מכללת אורט כפר-סבא תכנות מערכות בשפת C מחרוזות 02.11.14 אורי וולטמן uri.weltmann@gmail.com

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

  3. הפונקציה התקנית strchr, המוגדרת ב-string.h, מאפשרת לחפש תו מסוים בתוך מחרוזת. כותרת הפונקציה היא: char *strchr (const char *s, const char c) הפונקציה מחזירה מצביע למופע הראשון של התו c במחרוזת s, או מחזירה NULL אם התו לא מופיע במחרוזת. מה יהיה הפלט של קטע הקוד הבא? charstr[] = “This is a sample string"; char*ptr; printf(“Looking for the 's' character\n”); ptr= strchr(str,’s’); while(ptr != NULL) { printf)"found at %d\n",ptr-str); ptr = strchr(ptr+1,’s’); } חיפוש תו במחרוזת

  4. נממש את הפונקציה strchr: char *strchr (const char *s, const char c) { while (*s != ‘\0’ && *s != c) s++; return ((*s == c) ? s : NULL); } סטודנט א' וסטודנט ב' מציעים לעשות שינוי בלולאת ה-while שמופיעה במימוש הנ"ל. ההצעה של סטודנט א': while (*s++ != ‘\0’ && *s != c) ; ההצעה של סטודנט ב': while (*s != ‘\0’ && *s++ != c) ; האם צריך המרצה לתת ציון שלילי לשני הסטודנטים? או רק לאחד מהם? או לאף אחד מהם? חיפוש תו במחרוזת

  5. הפונקציה התקנית strstr, המוגדרת ב-string.h, מאפשרת לחפש תת-מחרוזת בתוך מחרוזת מסוימת. כותרת הפונקציה היא: char *strstr (const char *haystack, const char *needle) הפונקציה מחזירה מצביע למופע הראשון של needle ב-haystack, או מחזירה NULL אם needle אינה תת-מחרוזת של haystack. אם needle היא מחרוזת ריקה, הפונקציה מחזירה מצביע לתחילת haystack. מה יהיה הפלט של קטע התכנית הבא? chars1[] = “This is a sample string"; puts(strstr(s1,”is”)); איזה שינוי יש לערוך בקטע התכנית, על מנת שהפלט יהיה "a sample string"? האם יש יותר מתשובה אחת לשאלה הקודמת? חיפוש תת-מחרוזת

  6. לפעמים היינו רוצים להשתמש ב-strcpy(to,from), אבל להעתיק רק מספר מסוים של תווים מ-from, ולא את from כולו. לצורך כך קיימת ב-string.h פונקציה תקנית בשם strncpy, המתנהגת כמו strcpy, למעט זה שהיא מקבלת פרמטר שלישי n, הקובע את מספר התווים יועתקו. כותרת הפונקציה היא: char *strncpy (char *to, const char *from, unsigned int n) דוגמא לשימוש בפונקציה: char str[] ="This is a simple string"; char *pch = strstr(str,"simple"); strncpy(pch,"sample",6); puts(str); אם from קצרה מ-n בתים, אז יועתקו ‘\0’-ים (על מנת להשלים ל-n תווים). במידה ו-to ו-from נמצאים באזורים חופפים (ולו חלקית) בזיכרון, אז התנהגות הפונקציה אינה מוגדרת. העתקת מחרוזות

  7. הכרנו קודם (ואף מימשנו) את הפונקציה strcmp המשווה בין שתי מחרוזות, שכותרתה: int strcmp (const char *s1, const char *s2) הפונקציה מקבלת שתי מחרוזות, משווה ביניהן, ומחזירה 0 אם שתי המחרוזות שוות, מס' שלילי אם s1 < s2, ומס' חיובי אם s1 > s2. השוואת מחרוזות נעשית לפי סדר מילוני(lexicographic order) : משווים בין האות הראשונה של שתי המחרוזות. אם האות הראשונה של s1 קודמת באלפבית לאות הראשונה של s2, אזי s1 < s2. ואם להיפך – אז s1 > s2 . אם לשתי המחרוזות אותה האות הראשונה, אז משווים בין האות השנייה, באופן דומה. לאחר מכן, אם עדיין מדובר באותיות שוות, ממשיכים באותו אופן לאות השלישית, וכו'. אם אחת המחרוזות נגמרה, בשעה שבמחרוזות השנייה עוד יש אותיות – אז המחרוזות השנייה גדולה מהראשונה. אם שתי המחרוזות נגמרו באותו זמן, מבלי שהתהליך נעצר קודם לכן, אזי המחרוזות שוות. השוואת מחרוזות

  8. מה תחזיר הפונקציה strcmp עבור הזימונים הבאים: strcmp(“hello”,”world”) < 0 strcmp(“hello”,”hello”) 0 strcmp(“hello”,”Hello”) > 0 השוואת מחרוזות • הסיבה שעבור הזימון האחרון לא החזירה הפונקציה strcmp את הערך 0, היא שהתו 'H' והתו 'h' הם שני תווים שונים לגמרי מבחינתה (הם ממוקמים במקומות שונים בטבלת ASCII). • אם נרצה שהפונקציה strcmp תחזיר 0 עבור זימון זה, כלומר – שהיא לא תהיה רגישה לגודל אות (case insensitive), נשתמשו במקומה בפונקציה stricmp.

  9. מוגדרת הפונקציה: int stricmp (const char *s1, const char *s2) הפונקציה מתנהגת ממש כמו strcmp, כלומר: היא מקבלת שתי מחרוזות, משווה ביניהן, ומחזירה 0 אם שתי המחרוזות שוות, מס' שלילי אם s1 < s2, ומס' חיובי אם s1 > s2. ההבדל היחיד הוא שהפונקציה אינה מבדילה בין אותיות קטנות ואותיות גדולות ('A' מבחינתה זהה לגמרי ל-'a', 'B' זהה ל-'b', וכו'). איך נממש את הפונקציה? נקצה זיכרון (ע"י malloc שב-stdlib.h) לשתי מחרוזות זמניות t1 ו-t2 נעתיק את s1 ל-t1, ואת s2 ל-t2, אבל נהפוך כל אות לאות קטנה על-ידי שימוש בפונקציה הסטנדרטית tolower(), המוגדרת ב-ctype.h. כעת אנחנו בטוחים ש-t1 ו-t2 מכילות רק אותיות קטנות. נחזיר את הערך של strcmp(t1,t2). השוואת מחרוזות

  10. int stricmp (const char *s1, const char *s2) { char *t1,*t2; t1 = malloc(strlen(s1) + 1); while (*s1) *t1++ = tolower(*s1++); *t1 = '\0'; t2 = malloc(strlen(s2) + 1); while (*s2) *t2++ = tolower(*s2++); *t2 = '\0'; return strcmp(t1,t2); } השוואת מחרוזות • מדוע מופיע '1+' ב-malloc? • מדוע לא מכפילים את הביטוי שמופיע בתוך ה-malloc בביטוי sizeof(char)? • איזו שגיאה יש בפונקציה?

  11. int stricmp (const char *s1, const char *s2) { char *t1,*t2; int returnvalue; t1 = malloc(strlen(s1) + 1); while (*s1) *t1++ = tolower(*s1++); *t1 = '\0'; t2 = malloc(strlen(s2) + 1); while (*s2) *t2++ = tolower(*s2++); *t2 = '\0'; return strcmp(t1,t2); free(t1); free(t2); return returnvalue; } השוואת מחרוזות • נשים לב שאנחנו מזמנים כאן את malloc, אבל מבלי לבדוק האם הקצאת הזיכרון הצליחה (אולי הפונקציה החזירה NULL כי אין זיכרון פנוי?). • יתרה מכך: המצביעים t1 ו-t2 • מצביעים על סוף המחרוזת, ולא על • תחילתה. איך ניתן לפתור • את הבעיה? returnvalue = strcmp(t1,t2);

  12. פונקציה נוספת המשווה שתי מחרוזות לפי סדר לקסיקוגרפי היא הפונקציה strncmp, שכותרתה: int strncmp (const char *s1, const char *s2, unsigned n) הפונקציה מקבלת שתי מחרוזות, ומשווה רק בין n התווים הראשונים של כל מחרוזת, ומחזירה 0 אם שתי המחרוזות שוות, מס' שלילי אם s1 < s2, ומס' חיובי אם s1 > s2. אם במחרוזת מסוימת יש פחות מ-n תווים, אז מתייחסים רק לתווים שעד ל-null terminator. אם בשתי המחרוזות יש פחות מ-n תווים, אין הבדל בין strncmp ל-strcmp. השוואת מחרוזות strncmp(“helloa”,”hellob”,5) 0 strncmp(“helloa”,”hellob”,6) < 0 strncmp(“helloa”,”hellob”,9) < 0

  13. int strncmp (const char *s1, const char *s2, unsigned int n) { char *t1, *t2; int returnvalue; t1 = malloc(strlen(s1) + 1); strncpy(t1,s1,n); t1[n] = '\0'; t2 = malloc(strlen(s2) + 1); strncpy(t2,s2,n); t2[n] = '\0'; returnvalue = strcmp(t1,t2); free(t1); free(t2); return returnvalue; } השוואת מחרוזות • הפונקציה לא תעבוד כשורה... מה חסר? • גם כאן צריך היה לוודא שהקצאת הזיכרון הצליחה...

  14. ב-string.h מוגדרת הפונקציה התקנית: char *strpbrk (const char *str1, const char *str2) הפונקציה מחזירה מצביע למופע הראשון ב-str1 של תו מתוך str2. אם הפונקציה סרקה את str1, והגיעה עד ל-null terminator, מבלי שמצאה אף אחד מהתווים שבתוך str2, אז היא תחזיר NULL. חיפוש תווים במחרוזת

  15. #include <stdio.h> #include <string.h> int main() { char str[] = "This is a sample string"; char key[] = "aeiou"; char *pch; printf ("Vowels in '%s': ",str); pch = strpbrk (str, key); while (pch != NULL) { printf ("%c " , *pch); pch = strpbrk (pch+1,key); } printf ("\n"); return 0; } חיפוש תווים במחרוזת • מה יהיה הפלט?

  16. פונקציה המוגדרת גם היא ב-string.h, היא: unsigned int strspn (const char *str1, const char *str2) הפונקציה מחזירה את אורך הרישא (prefix) המקסימלית של str1, המורכבת כולה מתווים שנמצאים ב-str2. #include <stdio.h> #include <string.h> int main() { char str[] = “125th”, cset[] = "1234567890"; int i = strspn (str,cset); printf ("The length of the number is %d.\n",i); return 0; } אם התו הראשון של str1 אינו שייך ל-str2, אז הפונקציה תחזיר 0. מציאת רישא מותנית

  17. פונקציה הפוכה ל-strspn, המוגדרת גם היא ב-string.h, היא: unsigned int strcspn (const char *str1, const char *str2) הפונקציה מחזירה את אורך הרישא (prefix) המקסימלית של str1, המורכבת כולה מתווים שאינם נמצאים ב-str2. #include <stdio.h> #include <string.h> int main() { char str[] = “fcba73”, cset[] = "1234567890"; int i = strcspn (str,cset); printf ("The first number is at position %d.\n",i+1); return 0; } הפונקציה סורקת גם את ה-‘\0’, ולכן היא תחזיר את האורך של str1 אם אף אחד מהתווים של str2 לא נמצאים ב-str1. מציאת רישא מותנית

More Related