עבור לתוכן

הדפסה של מערך עם מחרוזות בסדר ABC בשפת C

Featured Replies

פורסם

בגלל זה יש לי משתנה שנקרא remember

המשתנה הזאת זוכר את המקום של התו שאחרי הרווח האחרון שנקרא

וככה הוא יכול להבדיל בין מילים

  • תגובות 34
  • צפיות 6.8k
  • נוצר
  • תגובה אחרונה
פורסם

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

פורסם

לא הבנתי אם זאת שאלה או הסבר

בעקרון המצביע יצביע על התא הראשון של המילה שעוד לא הודפסה

כאשר בהתחלה אני משווה אותו ל-0 וככה הוא יודע להתחיל מתחילת המחרוזת

פורסם

חח סוף סוף הצלחתי :)

שמע זה היה קצת מסובך אבל לא בלתי אפשרי

אם בא לך להסתכל על הפיתרון ולנסות להבין אז יופי

אם לא אני הולך לישון כי אני עייף ותכתוב פה תגובה ומחר אני אסביר לך :)

ד"א אני גם משתמש פה בתיקייה ctype

כדי שיהיה אפשר להשאיר את Y (גדולה) במקום ש y קטנה תמצא...

void main()
{
int i, j, q, remember=0;
char temp='\0';
char string[] = "Ym name is reblink kjihgfedcba";
int size=sizeof(string);
for(i=0; i<size; i++) {
if(string[i] == 32 || i==size-2) {
for(q=remember; ; q++) {
if(tolower(string[q]) > tolower(string[q+1]) && string[q+1]!=32 && string[q+1]!=0 && (q+1)!=size) {
temp = string[q];
string[q] = string[q+1];
string[q+1] = temp;
j++;
}
if(q==i) {
q=remember;
if(j==0) break;
j=0;
}
}
remember=i;
}
}
/* printing */
printf("\n");
for(q=0; q<size; q++)
printf("%c", string[q]);
printf("\n");
}

output של התוכנה:

mY aemn is beiklnr abcdefghijk

פורסם

הממ, באמת עכשיו כשחושבים על זה הניסוח של השאלה המקורית קצת לא ברור.

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

בכל מקרה, למי שציין פה רקורסיה - לא הבנתי למה זה טוב כאן. עדיף לולאות.

פורסם

שניצל נראה לי שצדקת בהבנה שלך

ואני שוב טעיתי חחח

הוא כתב:

נניח land ball acab lala

יודפס acab ball lala land

ובגלל שאלה לא באמת מילים אני עשיתי את זה שעשיתי

אלא משום מה (בגלל דיסלקציה) ראיתי את זה כמילה שמסודרת לפי הABC

עריכה:

תראה אחרי מחשבה של "איך אפשר לעשות את זה לעז***?"

אני חושב שהסכמתי עם עצמי שצריך לעשות כמה לולאות אחת בתוך השנייה

הראשונה - עוברת על אברי המערך ומחפש רווחים - כל פעם שמופיע רווח מתחילה בעוד לולאה שתעבור על "האותיות"(איברים) בין הרווח הקודם (או התחלת המערך) עד לרווח החדש שהופיע ( בסוף הלולאה אפשר להוסיף את הקוד הבא:

      if(string[i] == 32) {
remember=i+1;
}

אשר שומר את המקום החדש של תחילת מילה)

הלולאה השניה תעבור על האיברים בין remember (שבתחילת התוכנית =0) לבין i (סה"כ איברים באורך של מילה)

הלולאות האחרות עוברות על כל/חלק מהאיברים עוד פעם במטרה למצוא אם המילה הנוכחית שעכשיו התוכנית עוברת עליה צריכה להיות מודפסת

אם זה אומר שלולאה אחת בודק את האות הראשונה של המילה הנוכחית עם האות הראשונה של המילים האחרות במחרוזת

אם האותיות זהות צריך לעבור לאות הבאה לעשות את האותו הדבר לדוגמא( המילה bell תופיע אחרי המילה ball ולפני המילה bex[לא יודע אם יש מילה כזאת- זה רק בשביל ההסבר])

** המלצה:למחוק מילים שכבר הודפסו

לדוגמא אם המחרוזת היתה:

land ball acab lala

וכבר הדפסתי את acab

אז כל איבר של המילה acab יוחלף עם תו אחר לבחירתך (לדוגמא אני אוהב לעבוד במקרים כאלה עם \0)

וכך תוכל ותדע איך להתעלם מאיברים אלה

ואל תשכח גם מאותיות גדולות וקטנות הערך ASCII של a ו A שונה אז תשתמש ב tolower כדי להגיע תמיד לערך הASCII של אות קטנה

בהצלחה :)

פורסם
  • מחבר

לגבי אותיות קטנות החליטו להקל עלינו ( :bash: ) אפשר להניח שהקלט תקין וכולל רק אותיות קטנות באנגלית.

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

תודה על הכיוון אני אנסה לעשות שוב פעם כמו שהצעת..

פורסם

^ הדיבאגר הוא חבר שלך.

RebliNk17 - אני אוהב את ההתלהבות שלך! מזכיר לי את עצמי.

אגב המצאת את bubble sort, אז תהיה גאה בעצמך! (בלי ציניות). אם אתה רוצה

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

במערכים או כל מבנה נתונים אחר בתנאי שהוא לא גדול מ n\2. אה ובין מילים יש רווח אחד או יותר. תהנה :)

בכל מקרה, למי שציין פה רקורסיה - לא הבנתי למה זה טוב כאן. עדיף לולאות.

למה לא? אתה הרי בתכלס אתה עושה פה selection sort בשני המקרים (פשוט במקרה השני יש לך טוויסט קטן...).

מצא min דרוס, תדפיס. נשמע לי די רקורסיבי...

פורסם

זה לא רקורסיבי, זה איטרטיבי.

כמובן כל אלגוריתם איטרטיבי ניתן להביע ע"י מנגנון רקורסיבי, אבל למה לעשות דבר כזה?

פורסם

חח ויטלי זאת לא התלהבות

יש לי ידע מוקדם בשפות תיכנות (יותר שפות צד שרת) אבל C לא ממש למדתי (ממש קצת בתיכון לפני כמה שנים טובות)

אני עוזר לאחותי בעבודות שיש לה בלימודים , מסביר לה דברים

ואני לא יכול להסביר לה דברים שאני לא יודע אז אני צריך ללמוד, היא מסתמכת עלי שאני אעזור לה

אז זה שאני "מתלהב" זה פשוט אני מנסה להרחיב את הידע שלי כדי שאני אוכל לעזור לה :)

ואין לי שום דבר להתגאות בו אמרו לו שאסור לו להשתמש בכל מיני דברים אז פשוט צריך ליצור את אותם דברים שאסור להשתמש בהם

ולצערי אין לי כוח להצעה שלך לתרגיל אחותי כבר עברה נושא מה שאומר שגם אני ;D

פורסם

אה אוקי... אגב לא התכוונתי "מתלהב" במובן הרע, לא חשוב... :)

זה לא רקורסיבי, זה איטרטיבי.

כמובן כל אלגוריתם איטרטיבי ניתן להביע ע"י מנגנון רקורסיבי, אבל למה לעשות דבר כזה?

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

ב selection sort בשביל למיין n אתה קודם חייב למיין n-1. אם זה לדעתך לא רקורסיבי, למה?

וכן אתה יכול לכתוב איטרציה כ tailing recursion והפוך. זה לא אומר הרבה על האלגורתים...

לדוגמה אתה יכול לכתוב merge sort בעזרת איטרציה,זה הופך אותו לאלגוריתם איטרטיבי?

או אתה יכול לכתוב חיפוש לינארי בעזרת tailing recursion, זה הופך אותו לרקורסיבי?

אני רואה איטרטיבי כ: "עבור כל n תעשה x" ורקורסיבי כש: בשביל לפתור עבור n

אני חייב לפתור את אותה בעיה עבור n-1 (או n קטן יותר...).

פה, אם תשים לב, אין לך איטרציית "עבור כל n" אלא יש לך "כל עוד לא_ממויין".

ומה זה לא נראה נקי יותר בלי ה לופ?



void print_in_order(char* text)
{
char* word = smallest_word(text);
if (word == nil)
return void;


print_word(word);
erase_word(word);


return print_in_order(text);
}

פורסם

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

void print_in_order(char* text)
{
char* word = smallest_word(text);
while (word != null) {
print_word(word);
erase_word(word);
word = smallest_word(text);
}
}

פורסם

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

עליהם ברקורסיה...

לגבי LISP, תלוי באיזה lisp מדובר. ב common lisp לדוגמה אם אני זוכר ננכון יש לך מבנים איטרטיביים.

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

חוצמזה כלולאה זה נראה עדיין נראה לי פחות נקי :P

פורסם

טוב אז אחרי שהיה לי היום קצת זמן לשבת ולחשוב על התרגיל הזה מצאתי פיתרון ללא שימוש במערך עזר

אחת הפונקציות בתוכנית פשוט מחליפה בין מקומות של 2 מילים צמודות במערך כמה פעמים עד שכבר אין צורך

בנוסף הוספתי פונקציה לתיקון הקלט, מה הכוונה?

-- הפונקציה בודקת שאין 2 רווחים (או יותר) אחד אחרי השני, אם יש - מוחקת אחד מהם

-- בודקת שאין ספרות בקלט, אם יש - מוחקת את כולם

-- מחליפה אותיות גדולות עם קטנות

-- מוחקת רווח בסוף/תחילת קלט (רווח מיותר)

בנוסף הפונקציות עם שמות מובנים ורוב המשתנים גם מובנים (לדוגמא: i,j מונים, c כמו check -בדיקה וכו')

#include <stdio.h>
#include <ctype.h>

int move_array_left(char *, int, int, int);
int word_length(char *, int);
int start_compare(char *, int);
int check_and_fix(char *, int);

int main(){
int i, size;
char str[100];
gets(str);
size = 100;
size = check_and_fix(str, size);
start_compare(str, size);
for(i=0; i<size; i++) {
printf("%c", str[i]);
}
printf("\n\n\n");
printf("now I know my ABC's\nnext time won't you sing with me?\n");
return 0;
}

int check_and_fix(char *str, int size) {
int i=0, c=0;
for(i=0; i<size; i++) {
str[i] = tolower(str[i]);
if(i<size-1) {
if(str[i] ==32 && str[i+1] == 32)
c=1;
}
if(i==size-1 && str[i]==32) c=1;
if((str[i] < 'a' || str[i] > 'z') && str[i]!=32) c=1;
if(c==1) {
str[i]=str[i+1];
}
if(c==1 && i==size-1) {
c=0;
size--;
str[size]='\0';
i=-1;
}
}
return size+1;
}


int start_compare(char *strin, int size) {
int i, j, k, is_it_done=1, remember=0;
for(i=0; i<size; i++) {
if(strin[i] == 32) {
for(j=remember, k=1; j<i; j++, k++) {
if(strin[j] > strin[i+k]) {
for(k=i+1; strin[k]!=32 && k<size-1; k++);
is_it_done=move_array_left(strin, remember, k-1, size);
break;
} else if(strin[j] < strin[i+k]) break;
}
remember=i+1;
}
if(is_it_done ==1) {
i=-1;
is_it_done=0;
remember=0;
}

}
}

int move_array_left(char *stri, int from, int to, int size) {
int i, j, check=0, first_word=0;
char temp=NULL;
for(i=from; i<to; i++) {
if(stri[i] == 32 || check>0) {
stri[i] = stri[i+1];
check++;
} else {
first_word++;
}
}
stri[to] = 32;
for(i=0; i<first_word; i++) {
temp = stri[from];
for(j=from; j<to; j++)
stri[j]=stri[j+1];
stri[to] = temp;
}
return 1;
}

התוכנית גם יודעת להבדיל בין ac ab, זאת אומרת ab יופיע לפני ac בסדר היציאה

פורסם

תשתמש ב fgets, לא gets.

ולמעשה כל in place sort יעבוד פה בלי הקצאות זיכרון נוספות. הקטע הטריקי היחיד הוא לספק swap().

ויש גם את העניין עם ה indexים, במקום למיין מערך אתה בעצם ממיין linked list. כלומר O של n, במקום O של 1 על index()

אגב, בעולם האמיתי אתה פשוט (1) אוסף אינדקסים (2) קורא ל qsort ו(3) מדפיס. או אולי אפילו משהו bucket sort,

אם תוכל למצוא דרך לעשות hash טוב למחרוזות בטווח נתון (נראה לי קשה...). לכיוון הזה נסיתי לדחוף אותך.

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

ואם בכל האימונים שלך אתה מתאמן עם יד אחת, איזה מקצוען בדיוק אתה הולך להיות?

זה די מצחיק האמת, כל מאמן כדורסל שהכרתי כל היום שובר ת'ראש איך לגרום לתרגילים שלו להרגיש יותר כמו

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

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

דיונים חדשים