קלט/פלט ב - ++ C   

 

 


תוכן הפרק

עריכת קלט ופלט

עריכת פלט

שדות  בהדפסה

קביעת מצב עריכה

הדפסת מספרים שלמים לפי בסיס מסויים (אוקטלי, דצימלי או הקסדצימלי).

יישור שדות

עריכת פלט למספרים ממשיים.

מניפולטורים (manipulators)

קלט

קבצים  Files

מהו קובץ?

עבודה עם קבצים

פתיחת קובץ

שימוש בעצמי זרם עבור קבצים

סיום העבודה עם קובץ - סגירת הקובץ

פעולות נוספות על קבצים

קריאת/כתיבת תו מקובץ:

עוד פעולות  (תקציר בלבד - לפני שימוש נא לפנות לספר או לעזרה)

גישה ישירה למקום מסויים בקובץ

שינוי מקום בקובץ:

פונקציות הבודקות את מצב הקובץ

 

 

·            אין פקודות קלט/פלט בשפת C++!

·            תקן השפה מגדיר ספריות של מחלקות ופונקציות לבצוע קלט/פלט.

·            מבצעים קלט ופלט על ידי שימוש בפונקציות ועצמים המיועדים למטרות אלה.

·            ב C++ הפלט הוא זרם (stream) של בתים שהתוכנית שולחת. גם הקלט מגיע מתוך זרם בתים.

·            ישנם ארבעה זרמים  (streams) תקניים, הקיימים עבור כל תוכנית, והם:

                     1.  cin  עצם מטיפוס המחלקה  istream המייצג את הזרם המגיע מהקלט התקני (ברירת המחדל המקלדת).

                     2.  cout עצם מטיפוס המחלקה  ostream המייצג את הזרם הנשלח לפלט התקני (ברירת המחדל מסך).

                     3.  cerr עצם זהה ל cout, המייצג את זרם הנשלח לפלט השגיאה התקני (ברירת המחדל מסך).

                     4.  clog  עצם זהה ל  cerr  פרט לכך שהוא מכיל מכלא (buffer).

·            התכניתן יכול להגדיר עצמי קלט/פלט נוספים לייצוג של זרמים נוספים.

·            המחלקות הנ"ל מוצהרות בקובץ <iostream.h>.

·            צורת השימוש הנפוצה בעצמים אלה, בכדי לבצע קלט/פלט, היא שימוש במפעילים  >> <<  המוגדרים מחדש (overloaded)עבורם.

 

עריכת קלט ופלט 

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

               ·            נתאר חלק מאפשרויות העריכה הללו.

 

 

עריכת פלט

שדות  בהדפסה

               ·            הפונקציה  cout.width(n)   קובעת כי ההדפסה הבאה של המספר או המחרוזת (אך לא תו בודד) תהיה בשדה ברוחב של n  תווים לפחות.

cout.width(4);

cout << '(' << 12 << ')';

הפלט  (שים לב כי קביעת הרוחב לא חלה על הדפסת תו בודד.) :

(  12)

               ·            הפונקציה  cout.fill(c)  קובעת כי תו המילוי לשדה יהיה התו c.

cout.width(4);

cout.fill('#');

cout << '(' << "ab" << ')';

הפלט:

(##ab)

 

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

cout.width(4);

cout << '(' << 121212 << ')';

הפלט יהיה:

(121212)

 

               ·            השפעתן של הפונקציות width ו- fill הינה רק על המספר או המחרוזת הראשון המודפס לאחריהן בלבד. מכאן, שבקטע הקוד הבא:

cout.width(4);

cout.fill('#');

cout << '(' << 12 << "),(" << 12 << ")\n";

נקבל את הפלט:

(##12),(12)


קביעת מצב עריכה

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

        עד שקובעים מצב חדש.

               ·            הפונקציה flags() קובעת מצב עריכה חדש.

               ·            הפונקציה setf()  מוסיפה אפשרויות נוספות למצב העריכה הקיים.

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

 

// flags for controlling format (Example only!):

class ios {

public:

          enum

          {

          skipws=01,             // skip whitespace on input

                                // field adjustment:

          left=02,                  // padding after value

          right=04,                // padding before value

          internal=010, // padding between sign and value

                                // integer base:

          dec=020,                // decimal

          oct=040,                 // octal

          hex=0100,              // hexadecimal

          showbase=0200,      // show integer base

          showpoint=0400,     // print trailing zeros

          uppercase=01000,    // 'E', 'X' rather than 'e', 'x'

          showpos=02000,      // explicit ‘+’ for positive ints

                                // floating point notation:

          scientific=04000,     // .ddddddEdd

          fixed=010000,         // dddd.dd

                                // flush output:

          unitbuf=020000,      // flush after each output operation

          stdio=040000 // flush after each character

          };

};

 

 

               ·            הפונקציה  flags(int flgs)  קובעת מצב עריכה חדש, ומחזירה את מצב העריכה הנוכחי (כך אפשר לשמור את המצב הנוכחי 

        כדי לחזור אליו בהמשך).

לדוגמא:

#include <iostream.h>

void main()

{

    cout << 28 << ' ' << -28 << endl;

    cout.width(6);

    cout.flags(ios::left | ios::showbase | ios::hex);

    cout << 28 << ' ' << -28 <<  endl;

}

הפלט:

28 -28

0x1c   0xffffffe4

 

במקרה זה, ייקבע יישור (alignment) לשמאל, מספר שלם יודפס לפי בסיס 16, והקידומת  0x  תופיע לפניו.

הפונקציה flags() מחזירה את מצב העריכה הקודם.

               ·            משתמשים במפעיל  |   (bitwise-OR)  בכדי לשלב מספר תנאים.

               ·            הפונקציה setf()  מוסיפה אופציות למצב הקיים (ואינה מחליפה אותו כמו  flags() ).

כך שלמשל:

cout.setf(ios::showpos);

שקול ל-

cout.flags(cout.flags() | ios::showpos);

·   למבינים בסיביות: אפשר להשתמש בפונקציה  flags()  לביטול אופציות  תוך שימוש במפעיל ~ (הופך סיביות, או משלים לאחד) ובמפעיל  &  (bitwise-AND) באופן הבא:

cout.flags(cout.flags() & ~ios::showpos);


הדפסת מספרים שלמים לפי בסיס מסויים (אוקטלי, דצימלי או הקסדצימלי).

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

 

לדוגמא:

cout << 1234 << ' '; // default decimal

cout << 1234 << ' ';

 

cout.setf(ios::oct, ios::basefield); // octal

cout << 1234 << ' ';

cout << 1234 << ' ';

 

cout.setf(ios::hex, ios::basefield); // hexadecimal

cout << 1234 << ' ';

cout << 1234 << ' ';

הפלט:

1234 1234 2322 2322 4d2 4d2

 

 

 

  1. האופציה ios::showbase  מציגה בהדפסה את הבסיס הנוכחי. (0 מוביל בשביל בסיס 8, 0x  מוביל בשביל בסיס 16):

cout.setf(ios::showbase);

cout << 1234 << ' ';

cout.setf(ios::oct, ios::basefield);

cout << 1234 << ' ';

cout.setf(ios::hex, ios::basefield);

cout << 1234 << ' ';

הפלט:

1234  02322  0x4d2

דוגמא להדפסת מספרים שליליים לפי בסיס 16:

cout.setf(ios::showbase | ios::internal);

cout.setf(ios::hex, ios::basefield);

cout.width(12);

cout << -28 << ' ' << 28 << endl;

הפלט:

0x  ffffffe4 0x1c

 

יישור שדות

גם כאן ניתן לבחור באפשרות אחת: יישור הפלט לימין, לשמאל או לאמצע השדה. לכן יש להוסיף לארגומנט ios::left, ios::right או ios::internal. גם כאן משתמשים בארגומנט ios::adjustfield שני המתאר את סוג האופציה שקובעים מחדש.  ברירת המחדל: בימין השדה. למשל:

cout.width(6);   // default: ios::right

cout << '(' << -12 << ")\n";

cout.width(6);

cout.setf(ios::left, ios::adjustfield);

cout << '(' << -12 << ")\n";

cout.width(6);

cout.setf(ios::internal, ios::adjustfield);

cout << '(' << -12 << ")\n";

הפלט:

(   -12)

(-12   )

(-   12)

 


עריכת פלט למספרים ממשיים.

               ·            מספר ספרות הדיוק נקבע ע"י הפונקציה precision() באופן הבא:

               ·            שים לב לעיגול המספר.

 

cout << 1234.56789 << ' ';  // default: precision(6)

cout << 1234.56789 << '\n';

 

cout.precision(8)

cout << 1234.56789 << ' ';

cout << 1234.56789 << '\n';

 

cout.precision(4)

cout << 1234.56789 << ' ';

cout << 1234.56789 << '\n';

 

cout.precision(3)

cout << 1234.56789 << ' ';

cout << 1234.56789 << '\n';

 

הפלט:

1234.57 1234.57

1234.5679 1234.5679

1235 1235

1.23e3 1.23e3

·   הקביעה של  precision()  תקפה עד הקריאה הבאה לפונקציה.

 

יש שלוש אפשרויות להציג מספר ממשי:

   1.   משמעות הדיוק היא כמות הספרות שתופענה משני צידי הנקודה (6 ספרות - ברירת המחדל).

   2.   כאשר משתמשים באפשרות ios::fixed משמעות הדיוק היא כמות הספרות אחרי הנקודה העשרונית.

   3.   כאשר משתמשים באפשרות ios::scientific משמעות הדיוק היא כמות הספרות אחרי הנקודה העשרונית, כאשר יש ספרה אחת לפני הנקודה וחזקה מתאימה של 10 בסוף המספר.

·   בכדי לקבוע את האפשרויות ios::fixed,  ios::scientific  משתמשים בפונקציה  setf()  עם שני ארגומנטים כאשר הארגומנט השני הוא  ios::floatfield. למשל:

cout << 1234.56789 << '\n'; 

cout.setf(ios::fixed, ios::floatfield);

cout << 1234.56789 << '\n';

cout.setf(ios::scientific, ios::floatfield);

cout << 1234.56789 << '\n';

cout.setf(0, ios::floatfield); // reset to default.

cout << 1234.56789 << '\n'; 

הפלט:

1234.57

1234.567890

1.234568e+03

1234.57

               ·            הקריאה ל- setf(0, ios::floatfield) גורמת להחלת ברירת המחדל.

               ·            אזהרה! - מהדרים ישנים אינם מקפידים על כללים אלו בדיוק.

 

 

 

 


מניפולטורים (manipulators)

·   מניפולטורים הם כלים (ממומשים באמצעות פונקציות ומחלקות מיוחדות) אשר ניתן לשלבם בתוך הוראות קלט ופלט בצורה נוחה.

·   כלים אלה מופעלים על עצמי קלט/פלט, וההפעלה משולבת עם הפעלת המפעילים  >> << . 

·   על-מנת להשתמש במניפולטורים חייבים להצהיר עליהם באמצעות השורה הבאה:

#include <iomanip.h>

·   היתרון העיקרי בשימוש במניפולטורים טמון בעובדה שלעיתים די קרובות אנו מעונינים בעריכה שונה של נתונים שונים באותו רצף. למשל:

cout.width(4);

cout << a << ' ';

cout.width(6);

cout << b << '\n';

ניתן לרשום את כל זה בשורה אחת בעזרת המניפולטור setw():

cout << setw(4) << a << ' ' << setw(6) << b << '\n';

הדבר מאפשר כתיבה מקוצרת וברורה יותר.

 

טבלאת המניפולטורים העיקריים:

 

שם המניפולטור

קלט

פלט

תיאור

endl

 

x

עבור לשורה חדשה של פלט

ends

 

x

לשלוח התו 0 (NULL) לפלט

flush

 

x

לשלוח מייד לפלט את תוכן ה-buffer

dec

x

x

מספרים יקראו/יכתבו בבסיס עשרוני

oct

x

x

מספרים יקראו/יכתבו בבסיס 8

hex

x

x

מספרים יקראו/יכתבו בבסיס 16

ws

x

 

דלג על תווים "לבנים" (רווח, טאב, שורה-חדשה)

setw(int w)

x

x

קביעת רוחב שדה קריאה/כתיבה ל- w

setfill(char ch)

x

x

קביעת המלוי של שדה הפלט לתו ch (ב"מ:  רווח)

setprecision(int n)

x

x

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

 

 

דוגמאות:

cout << 1234 << ' '

     << hex  << 1234 << ' ' << oct << 1234 << endl;

יפיק את הפלט:

1234 4d2 2322

כמו-כן, הקוד:

cout << setw(4) << setfill('#') << '(' << 12 << ")\n";

cout << '(' << 12 << ")\n";

יפיק את הפלט:

(##12)

(12)

ללמדינו שהשפעת המניפולטורים מקומית.

קלט

               ·            בנוסף על המפעיל   >>    יש באפשרותנו לבצע קלט באמצעות הפונקציה  cin.get(). לפונקציה זו שתי גרסאות:

istream& get(char& c);

istream& get(char* p, int n, char separate = '\n');

               ·            הגרסא הראשונה של  get() מיועדת לקריאת תו בודד.

void main()

{

    char c;

    while (cin.get(c)) cout << c;

}


               ·            הפונקציה  put()  יכולה להחליף את המפעיל  <<  באופן הבא:

void main()

{

    char c;

    while (cin.get(c)) cout.put(c);

}

               ·            הגירסא של  get()  בעלת שלושה ארגומנטים קוראת לכל היותר  n  תווים לתוך מערך תווים. בסוף המחרוזת שנקראת למערך 

        התווים תמיד מושם התו  '\0',  לכן יקראו לכל היותר  n-1  תווים. הארגומנט השלישי הוא תו המציין את סוף המחרוזת הנקראת.

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

void f()

{

    char buff[100];

   

    cin >> buff; //dangerous: reads one word, overflow if too long.

    cin.get(buff, 100, '\n');//safe: reads a line not longer than 99.

    // ...

}

               ·            אם התו המסיים נמצא, הוא מושאר ברצף התווים להיות התו הבא לקריאה מהזרם. דבר זה מיועד לבדיקת גלישה, כלומר ישנם

        יותר תווים שהיו צריכים להקרא מאלו שנקראו בפועל:

void f()

{

    char buff[100];

    cin.get(buff, 100, '\n');//safe: reads a line not longer than 99.

    char c;

    if (cin.get(c) && c != '\n') {

        // input string longer than expected.

    }

}

               ·            בדיקת מאפיני קלט.

הספריה ctype.h מכילה, בין היתר, פונקציות לבדיקת תכונות תווים. להלן רשימת השימושיות ביותר:

int isalpha(char)               // 'a'..'z' 'A'..'Z'

int isupper(char)               // 'A'..'Z'

int islower(char)               // 'a'..'z'

int isdigit(char)                // '0'..'9'

int isxdigit(char)     // '0'..'9' 'a'..'f' 'A'..'F'

int isspace(char)               // ' ', '\t', return, newline, formfeed, ...

int iscntrl(char)                // control character (ASCII 0..31 and 127)

int ispunct(char)               // punctuation: none of the above

int isalnum(char)               // isalpha() OR isdigit()

int isprint(char)                // printable: ASCII ' '..'~'

int isgraph(char)               // isalpha() OR isdigit() OR ispunct()

int isascii(char c)    // { return 0 <= c && c <=127;}

 

כל הנ"ל, למעט isascii מיושמים ע"י בדיקה בטבלה ולכן יעילים יותר וניידים יותר מאשר בישום שונה. לדוגמא, הביטוי ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'), מלבד היותו מסורבל יותר בהשוואה ל- isalpha(c), יכול להיות שגוי כאשר הוא מחושב במערכת שבה ייצוג התווים הוא בשיטת  EBCDIC ולא ASCII, שכן בשיטת- EBCDIC אין רצף בתווי ה-  alphabet.

 

דוגמא: מימוש אפשרי לפונקציה  eatwhite() הקוראת תווי  whitespace   מהזרם:

istream& eatwhite(istream& is)

{

    char c;

    while(is.get(c))

    {   if (isspace(c) == 0)

        {   is.putback(c);

            break;

        }

    }

    return is;

}

               ·            הפונקציה  putback() מחזירה תו לזרם, כדי שיהיה התו הבא שיקרא מהזרם.

 

חזרה להתחלה


קבצים  Files

               ·            ה output-stream יכול להישלח למסך, למדפסת, לקובץ או ליעד אחר אבל שוב, מבחינת המתכנת הכתיבה היא לתוך

   זרם של בתים.

               ·            ה input-stream יכול לבוא מהמקלדת, מקובץ או ממקור אחר, לתוכנית שלנו אין הדבר משנה כי הטיפול דומה לכל קריאה

        מתוך זרם של בתים.

               ·            byte-stream  פירושו זרם של בתים (סדרה של בתים) כאשר:

               ·            בין המילים מפרידים white-space-characters .

               ·            כל שורה מסתיימת בתו '\n'.

               ·            כתיבה של תו נעשית למקום הבא בזרם התווים.

               ·            קריאה של תו קוראת את התו הבא מזרם התווים.

 

מהו קובץ?

               ·            בשפת  C++  המושג קובץ הוא סוג מיוחד של  stream  אשר המיוחד שבו הוא שהוא מגיע או נשלח לתקליט קשיח או 

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

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

               ·            הקבצים נשמרים בתקליט תחת שם מסויים. לדוגמא:  C:\PROGS\PROG1.CPP

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

עבודה עם קבצים

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

        שתאפשרנה לנו לעבוד עם קובץ.

               ·            בספריה  <fstream.h>  מוגדרים עצמים ופונקציות המאפשרים לבצע פעולות שונות על קבצים.

               ·            כאשר רוצים לעבוד עם קובץ עלינו לדעת מספר דברים:

  1.  שם הקובץ. לדוגמא:  C:\TEMP\DATA.TXT.

  2.  אופן השימוש בקובץ:  קריאה בלבד / כתיבה בלבד /  קריאה-כתיבה.

 

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

  1.  fstream    הגדרת קובץ (קובץ לקריאה/ וכתיבה).

  2.  ifstream  הגדרת קובץ קלט - קובץ שנרצה לקרוא ממנו.

  3.  ofstream  הגדרת קובץ פלט - קובץ שנרצה לכתוב לתוכו.

 

לדוגמא:

#include<fstream.h>

 

void f()

{

    fstream   rwFile; // file stream object for read/write.

    ifstream  rFile;  // file stream object for read only.

    ofstream  wFile;  // file stream object for write only.

}


פתיחת קובץ

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

               ·            יצירת הקשר מכונה פתיחת קובץ.

               ·            הפונקציה  open()   מבצעת פתיחת קובץ.

#include<fstream.h>

 

void f()

{

    fstream   rwFile; // file stream object for read/write.

    ifstream  rFile;  // file stream object for read only.

    ofstream  wFile;  // file stream object for write only.

 

    rwFile.open("C:\\temp\\rwfile.txt", ios::app);

    rFile.open("C:\\temp\\data.txt", ios::in);

    wFile.open("C:\\temp\\results.txt", ios::out);

}

הצורה הבללית היא:

fileName.open(char* fileName, int mode);

 

               ·            fileName   מחרוזת המציינת את שם הקובץ, בתקליט. 

               ·            mode    קבוע, המציין איזה סוג קובץ ברצוננו לפתוח. קיימת מחלקה ios , בה מוגדרים הקבועים הבאים:

    1. ios::in                         -  קובץ קריאה
    2. ios::out                      -  קובץ כתיבה.
    3. ios::app                      -  קובץ הנפתח לכתיבה בסופו.
    4. ios::ate          -  קובץ הנפתח לכתיבה בסופו, אבל ניתן לכתוב בכל מקום בקובץ.
    5. ios::noreplace           - אם הקובץ אינו קיים כבר, הפקודה תכשל.
    6. ios::trunc                   - אם הקובץ כבר קיים, הוא ימחק.
    7. ios::binary     - קובץ המכיל נתונים בצורה בינארית (ולא טקסט). חובה כאשר
                                         שומרים גושי זכרון לקובץ.

 

               ·            ניתן לציין  mode יותר מורכב, כלומר, קובץ שנפתח עם כמה מהתכונות שצוינו, באמצעות   המפעיל | (bitwise-OR). 

        לדוגמא: פתיחת קובץ לקריאה או כתיבה: ios::in | ios::out.

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

        בפקודה open). לרוב יש עבור הפרמטר  mode  ערכי ברירת מחדל מתאימים.

 

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

#include<fstream.h>

 

void f()

{

    fstream   rwFile("C:\\temp\\rwfile.txt");

    ifstream  rFile ("C:\\temp\\data.txt"); 

    ofstream  wFile ("C:\\temp\\results.txt"); 

}


שימוש בעצמי זרם עבור קבצים

·            לאחר שיצרנו עצם זרם מול קובץ, ניתן להשתמש בו כאילו הוא עצם קלט או פלט תקני (cout,cin).

לדוגמא:

#include<fstream.h>

#include<iomanip.h>

 

void f()

{

    ifstream  inf ("C:\\temp\\data.txt"); 

    ofstream  outf("C:\\temp\\results.txt"); 

    int n, t, sum = 0;

    inf >> n;

    for (int i = 0; i < n; i++)

    {

        int t;

        inf >> t;

        sum += t;

        outf << "partial sum" << i << " is:" << setw(4) << sum

             << endl

        ;

    }

}

 

content of files:    data.txt                 results.txt

Text Box: 3
12 14 21
Text Box: partial sum0 is:  12
partial sum1 is:  26
partial sum2 is:  47
 

 

 

 

 

 

 

 


סיום העבודה עם קובץ - סגירת הקובץ

               ·            כאשר גומרים לעבוד עם הקובץ, צריך לנתק את הקשר בין העצם לבין הקובץ על התקליט.

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

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

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

        שקבצים פתוחים יפגעו ואפילו יהרסו.

               ·            הפקודה  close()  סוגרת את הקובץ. לדוגמא:     inf.close();

               ·            אחרי שסגרנו קובץ ניתן להשתמש באותו עצם והפונקציה  open()  בכדי לפתוח מחדש אותו קובץ או קובץ אחר.

פעולות נוספות על קבצים

קריאת/כתיבת תו מקובץ:

#include <fstream.h>

void copyFiles(char* toFileName, char* fromFileName)

{

    ifstream in(fromFileName);

    ofstream out(toFileName);

    char c;

    while (in.get(c))  // reads a single character

        out.put(c);    // writes a single character.

 

}

               ·            הפונקציה  get(c)  קוראת תו בודד ומחזירה ערך אמת אם הקריאה הצליחה ואחרת שקר.

               ·            הפונקציה  put(c)  כותבת תו בודד.


עוד פעולות  (תקציר בלבד - לפני שימוש נא לפנות לספר או לעזרה)

·   קיימות פעולות נוספות לקריאה וכתיבה מ/לקבצים

·   read(unsigned char* s, int num)   קריאה של num תוים מתוך הקובץ לתוך המחרוזת s.

·   write(unsigned char* s, int num)   כתיבת  num תוים מתוך המחרוזת s לתוך הקובץ.

·   ignore(int num=1, int delim=EOF)  דילוג על num מקומות מקובץ הקלט. מפסיקים לדלג ברגע שנתקלנו בתו שערכו כמו delim.

·   פעולות נוספות: get() - עוד אופציות,  getline(),peek(), putback(), flush().

 

 

 

גישה ישירה למקום מסויים בקובץ

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

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

קיים מצביע קריאה - המקום בקובץ ממנו נקרא.

ומצביע כתיבה - המקום בקובץ בו נכתוב.

את מקום מצביע הקריאה/כתיבה בקובץ - כלומר, המרחק שלו מתחילת הקובץ - אפשר לשמור בתוך עצם מסוג streampos.

               ·            הפונקציה streampos tellg() מחזירה את מקום מצביע הקריאה.

               ·            הפונקציה streampos tellp()  מחזירה את מקום מצביע הכתיבה.

 

שינוי מקום בקובץ:

               ·            שינוי מקום מצביע הקריאה: seekg(streamoff offset, seek_dir origin)

               ·            שינוי מקום מצביע הכתיבה: seekp(streamoff offset, seek_dir origin)

offset - עצם מסוג streamoff, האומר בכמה בתים רוצים להזיז את המצביע. (מימוש  long)

origin - עצם מסוגseek_dir  שאומר מאיפה רוצים לבצע את הזזת מצביע הקריאה/הכתיבה (מימוש enum). הוא מכיל אחד מהערכים הבאים:

ios::beg - ההזזה יחסית לתחילת הקובץ.

ios::cur - ההזזה היחסית למקום הנוכחי בקובץ.

ios::end - ההזזה יחסית לסוף הקובץ.

פונקציות הבודקות את מצב הקובץ

good() - חזירה אמת אם הפעולה האחרונה הצליחה.

eof()    - מחזירה אמת אם הגענו לסוף הקובץ.

fail() - מחזירה אמת אם הפעולה הבאה על הקובץ צפויה להכשל (תקלה עם סיכוי להתאוששות).

bad()    - מחזירה אמת אם קרתה תקלה בקובץ (אין הבטחות שיש סיכוי להתאוששות).

 


חזרה להתחלה