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

כתיבה וקריאה מקבצים C++.


pain_killer12

Recommended Posts

שלום חברים, יש לי תרגיל, שבו אני מקבל קובץ קוד בC++ בקובץ בפורמט txt

ואמור להוריד ממנו את ההערות שכתובות בו ולהעתיקו לקובץ חדש בלי ההערות.

אמרו לנו גם לבדוק אם יש בעיה לפתוח את הקבצים המדוברים (הם לא קיימים או משהו אחר)

אז להשתמש בexceptions המובנים של fstream. אין לי מושג מה זה. מישהו יכול להסביר לי איך ניגשים אליהם?

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

עכשיו, אני אמור ליצור מחלקה File שיהיו בה בעצם 3 משתנים פרטיים:

משתנה מסוג ifstream (שיצביע לקובץ הקלט) משתנה מסוג ofstream (קובץ הפלט) ומשתנה מסוג fstream (קובץ זמני לקריאה וכתיבה).

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

עכשיו כמה שאלות:

1. אחרי שאתחלתי כל אחד מהם עם open, איך אני בודק אם היו בעיות בפתיחה? מה אלה הדגלים האלה ios::in/out ?

לא הבנתי כל כך מהאינטרנט.

2. במידה ואני עושה זאת בCtor, אני יכול לעשות שם try על החלק של הפתיחה ואחרי זה לעשות כמה cacheים?

איך משתמשים באקספשן המובנים ומה אני אמור לתפוס?

צריך לבדוק שאין "שגיאות קומפילציה" של הערות, כמו /* (סוגר הערה) בלי פותח הערה וכו'.

על מנת לעשות זאת, אמרו לנו להשתמש בexceptions שוב. אין בעיה עם זה אני חושב.

השאלה הבאה שלי, היא האם הmain בעצם מיותר פה? כי הרי אני אצור משתנה מסוג File בCtor יפתחו הקבצים

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

תודה מראש לכל העוזרים.

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

יש דוגמא טובה כאן: http://www.cplusplus.com/reference/iostream/ios/exceptions/

הרעיון הוא שאומרים ל-fstream על מה לזרוק exceptions.

למיטב זכרוני ios::in ו-ios::out הם דגלים שאומרים האם ה-stream הוא לקלט, פלט או שניהם.

כדאי לדעת אם open מצליח, פשוט תשתמש ב-operator!


std::ifstream f("file.txt");
if ( !f ) return ERROR;

ראה גם את הדוגמא.

עבור exception-ים שאתה זורק בסגנון "אין הערה סוגרת", עדגיף שתזרוק std::runtime_exception או תזרוק טיפוס משלך שיורש ממנו.

ה-main לעולם לא מיותר מהבחינה שאם אין לך main התוכנית לא תתלנקג'.

כמובן, יכולת להשאיר אותו ריק ולכתוב את כל הקוד באיזה constructor של מחלקה, ואז לייצר אובייקט גלובלי מהמחלקה (זה מה שאתה הצעת, נכון?). אל תעשה את זה!

יש כאן כמה טעויות:

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

2) פחות אפשרויות במבנה התוכנה, טיפול בשגיאות וכו'.

3) בתוך ctor של משתנה גלובלי אין לך שליטה על סדר ההפעלה של ה-ctor-ים, מה שמוביל ל-static initialization order fiasco, משהו שעלול לנשוך אותך ללא אזהרה.

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

אוקיי, תודה רבה על התגובה והעזרה. יש לי כמה שאלות בנוגע למה שכתבת.

1. אם אני פותח קובץ לכתיבה עם ios::out, ונגיד והקובץ לא קיים, הוא יוצר אותו? כי אם כן אז זה לא טוב לי.

2. הבנתי איך לבדוק אם הקובץ נפתח. השאלה היא איך לזרוק בדיוק, את מה, ומה לתפוס.

תראה מה רשמו לי בתרגיל:

"בעיות של גישה לקובץ לדוגמא בלתי אפשרי לפתוח את קובץ הקלט / הפלט או

שהקובץ לא קיים.

המובנים. הטיפול בבעיות אלו יהיה exception- לשם תפיסת בעיה זאת יש להשתמש ב

הדפסת הודעה למשתמש ואז סיום פעולת התוכנית. הדפסת הודעת שגיאה למשתמש

תהיה כדלקמן:

במקרה של בעיה בקובץ הקלט: תודפס לקובץ הפלט ההודעה:

input.txt is not valid.

במקרה של בעיה בקובץ הפלט: תודפס למסך ההודעה:

output.txt is not valid. Can not write to output file."

נגיד ועשיתי משהו כזה:

ofstream x;
x.open("out.txt",ios::out);
if(!x)

עכשיו מה אני רושם בif כדי לזרוק את האקספשן המובנה? מה אני רושם אח"כ כדי לתפוס?

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

איך אתה מציע לי לבנות את הקוד?

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

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

אין לי הרבה זמן להתעמק כאן אז אשאיר אותך עם רמזים:

1) http://www.cplusplus.com/reference/iostream/ios_base/openmode/ - אלה הדגלים שאפשר להעביר ל-open, ויתכן שאפשר להשתמש בהם כדי למנוע יצירת קובץ. תצטרך פשוט לחפש ברשת.

אני לא בטוח שב-C++ אפשר באופן פורטבילי לפתוח קובץ קיים לכתיבה אבל להכשל אם הוא לא קיים. זה נשמע משהו מאוד מוזר.

2) יש לך שתי אופציות. אתה יכול להגיד ל-fstream לזרוק exceptions בעצמו, וזה מה שמודגם בלינק ששלחתי קודם. אופציה שניה זה שאתה תבדוק אחרי כל פעולה מה המצב של ה-stream ותזרוק exception בעצמך.


using namespace std;
void write_output()
{
...
ofstream x;
x.open( ... );
if (!x)
throw runtime_exception("cannot open output file");
...
}


int main()
{
try
{
...
write_output();
...
}
catch( runtime_exception& e)
{
cout << "error: " << e.what() << endl;
return 2;
}

return 0;
}

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

אוקיי, הבנתי בערך איך להשתמש באקספשן המובנים.

השאלה שלי עכשיו היא כזאת.

אני צריך להפריד בין אקספשן מובנה של קובץ קלט ואקספשן מובנה של קובץ פלט:

ifstream rFile;
ofstream wFile;
fstream tFile;
rFile.exceptions(ifstream::failbit | ifstream::badbit);
wFile.exceptions(ofstream::failbit | ofstream::badbit);
try
{
wFile.open("output.txt",ios::out);
rFile.open("input.txt",ios::in);
tFile.open("temp.txt",ios::in | ios::out);
}
catch(ofstream::failure x)
{
cout<<"output.txt is not valid. Can not write to output file.\n";
}
catch(ifstream::failure y)
{
wFile<<"input.txt is not valid.\n";
}

אבל הקומפיילר זורק לי אזהרה, שהcatch הראשון יטפל בכל מה שיזרק. השאלה אם זה באמת נכון?

ואז איך אני מפריד בין המקרים? או שזה לא נכון ופשוט להשאיר את זה ככה.

(שים לב, במקרה והifstream זורק אותי אני מדפיס לקובץ הפלט. ואם הפלט זורק אותי אני אמור להדפיס למסך).

תודה רבה.

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

ofstream::failure ו-ifstream::failure הם למעשה אותו טיפוס (ios_base::failure).

ה-catch השני מנסה לתפוס את אותו סוג חריגה כמו הראשון, ולכן הוא בתכל'ס לא עושה כלום.

הפתרון הוא להפריד את פתיחת הקבצים לשלושה tryים שונים.

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

ארכיון

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

×
  • צור חדש...