FANDOM


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



Bulbgraph

כדאי לדעת:

קטעי הקוד שבפרק זה משתמשים בספרייה הסטנדרטית. נדון בספריות באופן מעמיק יותר כאן. לעת עתה, פשוט יש לזכור לרשום בראשי הקבצים המשתמשים בקטעי הקוד שבפרק זה
#include <stdio.h>


תו סיום-הקובץ EOFעריכה

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

המבנה FILE והעבודה אתועריכה

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

  1. משתמשים בפונקציית ספריה כדי לקבל מצביע למבנה זה. נראה זאת בפתיחת קובץ.
  2. משתמשים בפונקציות הספריה כדי לבצע פעולות שונות בקובץ. אחד הארגומנטים שמקבלת כל פונקציה היא מצביע לFILE, ומעבירים לפונקציה את המצביע שקבלנו.
  3. בסיום השימוש בקובץ, משתמשים בפונקציית ספרייה כדי להודיע שסיימנו להשתמש בו, וגם כאן מעבירים לפונקציה את המצביע שקיבלנו. נראה זאת בסגירת קובץ.

פתיחת קובץעריכה

הקריאה לfopen והערך המוחזרעריכה

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

כדי לפתוח את הקובץ "try.txt", לדוגמה, אפשר לבצע זאת:

FILE *f = fopen("try.txt" , "rt");
if(!f)
{
  /* Handle case where couldn't open file. */
}

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

מחרוזת סוג הפתיחהעריכה

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

מוד הפתיחה
תווים משמעות
r פתיחת קובץ קיים לקריאה. אם לא קיים קובץ בשם האמור, הפתיחה תכשל.
w פתיחת קובץ חדש לכתיבה. אם קיים כבר קובץ בשם האמור, תוכנו ימחק.
a פתיחת קובץ קיים לכתיבת נתונים בסופו. התוכן החדש ידרוס את תו ה-EOF, וייכתב אחריו. אם הקובץ לא קיים, הוא יווצר תחילה.
r+ פתיחת קובץ קיים לקריאה וכתיבה. אם לא קיים קובץ בשם האמור, הפתיחה תכשל.
w+ פתיחת קובץ חדש לקריאה וכתיבה. אם קיים כבר קובץ בשם האמור, תוכנו ימחק.
a+ פתיחת קובץ קיים לכתיבת נתונים בסופו. תו סיום הקובץ יוזז לסוף הנתונים החדשים שנכתוב, כך שבהצגת תוכן הקובץ, יוצג כל התוכן. אם הקובץ לא קיים, הוא יווצר תחילה.
תוכן הקובץ
תווים משמעות
t קובץ טקסט
b קובץ בינרי

סגירת קובץ עריכה

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

הפונקציה fcloseעריכה

הפונקציה fclose סוגרת קובץ שנפתח על ידי fopen. משתמשים בה בצורה:

fclose(<f>);

כאשר f הוא מצביע לFILE שהוחזר מקריאה מוצלחת מfopen.

חשיבות סגירת קבציםעריכה

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


Achtung

שימו לב:

ריבוי קבצים פתוחים עלול לפגוע בביצועי המערכת.


פלטעריכה

הפונקציה fprintfעריכה

הפונקציה fprintf דומה מאד לפונקציה printf (שכבר ראינו בפלט וקלט):

fprintf(f, "This line will be written to the file.\n");


יש לשים לב לשינויים הבאים:

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

הפונקציה מחזירה מספר שלילי במקרה כישלון פלט. להלן דוגמה לבדיקה:

if( fprintf("Hello world") < 0)
  ... /* Handle error. */

להלן דוגמה לשימוש בfprintf:

#include <stdio.h>
 
 
int main()
{
  FILE *const f = fopen("new_file.txt", "wt");
 
  if(!f) 
  {
    printf("Error: could not open file!\n");
 
    return -1;
  }
 
  fprintf(f, "This line will be written to the file.\n");
  fprintf(f, "Here is another line: %d + %d = %d", 2, 2, 2 + 2);
 
  fclose(f);
 
  return 0;
}

השורות:

FILE *const f = fopen("new_file.txt", "wt");
 
if( !f ) 
{
  printf("Error: could not open file!\n");
 
  return -1;
}

מייצרות קובץ בשם "new_file.txt", ופותחות אותו לכתיבה כקובץ טקסט, בודקות האם הפעולה הצליחה, ומטפלות במצב אם לא.

השורות:

fprintf(f, "This line will be written to the file.\n");
fprintf(f, "Here is another line: %d + %d = %d", 2, 2, 2 + 2);

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

השורות:

  fclose(f);
 
  return 0;
}

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


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

עוד פונקציותעריכה

הספריה הסטנדרטית כוללת עוד פונקציות פלט לקבצים, לדוגמה fputs וfwrite.

קלטעריכה

הפונקציה fscanfעריכה

הפונקציה fscanf דומה מאד לפונקציה scanf (שכבר ראינו בפלט וקלט):

fscanf(f, "%d", &count);

יש לשים לב למעט השינויים הבאים:

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


נניח שfscanf ביקשה לקרוא ל משתנים. אז הקריאה מוצלחת אם הפונקציה מחזירה n. להלן דוגמה לבדיקה:

int d;
char c;
 
if( fscanf("%d %c", &d, &c) != 2)
  ... /* Handle error. */


Achtung

שימו לב:

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


הפונקציה fgetsעריכה

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

char a[50];
 
fgets(a, 49, f);

הקריאה:

fgets(a, 49, stdin);

תקלוט עד 49 תווים מתוך קובץ. אם ב49 התווים הראשונים יש מעבר לשורה חדשה (על ידי Enter), ייקלטו רק התווים עד שם. הארגומנט השלישי, f, הוא מצביע לFILE שממנו יקראו התווים.


Bulbgraph

כדאי לדעת:

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


עוד פונקציותעריכה

הספריה הסטנדרטית כוללת עוד פונקציות קלט מקבצים, לדוגמה fread.

זרמים סטנדרטייםעריכה

הספריה הסטנדרטית מגדירה שלושה מצביעים ל"קבצים" שלמעשה אינם לרוב קבצים אמיתיים, אלא צורות תקשורת עם המשתמש:

  • stdin הוא מצביע ל"קובץ" שהוא למעשה המקלדת.
  • stdout הוא מצביע ל"קובץ" שהוא למעש המסך.
  • stderr הוא מצביע ל"קובץ" שהוא למעשה גם כן המסך, אלא שהוא משמש לפלט שגיאות.

אפשר להשתמש במצביעים אלה בפונקציות פלט הקבצים ובפונקציות קלט הקבצים. לדוגמה, היינו יכולים לכתוב את שלום עולם! כך:

#include <stdio.h>
 
int main()
{
  fprintf(stdout, "Hello world\n");
  return 0;
}


Achtung

שימו לב:

אין לנסות לפתוח "קבצים" אלה בעזרת fopen או לנסות לסוגרם בעזרת fclose.


שינוי ומציאת המיקום בקובץעריכה

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


הפונקציה fseekעריכה

זזים ממקום למקום, על ידי fseek, בצורה הזאת:

fseek(<f>, <offset>, <origin>);

כאשר:

  • f הוא מצביע לFILE.
  • offset הוא מספר הבתים שיש לזוז (מספר זה יכול להיות גם שלילי).
  • origin הוא מוצא התזוזה, והוא יכול להיות אחת משלוש האפשרויות הבאות:
    • SEEK_CUR - המיקום הנוכחי
    • SEEK_SET - תחילת הקובץ
    • SEEK_END - סוף הקובץ

לדוגמה:

fseek( file, 2L, SEEK_CUR );

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



Achtung

שימו לב:

ההזזות השימושיות היחידות שבטוחות לביצוע במצב טקסט הן קפיצה לתחילת הקובץ או לסופו, כלומר:
fseek( file, 0L , SEEK_SET );
fseek( file, 0L , SEEK_END );


הפונקציה ftellעריכה

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

long pos = ftell( file );

לאחר קריאה זו, pos יכיל את מספר הבתים מתחילת הקובץ ועד המיקום הנוכחי.


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


הפרק הקודם:
איגודים
פלט וקלט קבצים
תרגילים
הפרק הבא:
הקדם מעבד

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.