פורסם 2011 בינואר 2114 שנים אני מנסה לחשוב על קוד שיבצע את הפעולה הראשונה של הקדם מעבד (הורדת הערות בקובץ גם מסוג C וגם מסוג C++) ושמירתם לקובץ אחר.למשל, אם יש לי קובץ בשם name.c , לאחר הורדת ההערות, יווצר לי קובץ נוסף בשם name.c1 שהוא למעשה אותו הקובץ כמו name.c רק ללא ההערות.דבר נוסף... קליטת שם הקובץ תהיה בצורה הבאה:>./ <my_prog_name> <name.c>חשבתי על האלגוריתם הבא: 1. יצירת מחרוזת בשם 'c1.' לשימוש בהמשך.2. קליטת שם הקובץ כולו דרך argv[1] למערך דינמי כי אינני יודע מה אורכו של שם הקובץ.3. אותו מערך דינמי יריץ לולאה על עצמו עד להגעה לסימן '.' ויחליף את '.' ב- '0\'.4. שרשור המחרוזת מסעיף 1. למערך מסעיף 3. והצבת '0\' לאחר השרשור.5. פתיחת הקובץ המקורי לקריאה מקובץ בלבד ע"י גישה ל- argv[1] ושימוש ב- fopen.6. העתקת תוכן הקובץ המקורי לקובץ עם השם אותו ניתן ע"י המערך עם השם החדש שלנו בזמן פתיחה לכתיבה של הקובץ החדש שיווצר.7. נוצר סוף סוף העתק לקובץ ההמקורי רק עם השם החדש. עכשיו אפשר לגשת אליו ולהעיף ממנו את ההערות.אני מרגיש שאולי עם פונקציות מסויימות אחרות הייתי יכול לייעל ולקצר משמעותית את האלגוריתם, אבל לא עולה לי כ"כ אלגוריתם אחר.אשמח לעזרה.תודה !!
פורסם 2011 בינואר 2114 שנים פשוט תסרוק את הקובץ מההתחלה לסוף כאשר אתה רואה התחלה של הערה (או // או /* ) תעבור למצב התעלמות עד לסוף הערהבמקרה של // סוף הערה הוא מעבר לשורה חדשה במקרה השני סוף הערה יגיע כאשר תראה */ , במצב התעלמות אל תכתוב כלום לקובץהפלט אחרת תכתוב מה שסרקת כרגע.
פורסם 2011 בינואר 2114 שנים 1) שים לב שאתה צריך להתעלם מ"הערות" שנמצאות במחרוזות. לדוגמא, ה"הערה" לא צריכה להמחק במצב כזה:printf("/*this is not a comment*/");2) אין סיבה להעתיק את כל הקובץ. תעבור תו תו, ותחליט האם אתה רוצה להעתיק אותו או לא. זה הרבה יותר פשוט.
פורסם 2011 בינואר 2214 שנים מחבר סבבה, כך אעשה. כבר כתבתי את התוכנית הזו...ולגבי יצירת קובץ חדש ?נניח ששם הקובץ עם סיומת C הוא בגודל לא ידוע, איך אני אמור לטפל בזה ? להגדיר מצביע על מערך בגודל דינמי ולטפל באופן שתיארתי ממקודם ?תודה !
פורסם 2011 בינואר 2214 שנים שים לב שאתה צריך להחליט האם הערות מקוננות נתמכות או לא. ז"א במצב הבא:1: /*2: bla bla bla3: 4: /*5: more stuff6: */7: 8: blah blah blah9: 10: */האם להתעלם משורות 7-10 או לא.
פורסם 2011 בינואר 2214 שנים נניח ששם הקובץ עם סיומת C הוא בגודל לא ידוע, איך אני אמור לטפל בזה ? להגדיר מצביע על מערך בגודל דינמי ולטפל באופן שתיארתי ממקודם ?קודם כל, יש פונקציות שיכולות למצוא לך את גודל הקובץ (לדוגמה fseek+ftell). חוץ מזה, אתה לא צריך לקרוא את כל הקובץ במכה אחת. אתה יכול לקרוא אותו תו אחר תו, או בבלוקים בגודל קבוע.
פורסם 2011 בינואר 2214 שנים מחבר הפונק' האלה מטפלות בתוכן הקובץ. אני מדבר על שם הקובץ...מבחינת גודל דינמי לקובץ, זה לא מעניין אותי כי אני מצביע עליו והקובץ לא יגדל אלא יקטן. אלא אם כן הורדת הערות מגדילה את הקובץ כפי ששמעתי שכבר קרה בעבר תחת Windows אבל לא קרה בלינוקס.בכל אופן... אני מחפש את הדרך הקלילה ביותר לקריאת שם הקובץ (בכל גודל שיהיה) , ולאחר מכן ליצור קובץ חדש עם אותו השם רק שבמקום name.c יופיע name.c1 עבור כל שם קובץ תקני שהוא, רק פשוט ללא ההערות.אם למשל הייתי מטפל במקרה פרטי כמו למשל (הקירוב הטוב ביותר למקרה זה) שאני קורא את שם הקובץ דרך argv[1] (שככה אני אמור לקרוא אותו) אבל כותב אותו לקובץ שאני מחליט מה שמו, הייתי מצביע עם מצביע אחד על כל קובץ, פותח את שניהם, מעתיק רק את המידע הרלוונטי וסוגר את שניהם. ואת זה כבר כתבתי וזה מוכן.אבל הבעיה שלי היא שאני צריך שהקובץ החדש יהיה עם הספרה 1 בסוף, זה הכל....איזה אלגוריתם יהיה הכי נכון כאן ?
פורסם 2011 בינואר 2214 שנים לא הבנתי מה הבעיה. בדוק את אורך שם הקובץ באמצעות ([strlen(argv[1 ואז צור מחרוזת חדשה באורך המתאים.
פורסם 2011 בינואר 2214 שנים מחבר סבבה אין בעיה, זה אומר שאני צריך להגדיר מערך דינמי, כי גודלו הוא נתון שמתברר לאחר הגדרת המשתנים הגלובליים, נכון ?ועוד משהו... איך הכי טוב ל"הדביק" לשם הקובץ את הספרה 1 בסוף ? (name.c1 instead of name.c כיצירת קובץ חדש כמובן)ועוד משהו.. האם מותר לי להגדיר:#typedef strlen(argv[1]) FILE_LENGTH ?תודה !
פורסם 2011 בינואר 2214 שנים סבבה אין בעיה, זה אומר שאני צריך להגדיר מערך דינמי, כי גודלו הוא נתון שמתברר לאחר הגדרת המשתנים הגלובליים, נכון ?מערך שגודלו לא קבוע וידוע בזמן הקומפילציה חייב להיות דינמי (כלומר מוקצה באמצעות malloc).ועוד משהו... איך הכי טוב ל"הדביק" לשם הקובץ את הספרה 1 בסוף ? (name.c1 instead of name.c כיצירת קובץ חדש כמובן)strcpy ו-strcat.#typedef strlen(argv[1]) FILE_LENGTH ?אני מניח שהתכוונת ל-define ולא ל-typedef. אבל למה לך לעשות דבר כזה לעזאזל? פשוט תגדיר משתנה ותשים בו את הערך הזה.
פורסם 2011 בינואר 2314 שנים מחבר כתבתי את הקוד הבא:#include <stdio.h>#include <ctype.h>#include <stdlib.h>#include <string.h>enum status {OUT , IN_STRING , LEFT_SLASH , IN_COMMENT , RIGHT_STAR , IN_CPP_COM};int main(int argc , char *argv[]){ FILE *fd , *new_fd; /* fd -> *.c ; new_fd -> *.c1 */ int ch; int state = OUT; int num_of_file_chars = strlen(argv[1]); /* number of chars in name.c */ char *new_file_name; new_file_name=(char *) malloc ((num_of_file_chars+1)*sizeof(char)); /*+1 for .c1*/ new_file_name[num_of_file_chars+1] = 1; if( !(fd = fopen (argv[1],"r") ) ) { fprintf(stderr,"cannot open file !\n"); exit(0); } if( !(new_fd = fopen (new_file_name,"w+") ) ) { fprintf(stderr,"cannot open file !\n"); exit(0); } while ( (ch=fgetc(fd)) != (feof(fd)) ) switch (state) { case OUT: if (ch=='/') state = LEFT_SLASH; else { fputc(ch,new_fd); if (ch=='\"') state = IN_STRING; } break; /*OUT*/ case LEFT_SLASH: if(ch=='*') state = IN_COMMENT; else if (ch=='/') state = IN_CPP_COM; else { fputc('/',new_fd); fputc(ch,new_fd); state = OUT; } break; /*LEFT_SLASH*/ case IN_COMMENT: if(ch=='*') state = RIGHT_STAR; break; /*IN_COMMENT*/ case IN_CPP_COM: if(ch=='\n') { state = OUT; fputc('\n',new_fd); } break; /*IN_CPP_COM*/ case RIGHT_STAR: if(ch=='/') state = OUT; else if (ch!= '*') state = IN_COMMENT; break; /*RIGHT_STAR*/ case IN_STRING: if(ch=='\"') state = OUT; fputc(ch,new_fd); break; /*IN_STRING*/ } /*switch*/ fclose(fd); fclose(new_fd); return 0; /*dummy*/} /*main()*/אין הערות ואין כלום, אבל התוכנה רושמת cannot open file כלומר היא לא מצליחה לפתוח את הקובץ (אני הכנסתי בקוד ההערה במקרה כישלון).לא מצליח (כבר שעות) לעלות על השגיאה...
פורסם 2011 בינואר 2314 שנים איפה השלב שבו אתה מעתיק את המחרוזת שמכילה את שם הקובץ הישן לתוך המחרוזת שמכילה את שם הקובץ החדש?
פורסם 2011 בינואר 2314 שנים מחבר שיפצתי את ההתחלה כדי שיהיה יותר קריא ומובן קצת:#include <stdio.h>#include <ctype.h>#include <stdlib.h>#include <string.h>enum status {OUT , IN_STRING , LEFT_SLASH , IN_COMMENT , RIGHT_STAR , IN_CPP_COM};int main(int argc , char *argv[]){ FILE *fd , *new_fd; /* fd -> *.c ; new_fd -> *.c1 */ int ch; int state = OUT; int new_file_string_len = strlen(argv[1])+1; /*num of chars in name.c +1 for name.c1*/ char *new_file_name; new_file_name=(char *) malloc ((new_file_string)*sizeof(char)); new_file_name[new_file_string_len] = 1; if( !(fd = fopen (argv[1],"r") ) ) { fprintf(stderr,"cannot open file !\n"); exit(0); } if( !(new_fd = fopen (new_file_name,"w+") ) ) { fprintf(stderr,"cannot open file !\n"); exit(0); } while ( (ch=fgetc(fd)) != (feof(fd)) ) switch (state) { case OUT: if (ch=='/') state = LEFT_SLASH; else { fputc(ch,new_fd); if (ch=='\"') state = IN_STRING; } break; /*OUT*/ case LEFT_SLASH: if(ch=='*') state = IN_COMMENT; else if (ch=='/') state = IN_CPP_COM; else { fputc('/',new_fd); fputc(ch,new_fd); state = OUT; } break; /*LEFT_SLASH*/ case IN_COMMENT: if(ch=='*') state = RIGHT_STAR; break; /*IN_COMMENT*/ case IN_CPP_COM: if(ch=='\n') { state = OUT; fputc('\n',new_fd); } break; /*IN_CPP_COM*/ case RIGHT_STAR: if(ch=='/') state = OUT; else if (ch!= '*') state = IN_COMMENT; break; /*RIGHT_STAR*/ case IN_STRING: if(ch=='\"') state = OUT; fputc(ch,new_fd); break; /*IN_STRING*/ } /*switch*/ fclose(fd); fclose(new_fd); return 0; /*dummy*/} /*main()*/פעלתי בצורה אחרת:יצרתי מערך חדש בגודל שם הקובץ הישן +1 (מערך דינמי כמובן), והדבקתי לאיבר האחרון את הספרה 1.האם פעלתי בצורה לא נכונה ?
פורסם 2011 בינואר 2414 שנים אוקי, אז יצרת מערך בהתאם לגודל המחרוזת הישנה. אבל מה התוכן שלו? איפה אתה שם בו תוכן כלשהו?חוץ מזה, עוד שתי תקלות בייצור המערך:א. אתה צריך לשמור מקום נוסף ל-'0\' בסופו.ב. התו האחרון צריך להיות '1', לא 1. אלה שני דברים שונים לחלוטין.
פורסם 2011 בינואר 2414 שנים מחבר תיקנתי את התוכנית מבחינת א. , ב. , שרשמת לי (היתה לי התחושה אבל לא הייתי סגור על זה...).אבל עדיין יש משהו שמציק לי..כרגע התוכנית היא כזאת:#include <stdio.h>#include <ctype.h>#include <stdlib.h>#include <string.h>enum status {OUT , IN_STRING , LEFT_SLASH , IN_COMMENT , RIGHT_STAR , IN_CPP_COM};int main(int argc , char *argv[]){ FILE *fd , *new_fd; /* fd -> *.c ; new_fd -> *.c1 */ int ch; int state = OUT; int new_file_string_len = strlen(argv[1])+2; /*num of chars in name.c +1 for name.c1*/ char *new_file_name; new_file_name=(char *) malloc ((new_file_string)*sizeof(char)); new_file_name[new_file_string_len-1] = '1'; new_file_name[new_file_string_len] = '\0'; if( !(fd = fopen (argv[1],"r") ) ) { fprintf(stderr,"cannot open file !\n"); exit(0); } if( !(new_fd = fopen (new_file_name,"w+") ) ) { fprintf(stderr,"cannot open file !\n"); exit(0); } while ( (ch=fgetc(fd)) != (feof(fd)) ) switch (state) { case OUT: if (ch=='/') state = LEFT_SLASH; else { fputc(ch,new_fd); if (ch=='\"') state = IN_STRING; } break; /*OUT*/ case LEFT_SLASH: if(ch=='*') state = IN_COMMENT; else if (ch=='/') state = IN_CPP_COM; else { fputc('/',new_fd); fputc(ch,new_fd); state = OUT; } break; /*LEFT_SLASH*/ case IN_COMMENT: if(ch=='*') state = RIGHT_STAR; break; /*IN_COMMENT*/ case IN_CPP_COM: if(ch=='\n') { state = OUT; fputc('\n',new_fd); } break; /*IN_CPP_COM*/ case RIGHT_STAR: if(ch=='/') state = OUT; else if (ch!= '*') state = IN_COMMENT; break; /*RIGHT_STAR*/ case IN_STRING: if(ch=='\"') state = OUT; fputc(ch,new_fd); break; /*IN_STRING*/ } /*switch*/ fclose(fd); fclose(new_fd); return 0; /*dummy*/} /*main()*/אבל:1. האם מותר לי לכתוב כפי שכבר כתבתי (לאחר שאיחסנתי מערך כאשר כל תו במערך הוא char משם הקובץ) את השורה הבאה, כלומר להתייחס אליו כאל מחרוזת, כי ב-C מערך הוא מחרוזת:new_fd = fopen (new_file_name,"w+")כלומר שהתוכנית תדע להקים file ששמו מורכב מצירוף של איברי המערך, אפשרי?2. איך אני אמלא מערך בתוכן של argv[1] ? התוכן שלו הוא מחרוזת, ואני אמור כאילו לפרק אותה לתווים ולהכניס כל תו למקום שלו במערך החדש... האם הדרך שלי לא טובה ואני צריך להחליף אלגו' ? או לחילופין יש לי פונק' שיעזרו לי ?תודה !!
ארכיון
דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.