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

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


iem

Recommended Posts

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

תיקנתי, למרות שאני חייב לומר לך שלא כ"כ הבנתי ההבדל בין strcat לבין strcpy.

#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_len)*sizeof(char));

strcpy(new_file_name , argv[1]);
new_file_name[new_file_string_len] = '\0';
new_file_name[new_file_string_len-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), ואם אני לא לוחץ CTRL C (עובד תחת לינוקס) היא לא terminated.

את הקובץ החדש היא לא יצרה לי... :'(

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

תסתכל על הקוד שלך.

תדפיס את המחרוזת שאתה יוצר לפני שאתה מנסה לפתוח את הקובץ.

תבדוק שהאינדקסים שלך תקינים (רמז: מה האינדקס של האיבר האחרון במערך בגודל n?)

ושאלתך: יודע את ההבדל ביניהם.

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

צודק, שכחתי שמתחילים מ-0 ועבור n זה יהיה n-1.

אבל הזזתי אינדקסים, נתתי פקודת הדפסה, וכלום... אני באמת לא מוצא עכשיו איפה אני טועה.. :nixweiss:


#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_len)*sizeof(char));

strcpy(new_file_name , argv[1]);
new_file_name[new_file_string_len-1] = '\0';
new_file_name[new_file_string_len-2] = '1';
printf ("new file name is: %s",new_file_name);
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()*/

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

אוקי, עכשיו אנחנו מתקדמים לאנשהו.

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

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

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

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

קודם כל זו התוכנית :


#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_len)*sizeof(char));

strcpy(new_file_name , argv[1]);
new_file_name[new_file_string_len-1] = '\0';
new_file_name[new_file_string_len-2] = '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()*/

עכשיו.. היא מייצרת לי את ה- c1.* ובלינוקס יש את הקטע שלקובץ טקסט ניתן לראות את ההתחלה שלו באייקון, כמו מין preview זול כזה, אז רואים שהוא הוריד לי את ההערות של השורות לפני הגדרת המשתנים הגלובליים אבל כשאני בא לפתוח את זה עם העורך טקסט הרגיל של לינוקס, הוא מריץ פס טעינה של כמה דקות ולא פותח אותו בסוף, ואם אני מעתיק את הקובץ לסביבת אז אחרי הרבה זמן טעינה הוא פותח לי אותו עם notepad ומשם אגב ראיתי שהקובץ מכיל את הטקסט עד ה-main פחות או יותר, ומשם רק ריבועים וקישקושים...

יש לך הסבר ורעיון איך אני פותר את זה ? עברתי על התוכנית ועל יבש היא רצה סבבה...

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

התוכנית שלך אכן נראית סבבה.

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

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

חוץ מזה, כמה טיפים קטנים:

1. תמיד תמיד תמיד שמים סוגריים מסולסלים אחרי if/for/while, גם אם זו רק פקודה אחת. זה יותר קריא ומונע טעויות בעתיד.

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

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

ניסיתי את מה שאמרת אבל זה פשוט לא הולך לי... אני תמיד עובד רק דרך ה-shell.

יכול להיות שאולי ב-while משהו לא תקין ? ניסיתי לפרק את ה- while ל-2 פקודות אבל אז הוא פתח לי את הקובץ בלי לכתוב כלום אליו...

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

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

:yelclap: עובד כמעט מושלם !!

יש רק בעיה קטנה...

הקוד שכתבתי:


#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;
if (argc > 2)
{
printf("Too many arguments !\n\n Program will now terminated !");
exit(0);
}

if (argc==1)
{
printf("Missing argument !\n\n Program will now terminated !");
exit(0);
}

new_file_name=(char *) malloc ((new_file_string_len)*sizeof(char));



strcpy(new_file_name , argv[1]);
new_file_name[new_file_string_len-1] = '\0';
new_file_name[new_file_string_len-2] = '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 (!feof(fd)){
ch=fgetc(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*/
} /*while*/
fclose(fd);
fclose(new_fd);
return 0; /*dummy*/

} /*main()*/

הקפדתי על הסמנטיקה שהערת לי בהודעה הקודמת BTW...

זה ה-name.c לצורך העניין (יכול להיות כל file name):

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


/* sample input */
#include <stdio.h> /* you should not treat this line*/
#include "cons.h" /* need to be replaced */
#include "mac.h" /* also need to be replaced */

enum numbers {zero,one,three=3,four};

void main()
{
int x,y=size,z;
x=extraSize;
z=first(x,y); /*the parameters are in the same names as in the macro itself */
printf("first is: %d",((x+z)>three*size)?first(x, y):first(one,zero)); /*some nice line */
if (someMacro(three,x,y)>four) /* another nice line */
y+=extraSize;
else
printf(" extraSize = %d",extraSize);

}

וזה מה שאני קיבלתי לאחר ההפעלה:


#include <stdio.h>
#include "cons.h"
#include "mac.h"

enum numbers {zero,one,three=3,four};

void main()
{
int x,y=size,z;
x=extraSize;
z=first(x,y);
printf("first is: %d",((x+z)>three*size)?first(x, y):first(one,zero));
if (someMacro(three,x,y)>four)
y+=extraSize;
else
printf(" extraSize = %d",extraSize);

}

ÿ

לא הבנתי מה זה הכאילו y הזאת שיצאה בסוף ואיך אני נפתר ממנה.... :nixweiss:

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

feof תחזיר ערך שאינו 0 רק ברגע שתקרא את התו ש"אחרי" התו האחרון בקובץ. כלומר, אם הקובץ הוא בגודל 10, אז אחרי 10 קריאות הפונקציה feof עדיין תחזיר 0. בקריאה ה-11, fgetc תחזיר ערך EOF, ורק מהרגע הזה feof תחזיר ערך שונה מ-0.

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

שמתי

	ch=fgetc(fd);

פעם אחת לפני ה- while לקליטת הראשון, ופעם אחת אחרי ה-case ולפני סוף ה-while לטיפול בכל אחד שאינו הראשון ונראה לי שפתרתי את הבעיה....


#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;
if (argc > 2)
{
printf("Too many arguments !\n\n Program will now terminate !");
exit(0);
}

if (argc==1)
{
printf("Missing argument !\n\n Program will now terminate !");
exit(0);
}

new_file_name=(char *) malloc ((new_file_string_len)*sizeof(char));

strcpy(new_file_name , argv[1]);
new_file_name[new_file_string_len-1] = '\0';
new_file_name[new_file_string_len-2] = '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);
}

ch=fgetc(fd);
while (!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*/
ch=fgetc(fd);
} /*while*/
fclose(fd);
fclose(new_fd);
return 0; /*dummy*/

} /*main()*/

שאלה נוספת...

אם אני רוצה לבדוק תקינות הקלט, כלומר argv[1], שיהיה קובץ c.* תקין, האם מספיק לי לבדוק שהאיבר אחד לפני האחרון הוא 'c' וזה שלפניו הוא '.' והראשון הוא אות או בין a-z או בין A-Z ? או שיש עוד קאצ' ?

תודה !

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

בעקרון הקוד שלך סבבה. למרות שיכלת פשוט לשים את ה-fgetc בתוך התנאי של ה-while ולהשוות את התוצאה ל-EOF (בלי להשתמש ב-feof בכלל).

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

..\blabla.c

וזה גם שם קובץ תקין. אבל הכי פשוט לתת לפונקציה fopen לבדוק את זה עבורך.

חוץ מזה, תקינות שם קובץ זה דבר תלוי . לדוגמה, c:\blabla.c זה שם תקין בחלונות אבל לא בלינוקס, ו-home\users\yoav\blabla.c\ זה שם תקין בלינוקס ולא בחלונות.

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

ארכיון

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


×
  • צור חדש...