Download presentation
Presentation is loading. Please wait.
1
מחרוזות נכתב ע " י כרמי גרושקו. כל הזכויות שמורות © 2010 הטכניון, מכון טכנולוגי לישראל 1
2
2
3
רעיונית, מחרוזת היא אוסף של תווים. עם זאת, בשפת C לא קיים מבנה יעודי למחרוזות. טכנית, מצביע לתו מגדיר מחרוזת החל מהתו אליו הוא מצביע, ועד לתו הקרוב שערכו '\ 0' ("backslash-zero") מחרוזת יכולה להיות חלק ממערך, או להווצר ע " י malloc. מערך יכול להכיל כמה מחרוזות. מחרוזת יכולה להיות באורך 0 3
4
קבועי מחרוזת, כדוגמת "Hi !" הם ביטויים מטיפוס char*. ערכם הוא כתובת באזור מיוחד בזכרון, לקריאה בלבד. printf( "Hello!" ); printf( 4592 ); … 'H''e''l' '!''\0' … 4592 4
5
כתלות בקומפיילר, שני קבועי - מחרוזות זהים עשויים להצביע לאותו מקום בזכרון : printf( "%d", a ); printf( "%d", b ); printf( "%d", a ); printf( "%d", b ); printf( 1804, a ); printf( 1804, b ); printf( 1804, a ); printf( 1804, b ); … '%''d''\0' … 1804 5
6
הפקודה הבאה מגדירה משתנה המצביע לקבוע מחרוזת : char* str = "Hi !"; ניסיון לשנות את המחרוזת המוצבעת ע " י str עשוי לגרום לקריסת התכנית, כיוון שהמחרוזת נמצאת באזור זכרון לקריאה בלבד : str[0] = 'G'; 6
7
לעומת זאת, הפקודה הבאה מקצה זכרון, ומעתיקה לתוכו את תוכנו של קבוע המחרוזת. ( כולל ה -'\ 0' !) char str2[5] = "Hi !"; שינוי המחרוזת המוצבעת ע " י str2 יצליח, כיוון ש -str2 הוא זכרון רגיל, שאינו לקריאה - בלבד. str2[0] = 'G'; 7
8
הדפסת מחרוזת נעשית ע " י תג הבקרה %s: printf( "%s", str ); קלט נעשה באופן דומה : scanf( "%s", str ); str חייב להצביע למקום שמותר לנו לכתוב אליו מערך שהוגדר מראש, או זכרון מהקצאה דינמית. אורך המחרוזת הנקלטת חייב להיות קטן מגודלו של המערך פחות 1, כדי להשאיר מקום לתו המיוחד '\ 0'. שימו לב שאין &, כיוון ש -scanf צריכה לדעת לאן לכתוב את מה שהיא קולטת, ו -str מצביע למקום זה. char str[15]; scanf( "%s", str ); char str[15]; scanf( "%s", str ); 8
9
כיוון שמחרוזת היא למעשה מצביע, לא ניתן להשוות בין מחרוזות בצורה האינטואיטיבית - char str[15]; scanf( "%s", str ); if( str == "Hi!" ) { /* This will never happen */ } char str[15]; scanf( "%s", str ); if( str == "Hi!" ) { /* This will never happen */ } char str[15]; scanf( "%s", str ); if( 1408 == 1544 ) { /* This will never happen */ } char str[15]; scanf( "%s", str ); if( 1408 == 1544 ) { /* This will never happen */ } 9
10
בדומה למערך של int, ניתן להגדיר מערך של char*. מערך כזה נקרא " מערך של מחרוזות ", כיוון שכל איבר במערך מגדיר מחרוזת. תמונת זכרון : char* a[4] = {"Hi", NULL, "%d", NULL}; printf( "%s", a[0] ); char* a[4] = {"Hi", NULL, "%d", NULL}; printf( "%s", a[0] ); … 'H''i''\0' … 1500 NULL1804NULL … '%''d''\0' … 1804 10
11
11
12
כתבו את הפונקציה הבאה : strlen - בהנתן מחרוזת (=char*), מחזירה את אורכה unsigned strlen( char* s ) { unsigned res = 0; while( s[res] ) res++; return res; } unsigned strlen( char* s ) { unsigned res = 0; while( s[res] ) res++; return res; } = char s[] 12
13
char str[35] = "Hello "; strcat( str, "world !" ) printf( "%s", str ); char str[35] = "Hello "; strcat( str, "world !" ) printf( "%s", str ); כתבו את הפונקציה הבאה : strcat המקבלת שתי מחרוזות str1 ו -str2, ומדביקה את השניה לסוף הראשונה. על הפונקציה להחזיר מצביע למחרוזת הראשונה, על מנת שניתן יהיה לשרשר קריאות. הפונקציה תניח שב -str1 יש מספיק מקום. char str[35] = "Hello "; strcat( strcat( str, "world !" ), " Bla Bla !" ); printf( "%s", str ); /* Prints: Hello world! Bla Bla ! */ char str[35] = "Hello "; strcat( strcat( str, "world !" ), " Bla Bla !" ); printf( "%s", str ); /* Prints: Hello world! Bla Bla ! */ 13
14
תמונת זכרון : char str[35] = "Hello "; strcat( str, "world" ); printf( "%s", str ); /* Prints: Hello world */ char str[35] = "Hello "; strcat( str, "world" ); printf( "%s", str ); /* Prints: Hello world */ 'H''e''l' 'o'' '' ''\0' … str 'H''e''l' 'o'' '' ''w''o''r''l''d''\0' … str 14
15
נמצא את המקום שבו a מסתיימת, ונעתיק לשם את b. char* strcat( char* str1, char* str2 ) { char* t = str1; while( *str1 ) str1++; while( *str2 ) *str1++ = *str2++; return t; } char* strcat( char* str1, char* str2 ) { char* t = str1; while( *str1 ) str1++; while( *str2 ) *str1++ = *str2++; return t; } 15
16
הסדר שבו מילים מסודרות במילון. נתונות שתי מחרוזות שונות a ו -b. יהא i האינדקס הראשון בו a[i] != b[i]. אם a[i]<b[i], נאמר ש -a קטנה מ -b, אחרת גדולה. שימו לב שההגדרה תלויה בטבלת התוים (ASCII,...) שימו לב שבסוף מחרוזת תמיד יש תו שערכו 0. לדוגמא, "a" < "b", "bla" < "c". 16
17
כתבו פונקציה המקבלת שתי מחרוזות str1 ו - str2, ומחזירה אפס אם שתיהן זהות >0 אם str1 > str2 <0 אם str2 < str1 אפשר להסתכל על הפקודה strcmp( str1, str2 ) כעל השאלה : " למה שווה str1-str2 ?" 17
18
נתקדם עם שתי המחרוזות במקביל, עד שאחת מהן נגמרת. אם גם השניה נגמרה, נחזיר '\ 0' - '\0' = 0 אחרת, נחזיר את ההפרש בין התוים int strcmp2( char* str1, char* str2 ) { while( *str1 && *str2 && *str1 == *str2) { str1++; str2++; } return *str1 - *str2; } int strcmp2( char* str1, char* str2 ) { while( *str1 && *str2 && *str1 == *str2) { str1++; str2++; } return *str1 - *str2; } 18
19
כתבו פונקציה המקבלת מערך a ואורכו n, ומחזירה את מספר המחרוזות המוכלות בו. שימו לב מה זה מדגיש - מערך ומחרוזת אינם אותו הדבר. הדבר שקול לספירת תוי ה -'\ 0 ' שבמערך. unsigned count_strings( char s[], int n ) { unsigned res = 0; int i; for( i=0; i<n; i++ ) res += (s[i] == '\0'); return res; } unsigned count_strings( char s[], int n ) { unsigned res = 0; int i; for( i=0; i<n; i++ ) res += (s[i] == '\0'); return res; } כזכור, ערכו של ביטוי זה הוא 0 או 1 19
20
כתבו פונקציה המקבלת מחרוזת המייצגת מספר שלם, ומחזירה את המספר הזה. int n = str2int("-1234"); printf( "%d", n ); /* Prints: -1234 */ int n = str2int("-1234"); printf( "%d", n ); /* Prints: -1234 */ 20
21
כתבו פונקציה המקבלת מחרוזת המייצגת מספר שלם, ומחזירה את המספר הזה. int str2int( char* str ) { int res = 0; int negative = (*str == '-'); if( *str == '-' ) str++; while( *str ) { res = 10*res + (*str-'0'); str++; } return negative ? -res : res; } int str2int( char* str ) { int res = 0; int negative = (*str == '-'); if( *str == '-' ) str++; while( *str ) { res = 10*res + (*str-'0'); str++; } return negative ? -res : res; } 21
22
נתונות שלוש מחרוזות s1, s2, s3 המורכבות מאותיות אנגליות קטנות (a-z) בלבד. כתבו פונקציה המדפיסה רשימה של כל האותיות המופיעות גם ב -s1 וגם ב -s2, אך לא ב -s3. הדפיסו כל אות כזו פעם אחת בלבד, בסדר כלשהו. דוגמא : str1 = "introductionto" str2 = "computer" str3 = "science" פלט : trou פתרו ללא לולאות מקוננות (= מעבר יחיד על המחרוזות ) 22
23
" כתבו פונקציה המדפיסה רשימה של כל האותיות המופיעות גם ב -s1 וגם ב -s2, אך לא ב -s3." איך הייתם פותרים את הבעיה ללא האילוץ האחרון על הלולאות המקוננות ? הטריק ( שחוזר על עצמו בשאלות רבות ) הוא שניתן להגדיר מערך עזר בגודל 26 ( מספר האותיות האנגליות ). "cable" abcdefghijklmnopqrs… 11111… 23
24
void print_letters( char* s1, char* s2, char* s3 ) { int i, letters[26] = {0}; for( ; *s1; s1++ ) letters[*s1 - 'a'] = 1; for( ; *s2; s2++ ) if( letters[*s2 - 'a'] ) letters[*s2 - 'a'] = 2; for( ; *s3; s3++ ) letters[*s3 - 'a'] = 0; for( i=0; i<26; i++ ) if( letters[i] == 2 ) printf( "%c", i+'a' ); } void print_letters( char* s1, char* s2, char* s3 ) { int i, letters[26] = {0}; for( ; *s1; s1++ ) letters[*s1 - 'a'] = 1; for( ; *s2; s2++ ) if( letters[*s2 - 'a'] ) letters[*s2 - 'a'] = 2; for( ; *s3; s3++ ) letters[*s3 - 'a'] = 0; for( i=0; i<26; i++ ) if( letters[i] == 2 ) printf( "%c", i+'a' ); } 24
25
סדרת אבו - נאצ ' י היא כמו סדרת פיבונאצ ' י, רק ששני המספרים הראשונים אינם בהכרח 1. למרות זאת, הם חייבים להיות חד - ספרתיים. לדוגמא : 1, 9, 10, 19, 29, 48, … כתבו פונקציה המקבלת מחרוזת של ספרות, ומכריעה אם היא מהווה סדרת אבו - נאצ ' י. למשל, עבור " 1910192948 " - אמת עבור " 15712195069 " - שקר ניתן להניח שאיברי הסדרה נכנסים ב -unsigned. 25
26
" למשל, עבור " 1910192948 " - אמת עבור " 15712195069 " - שקר " נקרא את שני האיברים הראשונים ( אנחנו יודעים שהם ספרה בודדת ) בלולאה, נחשב את המספר הבא. אם המספר הזה לא נמצא במקום הנכון במחרוזת, נחזיר 0. אם הגענו לסוף המחרוזת בשלום, נחזיר 1. 26
27
int is_abunachi( char* str ) { unsigned prev = (str[0]-'0'), curr = (str[1]-'0'), next, next_digits; str += 2; while(*str) { next = prev+curr; prev = curr; curr = next; next_digits = count_digits(next); if( sub_str2int( str, next_digits ) == next ) str += next_digits; else return 0; } return 1; } int is_abunachi( char* str ) { unsigned prev = (str[0]-'0'), curr = (str[1]-'0'), next, next_digits; str += 2; while(*str) { next = prev+curr; prev = curr; curr = next; next_digits = count_digits(next); if( sub_str2int( str, next_digits ) == next ) str += next_digits; else return 0; } return 1; } כמה ספרות יש ב -next ? מה המספר הרשום בתת - המחרוזת המתחילה ב -str באורך next_digits ? 27
28
נגדיר משקל של אות בא " ב האנגלי כמספרה הסידורי של האות בא " ב (a = 1, b = 2,...). נגדיר משקל של מילה כסכום המשקלות של אותיותיה. "abc" = 1+2+3 = 6 "abba" = 1+2+2+1 = 6 "babble" = 1+2+2+2+5+12 = 24 28
29
כתבו פונקציה calc_weight המקבלת מילה כמחרוזת ומחזירה את משקלה. הניחו שהמלה לא ריקה, ומכילה אותיות אנגליות קטנות בלבד. unsigned calc_weight( char* word ) { unsigned w = 0; for( ; *word; word++ ) w += (*word - 'a') + 1; return w; } unsigned calc_weight( char* word ) { unsigned w = 0; for( ; *word; word++ ) w += (*word - 'a') + 1; return w; } 29
30
כתבו פונקציה המקבלת מערך של מחרוזות ואת אורכו, ומחזירה מצביע למילה שמשקלה מירבי. ( אותן הנחות ) char* max_weight( char* words[], int n ) { unsigned w, max_w = 0; char* max_word = NULL; int i; for( i=0; i<n; i++ ) { w = calc_weight( words[i] ); if( w > max_w ) { max_w = w; max_word = words[i]; } return max_word; } char* max_weight( char* words[], int n ) { unsigned w, max_w = 0; char* max_word = NULL; int i; for( i=0; i<n; i++ ) { w = calc_weight( words[i] ); if( w > max_w ) { max_w = w; max_word = words[i]; } return max_word; } 30
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.