אלגוריתם - תוכנית C - קדם מעבד - תכנות - HWzone פורומים
עבור לתוכן
  • צור חשבון

אלגוריתם - תוכנית C - קדם מעבד


iem

Recommended Posts

אני מנסה לחשוב על קוד שיבצע את הפעולה הראשונה של הקדם מעבד (הורדת הערות בקובץ גם מסוג 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. נוצר סוף סוף העתק לקובץ ההמקורי רק עם השם החדש. עכשיו אפשר לגשת אליו ולהעיף ממנו את ההערות.

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

אשמח לעזרה.

תודה !!

קישור לתוכן
שתף באתרים אחרים

  • תגובות 36
  • נוצר
  • תגובה אחרונה

פשוט תסרוק את הקובץ מההתחלה לסוף כאשר אתה רואה התחלה של הערה (או // או /* ) תעבור למצב התעלמות עד לסוף הערה

במקרה של // סוף הערה הוא מעבר לשורה חדשה במקרה השני סוף הערה יגיע כאשר תראה */ , במצב התעלמות אל תכתוב כלום לקובץ

הפלט אחרת תכתוב מה שסרקת כרגע.

קישור לתוכן
שתף באתרים אחרים

1) שים לב שאתה צריך להתעלם מ"הערות" שנמצאות במחרוזות. לדוגמא, ה"הערה" לא צריכה להמחק במצב כזה:


printf("/*this is not a comment*/");


2) אין סיבה להעתיק את כל הקובץ. תעבור תו תו, ותחליט האם אתה רוצה להעתיק אותו או לא. זה הרבה יותר פשוט.

קישור לתוכן
שתף באתרים אחרים

סבבה, כך אעשה. כבר כתבתי את התוכנית הזו...

ולגבי יצירת קובץ חדש ?

נניח ששם הקובץ עם סיומת C הוא בגודל לא ידוע, איך אני אמור לטפל בזה ? להגדיר מצביע על מערך בגודל דינמי ולטפל באופן שתיארתי ממקודם ?

תודה !

קישור לתוכן
שתף באתרים אחרים

נניח ששם הקובץ עם סיומת C הוא בגודל לא ידוע, איך אני אמור לטפל בזה ? להגדיר מצביע על מערך בגודל דינמי ולטפל באופן שתיארתי ממקודם ?

קודם כל, יש פונקציות שיכולות למצוא לך את גודל הקובץ (לדוגמה fseek+ftell). חוץ מזה, אתה לא צריך לקרוא את כל הקובץ במכה אחת. אתה יכול לקרוא אותו תו אחר תו, או בבלוקים בגודל קבוע.

קישור לתוכן
שתף באתרים אחרים

הפונק' האלה מטפלות בתוכן הקובץ. אני מדבר על שם הקובץ...

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

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

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

אבל הבעיה שלי היא שאני צריך שהקובץ החדש יהיה עם הספרה 1 בסוף, זה הכל....

איזה אלגוריתם יהיה הכי נכון כאן ?

קישור לתוכן
שתף באתרים אחרים

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

ועוד משהו... איך הכי טוב ל"הדביק" לשם הקובץ את הספרה 1 בסוף ? (name.c1 instead of name.c כיצירת קובץ חדש כמובן)

ועוד משהו.. האם מותר לי להגדיר:

#typedef strlen(argv[1]) FILE_LENGTH

?

תודה !

קישור לתוכן
שתף באתרים אחרים

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

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

ועוד משהו... איך הכי טוב ל"הדביק" לשם הקובץ את הספרה 1 בסוף ? (name.c1 instead of name.c כיצירת קובץ חדש כמובן)

strcpy ו-strcat.

#typedef strlen(argv[1]) FILE_LENGTH

?

אני מניח שהתכוונת ל-define ולא ל-typedef. אבל למה לך לעשות דבר כזה לעזאזל? פשוט תגדיר משתנה ותשים בו את הערך הזה.

קישור לתוכן
שתף באתרים אחרים

כתבתי את הקוד הבא:


#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 כלומר היא לא מצליחה לפתוח את הקובץ (אני הכנסתי בקוד ההערה במקרה כישלון).

לא מצליח (כבר שעות) לעלות על השגיאה...

קישור לתוכן
שתף באתרים אחרים

שיפצתי את ההתחלה כדי שיהיה יותר קריא ומובן קצת:


#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.

האם פעלתי בצורה לא נכונה ?

קישור לתוכן
שתף באתרים אחרים

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

חוץ מזה, עוד שתי תקלות בייצור המערך:

א. אתה צריך לשמור מקום נוסף ל-'0\' בסופו.

ב. התו האחרון צריך להיות '1', לא 1. אלה שני דברים שונים לחלוטין.

קישור לתוכן
שתף באתרים אחרים

תיקנתי את התוכנית מבחינת א. , ב. , שרשמת לי (היתה לי התחושה אבל לא הייתי סגור על זה...).

אבל עדיין יש משהו שמציק לי..

כרגע התוכנית היא כזאת:


#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] ? התוכן שלו הוא מחרוזת, ואני אמור כאילו לפרק אותה לתווים ולהכניס כל תו למקום שלו במערך החדש... האם הדרך שלי לא טובה ואני צריך להחליף אלגו' ? או לחילופין יש לי פונק' שיעזרו לי ?

תודה !!

קישור לתוכן
שתף באתרים אחרים

ארכיון

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


×
  • צור חדש...