עזרה בתוכנית ב C++

  • פותח הנושא lmalo
  • פורסם בתאריך

vinney

Well-known member
למה שזה יתאפס?

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

neko

New member
נצלו"ש, קבצים ב++C, בעיה מעצבנת.

אני קורא קובץ שהפורמט שלו לא לגמרי אחיד, והוא הולך משהו בסגנון: מספר מספר מספר X זוגות מספרים מספר מספר מספר Y זוגות מספרים וכו'. עכשיו, אני יודע כמה שורות יש בקובץ (קבוע), אבל אני לא יודע מה האורך של כל שורה (משתנה משורה לשורה). בינתיים, אני קורא שלשה, ואז מתחיל לקרוא זוגות עד שאני נכשל - אבל אני נכשל רק בסוף הקובץ, ולא בסוף השורה כמו שאני רוצה
האם יש דרך לדעת שאני בסוף השורה? מצ"ב הקוד של הלולאה שקוראת את הקובץ:
for (int i=0; i<k; i++) { if ((fscanf(sceneFile, "%f %f %f",&(molds.x), &(molds.y), &(molds.z)))!=3) { return INVALID_DATA; // 3 numbers are expected but could not be read. } while ((fscanf(sceneFile, "%f %d", &angle, &axis))==2) { molds.rotations[axis-1]+=angle; cout << "Axis = " << axis << ", angle= " << angle << "." << endl; } }
 

The Albatross

New member
מה עם getline?

ifstream fileObj(path.c_str(), ios::in); string strLine = ""; if (fileObj.is_open()){ while (getline(fileObj, strLine)){ } }​
 

neko

New member
שמעתי על הקטע של STREAMS

(אני עובד ב++C למרות שתכל'ס למדתי רק C) - אני יכול לשלב את זה עם FOPEN וFSCANF וכו', או שאני צריך לקרוא את הקובץ אחרת לגמרי?
 

erezsh

New member
שאלה

למה אתה משתמש ב-scanf?! אבל בכל זאת, אם אתה מתעקש, אתה יכול לקרוא את השורה כפי שנאמר פה (fgets), ואז לעבור עליה עם sscanf...
 

gmorphus

New member
מה רע בfscanf?

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

neko

New member
לא הולך - הוא עובר לשורה הבאה

בלי לתת חיווי גם אם יש וגם אם אין \n.
 

neko

New member
מה זאת אומרת למה SCANF?

כמו שאמרתי קודם, אני לא מכיר שום דרך אחרת לקרוא קבצים! בכל מקרה, ניסיתי עכשיו לקרוא שורה עם FGETS ולעבור עליה עם SSCANF, אבל גם זה לא עובד, כי כל פעם שאני קורא לSSCANF, הוא מתחיל מתחילת הSTRING ולא מתקדם עליו
 

vinney

Well-known member
scanf, על שלל גווניה, זה מקור לבאג

qתשתמש בfgets ואז תריץ sscanf עליה, אם אתה רוצה. אף פעם אל תפעיל scanf/fscanf ישירות על הקלט, זה מתכון לצרות.
 

vinney

Well-known member
יש הרבה

הוא מתעלם מקלט לא מתאים (כמו במקרה שלנו) בלי שתדע על זה חופשי דורס זכרון אם אתה לא מקצה מספיק לא בודק בשום צורה שהפרמטרים שהוא מקבל (מצביעים, כולם) מתאימים לformat string שהוא מקבל זה רק דוגמאות נפוצות ביותר, זה פונקציה שהשימוש בה דורש הרבה הרבה הרבה מאוד תשומת לב מצדו של המתכנת, כי לא בודקת כלום. הדרך היחידה שבה אפשר להשתמש ב scanf זה אך ורק כפעולה הפוכה לprintf קודם, אחרת עדיף למצוא דרך אחרת.
 

DecayCell

New member
אבל...

גם ()gets, על שלל הווריאציות שלה, לא בטוחה במיוחד... למעשה, היא כל-כך לא בטוחה ש-GCC פולט אזהרה אם משתמשים בה, כמדומדני.
 

vinney

Well-known member
נכון

ומאותן הסיבות. להבדיל, fgets, שצריך להשתמש בה במקום בgets, מקבלת כקלט מס' מקסימום של תוים לקריאה, וכך נמנעת בעיית דריסת הזכרון.
 

erezsh

New member
אוקיי. חשבתי על זה קצת, ויש 3 דרכים

א. בעזרת fscanf: במקום פורמט של %f ואז %d ואז רווח, תחליף את הרווח ב-%c. כך אחרי כל fscanf תוכל לבדוק את התו שנקרא ולראות אם הוא רווח או שורה חדשה. ב. בעזרת sscanf: בסוף הפורמט תוסיף %n (אולי אני מתבלבל בתו) - שתפקידו להגיד לך כמה תווים נקראו עד עכשיו. כך תוכל להוסיף את הערך המוחזר למשתנה המחרוזת בקריאה הבאה, ולדלג על מה שכבר קראת. ג. הדרך הנורמלית - לפרסר בעצמך: למה הדרך הנורמלית? כי אתה לא תיפול בפח של רווח אחד יותר מדי, או שורה ריקה וכו'. ככה אתה יודע שאתה מטפל בכל המקרים יוצאי הדופן. פשוט תשתמש ב-atoi/strtol/strtod/atof וכו'. אתה יכול בקלות למצוא מתי מספר נגמר, כי מתחילי רווחים, ומתי מספר מתחיל, כי נגמר רווחים, ומתי נגמרת השורה בדיוק.
 

neko

New member
החלטתי לאמץ את א', שעובדת נפלא

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

frangelico

New member
את המספר

במקרה שהמחרוזת מייצגת באמת מספר תוכל לקבל כך:
int Mispar(char a[],int len) { int n = strlen(a) - len; if ((a[n]>=48)&&(a[n]<=57)) { return (a[n] - '0') * pow(10, len - 1) + Mispar(a,len-1); } return 0; }​
ה n לא הכרחי ואפשר גם בלעדיו הוא רק בשביל שיהייה ברור יותר ולחסוך בקריאות לפונקציות.
 
למעלה