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

C++ - בעייה אחת מחליפה בעייה אחרת


מישהו שלא מצליח להיכנס

Recommended Posts

שלום אנשים

כתבתי פרוייקט בC++, דיי רציני, ויש לי 2 בעיות שונות, כשאני מתקן אחת, מגיעה השנייה

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

הפתרון - קיצור של המחרוזת (אני מוסיף מחרוזת קבועה - תגיות [הפלט בשפת XML] שאני יכול לקצר)

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

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

אני מניח שבעיית הגלישה בזיכרון (שגורמת להוספה של זבל) נובעת מoverflow - אין לי מושג איך זה קורה (ההקצאות כמו שצריך, הכל כולל התחשבות בתו שמסמל סוף שורה)

עזרה?

תודה מראש

איל

מצורף קובץ הפרוייקט - מכווץ

יש 2 קבצים - Main.jack ו-Square.jack שהתוכנית אמורה לטפל בהן ולהוציא קובץ XML (זה מוציא גם קובץ TKN בתור התחלה, ואז מהקובץ TKN נוצר הקובץ XML, הבעיות מתחילות ביצירה של הקובץ TKN וכשהתוכנית קורסת אפשר לראות בקובץ TKN עד לאן היא הגיעה)

ב"Tokenizer.cpp", בפונקציה TokenWithTags יש קטע שבו אני עוטף מחרוזת בתג <intConstant> </intConstant>, במצב הזה התוכנית מפסיקה לעבוד לפני שהיא מסיימת, אם משנים אותם ל integerConstant, היא מוסיפה זבל אחרי כל (או כמעט כל) תגיד כזאת אבל לא נתקעת

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

תודה מראש

איל

[attachment deleted by admin]

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

שמע, עדיין לא התעמקתי בכל הקוד שלך, אבל נראה שיש בו המון בעיות (גם דברים אסתטיים וגם באגים).

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

דרך אגב, באיזו מסגרת אתה לומד ++C, ואיזה רקע תכנותי יש לך?

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

לעצמי (שאני לא אשכח): strcat משרשר מחרוזת

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

אשמח אם תגיד לי מה השגיאות שיש שם

אני לא לומד C++, כל הידע שלי בC/C++ מגיע בעיקר מקורס מבוא למדעי המחשב ומקורס תכנות מונחה עצמים, קצת למדתי מהאינטרנט, ואני יחסית חלש בזה

אין לי ממש רקע תכנותי רציני, הדבר הכי רציני שעשיתי היה פרוייקט של חנות בC++ (אפשר להוסיף מוצר מסוג מסויים עם מחיר ותיאור, לבדוק כמה כסף יש מהמוצרים בחנות, מה מכרנו, כמה הרווחנו, ולייבא/לייצא את הכל לקובץ טקסט, המחלקה MyString נועדה במקור לזה)

תודה רבה על העזרה!

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

אז אני אשמח את תאמר מה מהקוד הזה אתה כתבת.

קודם כל, אני בכלל מתפלא שהקוד הזה מתקמפל.

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

נתחיל למנות את הבעיות - קודם כל, מבחינה אסתטית, יש המון קוד מיותר:

אין צורך לעשות <-this, זה פשוט מיותר.

יש המון המרות מיותרות (כל מיני מקומות שממירים ל-int ול-char ללא סיבה).

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

אתה משתמש גם ב-std::string וגם ב-MyString. אין שום סיבה להשתמש בשני מימושים שונים של אובייקטים שמשמשים לאותה מטרה. חוץ מזה, ב-MyString יש שדה בשם string, וזה יכול לגרום לבעיות (התנגשויות). בכלל, אני לא רואה שום סיבה להשתמש ב-MyString, אלא אם זו המטרה של התרגיל (לממש מחלקה של מחרוזת ולהשתמש בה).

ב-MyString יש דליפת מטורפת - כל פעם שעושים new, לא מוחקים את מה שהאובייקט החזיק קודם לכן, מה שמשאיר המון שהוקצה ולא שוחרר.

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

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

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

הקוד אולי משתמש בפקודות ++C אבל אינו מנצל את השימוש במחלקות

צירפתי מחלקה של מחרוזת שהשתמשתי במהלך לימודי (היא עדיין דורשת קצת שיפוץ)

אבל לא תגרום לדליפה (לפחות לא אמורה)

רצוי לתת גם שמות משתנים קצת יותר משמעותיים (יותר מ2 תווים)

תשתמש גם בCONST במקום במספרים (קריא יותר)

קפוץ לאתר הבא : http://linux.die.net/man/3/strtok

זה יקל עליך למצוא token

[attachment deleted by admin]

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

אז קח את המחלקה הסטנדרטית ותוסיף עליה. יש מעט מאוד מקרים שצריך לשנות את המימוש של string, לכל צורך שהוא.

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

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

אתה צודק המחלקה שיצרתי היתה יותר תרגיל לכיתה בזמנו וככה היא גם נשארה, לא יצא לי לעבוד על ++C כבר זמן מה

וב#C (שם התוכנית תעבוד טוב) string הוא דבר בסיסי אז זה הדבר הראשון שקפץ לראש

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

אז אני אשמח את תאמר מה מהקוד הזה אתה כתבת.

קודם כל' date=' אני בכלל מתפלא שהקוד הזה מתקמפל.

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

נתחיל למנות את הבעיות - קודם כל, מבחינה אסתטית, יש המון קוד מיותר:

אין צורך לעשות <-this, זה פשוט מיותר.

יש המון המרות מיותרות (כל מיני מקומות שממירים ל-int ול-char ללא סיבה).

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

אתה משתמש גם ב-std::string וגם ב-MyString. אין שום סיבה להשתמש בשני מימושים שונים של אובייקטים שמשמשים לאותה מטרה. חוץ מזה, ב-MyString יש שדה בשם string, וזה יכול לגרום לבעיות (התנגשויות). בכלל, אני לא רואה שום סיבה להשתמש ב-MyString, אלא אם זו המטרה של התרגיל (לממש מחלקה של מחרוזת ולהשתמש בה).

ב-MyString יש דליפת מטורפת - כל פעם שעושים new, לא מוחקים את מה שהאובייקט החזיק קודם לכן, מה שמשאיר המון שהוקצה ולא שוחרר.

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

[/quote']

את הקטע שאני מתייחס לטוקניזר בתור מחלקה תיקנתי, הקטע עם MyString - אלוהים ישמור, מלא בעיות תיקנתי בקוד שלו וזה פשוט לא נגמר...

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

מחקתי את #include <string> מMyString, לא יודע אפילו למה זה שם

אוקי, עכשיו תיקנתי את הדליפות מMyString, תודה רבה!

הסיבה שאני משתמש בMyString היא שאני לא ממש מצליח לעבוד עם המחלקה string, היו לי כמה בעיות (הייתי צריך פונקציות מסויימות שלא מצאתי) ולכן העדפתי להשתמש בMyString

התוכנית הזאת היא סוג של עזרה לקומפיילר, היא לוקחת תוכנית בשפת jack ומחלקת אותה לכמה טוקנים בסיסיים (זה תפקיד הTokenizer) ואחרי זה מנתחת את רשימת הטוקנים ומוציאה קובץ XML עם המבנה של בתוכנית (תחילת מחלקה, הצהרה על פונקציה, רשימת ארגומנטים וכו')

jack זו שפה מאוד בסיסית, מעט מאוד פקודות

תודה על העזרה :)

עריכה: סוף סוף שגיאה שאפשר לעבוד איתה! מה זה Heap Corruption?

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

כתוב לי After normal block #256 at 0x00338EA8

CRT detected that the application wrote to memory after end of heap buffer

בDebug Mode אני מקבל הודעה על breakpoint שאולי נגרם כתוצאה מפגים בHeap, הbreakpoint בדיוק על delete[] mstring (שיניתי את השם מstring לmstring ליתר ביטחון)

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

הסיבה שאני משתמש בMyString היא שאני לא ממש מצליח לעבוד עם המחלקה string, היו לי כמה בעיות (הייתי צריך פונקציות מסויימות שלא מצאתי) ולכן העדפתי להשתמש בMyString

איזו פונקציה אתה צריך שלא מצאת ב-string?

כמו שאמרתי קודם, באמת שאני לא רואה שום סיבה לא להשתמש ב-std string. כל פונקציה שאתה צריך נמצאת שם, ואם לא אז אתה יכול להוסיף פונקציה חיצונית שתעשה לך את העבודה, במקום לממש את כל המחלקה מחדש.

עריכה: סוף סוף שגיאה שאפשר לעבוד איתה! מה זה Heap Corruption?

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

כתוב לי After normal block #256 at 0x00338EA8

CRT detected that the application wrote to memory after end of heap buffer

בDebug Mode אני מקבל הודעה על breakpoint שאולי נגרם כתוצאה מפגים בHeap, הbreakpoint בדיוק על delete[] mstring (שיניתי את השם מstring לmstring ליתר ביטחון)

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

עשה טובה, קודם כל תסדר קצת את הקוד שלך (תעיף את ה-thisים המיותרים וההמרות המיותרות, תעביר את כל הקוד להשתמש ב-std::string בלבד) ואם עדיין יש לך בעיות, תעלה את הקוד החדש לכאן וננסה לעבור עליו.

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

איזו פונקציה אתה צריך שלא מצאת ב-string?

כמו שאמרתי קודם' date=' באמת שאני לא רואה שום סיבה לא להשתמש ב-std string. כל פונקציה שאתה צריך נמצאת שם, ואם לא אז אתה יכול להוסיף פונקציה חיצונית שתעשה לך את העבודה, במקום לממש את כל המחלקה מחדש.

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

עשה טובה, קודם כל תסדר קצת את הקוד שלך (תעיף את ה-thisים המיותרים וההמרות המיותרות, תעביר את כל הקוד להשתמש ב-std::string בלבד) ואם עדיין יש לך בעיות, תעלה את הקוד החדש לכאן וננסה לעבור עליו.

[/quote']

אשמח לעבור להשתמש במחלקה string

פונקציות שאני צריך: למצוא את האינדקס הכי נמוך שבו נמצא תו מסויים (indexOf(const char) - שיחזיר את האינדקס הראשון שבו מופיע התו

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

אופרטור השוואה יש? (str1==str2)

שרשור? (תו או מספר - למשל בMyString יש אופרטור + שמקבל 2 מחרוזות או מחרוזת ומספר, במקרה שזה מספר הפונקציה הופכת את המספר למחרוזת מתיאמה)

אפשר לעשות str1=str2?

והבעייה הכי גדולה שלי: איך אני משתמש בstring בקריאת שורה מקובץ? ניסיתי ולא הצלחתי =// אני דיי בטוח שזו הסיבה העיקרית שבגללה לא השתמשתי בstring

אם יש פתרון לכל הבעיות האלו, אני אחליף הכל לstring בשמחה (הבעייה העיקרית היא קריאת שורה מקובץ)

אם אתה מכיר איזה אתר שמסביר טוב על המחלקה string אשמח לקישור (עדיף בעברית, אבל אם אין אני אסתדר, פשוט לפעמים אני לא מבין למה מתכוונים)

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

תודה רבה!

יש לי רק בעייה אחת: אני צריך לחפש את המחרוזת "*/" (שמסמלת הערה), אבל במקרה שהמחרוזת לא נמצאה, אני מקבל ערך string::npos (לפי מה שכתוב כאן), איזה מין ערך זה? (מבחינת מספר - int)

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

עריכה: במחשבה שנייה, זה אדיוטי מצידי, אני יכול לבדוק בעצמי בקלות את שתי אלה

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

ארכיון

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

×
  • צור חדש...