Download presentation
Presentation is loading. Please wait.
1
קבצים קרן כליף
2
ביחידה זו נלמד: מוטיבציה לעבודה עם קבצים סוגי קבצים:
בינאריים טקסט פעולות על קבצים (עבור שני סוגי הקבצים): פתיחת קובץ קריאה מקובץ כתיבה לקובץ סגירת קובץ פעולות נוספות: fseek, ftell, rewind, ferror, fflush, feof
3
קבצים - מוטיבציה כאשר אנחנו כותבים תוכנה, המידע אשר אנחנו מכניסים בכל הרצה הולך לאיבוד עם סיומה, מאחר והתוכנה רצה בזיכרון ה- RAM של המחשב היינו רוצים לשמור את המידע בין ההרצות בזיכרון הקבוע (Hard Disk) כדי: ליצור תוכנה בעלת משמעות ורצף להקל עלינו בעת בדיקות התוכנה קריאת נתונים מקובץ מוכן מראש ולא מהמשתמש שמירת נתונים לשימוש ע"י תוכניות אחרות ניתן לשמור את המידע בכמה אופנים שונים: DB (לא יילמד בקורס זה) קבצים
4
עבודה כללית עם קבצים - מוטיבציה
יתכן ותהייה לנו תוכנית שנרצה לשמור את הפלט שלה לקובץ יתכן ותהייה לנו תוכנית שנרצה שהקלט שלה יהיה מקובץ, ולא מהמקלדת דוגמא: קריאת אוסף מספרים מקובץ בפורמט ידוע מראש והצגת סכום המספרים כתיבת תוכנית המכינה דו"ח כלשהו ושומרת את הדוח בקובץ, בנוסף להצגתו על המסך
5
סוגי קבצים קובץ טקסט: כתוב בשפה אותה אנו יכולים לקרוא ולהבין
קובץ בינארי: לא ניתן להבין את התוכן
6
מבנה עבודה כללי עם קבצים
קובץ הוא משתנה מטיפוס *FILE ומוגדר ב- stdio.h בתחילת העבודה יש לפתוח קובץ לקריאה/לכתיבה תוך ציון האם זהו קובץ טקסט או בינארי יש לבדוק האם פתיחה הצליחה לבסוף יש לסגור את הקובץ void main() { FILE* f = fopen(<file name>, <open parameters>); if (f == NULL) printf("Failed opening the file. Exiting!\n"); return; } // here some operation with the file.. fclose(f);
7
פתיחת קובץ – פרמטרים לסוג הפתיחה
FILE* fopen(char* fileName, char* mode); פתיחת קובץ טקסט לקריאה: “r” פתיחת קובץ טקסט לכתיבה: “w” - במידה ויש נתונים בקובץ הם ידרסו “a” – כותב לסוף קובץ (כלומר לא דורס את המידע, אם קיים). לא מאפשר כתיבה לתחילת הקובץ! פתיחת קובץ טקסט לקריאה ולכתיבה: “r+” – הקובץ חייב להיות קיים, יתקבל NULL אם לא “w+” – אם הקובץ קיים, דורס אותו “a+” – אם הקובץ קיים כותב לסופו, אחרת יוצר קובץ חדש. לא מאפשר כתיבה לתחילת הקובץ! כדי לפתוח את הקובץ כבינארי נוסיף b בסוף הפרמטר לפתיחה. למשל: “rb”, “wb” וכו'. ברירת המחדל היא קובץ טקסט. ניתן ב- mode הפתיחה לציין t, עבור קובץ טקסט. למשל: “wt”
8
פתיחת קובץ – סיבות לכשלון
קובץ המוגדר לקריאה בלבד שמנסים לפתוח אותו לכתיבה פתיחה ע"י "r" קובץ שאינו קיים
9
int fclose(FILE* file);
סגירת קובץ int fclose(FILE* file); מקבלת מצביע לקובץ ומחזירה 0 אם הצליחה לסגור אותו, אחרת תחזיר 1- (הקבוע EOF) תכשל למשל כאשר מנסים לסגור קובץ שאינו פתוח int fcloseall(); סוגרת את כל הקבצים שפתחנו ומחזירה את מספר הקבצים שסגרה
10
פקודות הכתיבה לקובץ טקסט הן כמו הפקודות לכתיבה למסך, פרט לכך ש:
פקודות הכתיבה לקובץ טקסט הן כמו הפקודות לכתיבה למסך, פרט לכך ש: שמן מתחיל עם f הן מקבלות פרמטר נוסף שהוא מצביע לקובץ אליו רוצים לכתוב int fprintf(FILE* , char*, ... ); int fputs(char*, FILE*); int fputc(char, FILE*);
11
כתיבה לקובץ טקסט – דוגמא (1)
#include <stdio.h> void main() { FILE* f = fopen("myFile.txt", "w"); int res; if (f == NULL) printf("Failed opening the file. Exiting!\n"); return; } fprintf(f, "%s %d %lf\n", "KerenK", 28, 99.8); fputs("Hello World!", f); fputc('A', f); fclose(f); דריסת הקובץ אם קיים
12
כתיבה לקובץ טקסט – דוגמא (2)
#include <stdio.h> void main() { FILE* f = fopen("myFile.txt", "w"); int res; if (f == NULL) printf("Failed opening the file. Exiting!\n"); return; } fputs("Hello World!\n", f); fclose(f); f = fopen("myFile.txt", "a"); fputs("And Good Morning!\n", f); פתיחת הקובץ וכתיבה לסופו
13
כתיבה לקובץ טקסט – דוגמא (3)
#include <stdio.h> void main() { FILE* f = fopen("myFile.txt", "w"); int res; if (f == NULL) printf("Failed opening the file. Exiting!\n"); return; } fputs("Hello World!\n", f); fclose(f); f = fopen("myFile.txt", “w"); fputs("And Good Morning!\n", f); דריסת הקובץ הקודם...
14
מקבלות גם את כמות התווים לקריאה. קוראת עד ‘\n’ או עד n-1 תווים
קריאה מקובץ טקסט פקודות הקריאה לקובץ טקסט הן כמו הפקודות הקריאה למסך, פרט לכך ש: שמן מתחיל עם f הן מקבלות פרמטר נוסף שהוא מצביע לקובץ אליו רוצים לכתוב int fscanf(FILE* , char*, ... ); char* fgets(char*, int n, FILE*); מחזירה את המחרוזת שקראה או NULL אם לא הצליחה (למשל הקובץ נגמר) int fgetc(FILE*); מחזירה את ערך האסקיי של התו או את הקבוע EOF (שערכו 1-) אם לא הצליחה (למשל הקובץ נגמר) מקבלות גם את כמות התווים לקריאה. קוראת עד ‘\n’ או עד n-1 תווים
15
שמירה וקריאה מקובץ - כללי
כאשר נשמור מידע לקובץ, אנו בוחרים לשמור את המידע בסדר מסוים צריכה להיות התאמה בין סדר כתיבת הנתונים לקובץ לסדר קריאת הנתונים מהקובץ למשל: אם כתבתי מידע על סטודנט בסדר הבא: שם , ת.ז. וגיל, גם סדר קריאת הנתונים יהיה זהה כלומר, צריכה להיות הסכמה וידיעה בין מי שכותב לקובץ ומי שקורא ממנו לגבי סדר הנתונים בקובץ
16
קריאה מקובץ טקסט – דוגמא
#define SIZE 20 void main() { char str[]="Hi", sentence[]="Hello World!", str2[SIZE], sentence2[SIZE]; int num1=6, num2=0; float f1=4.5, f2=0; FILE* f = fopen("myFile.txt", "w"); // check if open file succeeded.. fputs(sentence, f); fprintf(f, "\n%d %f %s\n", num1, f1, str); fclose(f); printf("Before reading from file:\nnum2=%d f2=%f str=|%s| sentence2=|%s|\n", num2, f2, str2, sentence2); f = fopen("myFile.txt", "r"); fgets(sentence2, SIZE, f); fscanf(f, "%d %f %s", &num2, &f2, str2); printf("\nAfter reading from file:\nnum2=%d f2=%f str=|%s| sentence2=|%s|\n", num2, f2, str2, sentence2); }
17
int feof (FILE * stream);
18
דוגמא – העתקת קובץ fcloseall(); // returns 2 since closed 2 files
void main() { char ch; FILE* fSource, *fDest; fSource = fopen("example.txt", "r"); // check if open file succeeded.. fDest = fopen("exampleCopy.txt", "w"); ch = fgetc(fSource); while (!feof(fSource)) // OR: (ch != EOF) fputc(ch, fDest); } fclose(fSource); // returns 0 since close file succeed fclose(fDest); // returns 0 since close file succeed fcloseall(); // returns 2 since closed 2 files
19
קריאת מספרים מקובץ וחישוב הממוצע
#include <stdio.h> void main() { FILE* f; int num, sum=0, counter=0, rc; f = fopen("numbers.txt", "r"); // check if open succeed... rc = fscanf(f, "%d", &num); while (rc != EOF) //OR: (!feof(f)) printf("The read numbers is %d\n", num); sum += num; counter++; } fclose(f); printf("The average is %f\n", (float)sum/counter);
20
שמירת וטעינת רשומות לקובץ טקסט
כאשר כותבים רשומה לתוך קובץ טקסט, יש לכתוב שדה-שדה כאשר קוראים רשומה מקובץ טקסט, יש לקרוא שדה-שדה
21
שמירת וטעינת רשומות מקובץ טקסט - דוגמא
#define SIZE 20 struct Person { char name[SIZE]; long id; float age; } typedef person_t; void main() person_t p1={"momo", 1111, 23.5}, p2 = {"gogo", 2222, 24.8}, p3, p4; FILE* f = fopen("persons.txt", "w"); fprintf(f, "%s %ld %.2f\n", p1.name, p1.id, p1.age); fprintf(f, "%s %ld %.2f\n", p2.name, p2.id, p2.age); fclose(f); f = fopen("persons.txt", "r"); fscanf(f, "%s %ld %f\n", p3.name, &p3.id, &p3.age); fscanf(f, "%s %ld %f\n", p4.name, &p4.id, &p4.age); printf("p3: name: %s\t id: %ld\t age: %.2f\n", p3.name, p3.id, p3.age); printf("p4: name: %s\t id: %ld\t age: %.2f\n", p4.name, p4.id, p4.age); }
22
שמירה וטעינת מערך של רשומות מקובץ טקסט
כאשר כותבים מערך לקובץ, השדה הראשון צריך להיות מספר הרשומות שאנו כותבים, כדי שקורא הקובץ ידע כמה רשומות יש בתוכו
23
שמירה וטעינה - מערך רשומות (1)
struct Person { char name[SIZE]; long id; float age; } typedef person_t; void main() FILE* f; person_t* personsSource, *personsDest; int sizeSource, sizeDest, i; printf("How many persons? "); scanf("%d", &sizeSource); // allocating the persons array personsSource = (person_t*)malloc(sizeSource*sizeof(person_t)); // reading persons.. for (i=0 ; i < sizeSource ; i++) printf("Enter name, id and age of person #%d: ", i+1); scanf("%s %ld %f", personsSource[i].name, &personsSource[i].id, &personsSource[i].age); }
24
f = fopen("persons.txt", "w");
fprintf(f, "%d\n", sizeSource); // writing the size to the file for (i=0 ; i < sizeSource ; i++) // writing each person to the file fprintf(f, "%s %ld %f\n", personsSource[i].name, personsSource[i].id, personsSource[i].age); fclose(f); free(personsSource); // don’t forget to free the array!! f = fopen("persons.txt", "r"); fscanf(f, "%d\n", &sizeDest); // reading the size from the file // allocating the new array personsDest = (person_t*)malloc(sizeDest*sizeof(person_t)); // reading each person from the file for (i=0 ; i < sizeDest ; i++) fscanf(f, "%s %ld %f\n", personsDest[i].name, &personsDest[i].id, &personsDest[i].age); printf("There are %d persons in the file:\n", sizeDest); printf("Person #%d: Name=%s\t Id=%ld\t Age=%f\n", i+1, personsDest[i].name, personsDest[i].id, personsDest[i].age); free(personsDest); // don’t forget to free the array!! }
25
מחזירה את כמות האיברים שכתבה
כתיבה לקובץ בינארי פקודת הכתיבה לקובץ בינארי: int fwrite(const void * ptr, // address of variable to write int size, // size of type int count, // number of elements FILE * stream (; // pointer to the file מחזירה את כמות האיברים שכתבה כאשר כותבים לקובץ בינארי ניתן לכתוב בלוק של מידע למשל: מערך או רשומה בפעולת כתיבה בודדת יש להיזהר מכתיבת פוינטרים לקובץ!
26
קריאה מקובץ בינארי פקודת הקריאה מקובץ בינארי: int fread(void* ptr, // address of variable to read into int size, // size of type int count, // number of elements FILE* stream (; // pointer to the file מחזירה את כמות האיברים שקראה כאשר קוראים מקובץ בינארי ניתן לקרוא בלוק של מידע למשל: מערך או רשומה בפעולת קריאה בודדת
27
שמירת וטעינת רשומות מקובץ בינארי - דוגמא
#define SIZE 20 struct Person { char name[SIZE]; long id; float age; } typedef person_t; void main() person_t p1={"momo", 1111, 23.5}, p2 = {"gogo", 2222, 24.8}, p3, p4; FILE* f = fopen("persons.bin", "wb"); fwrite(&p1, sizeof(person_t), 1, f); fwrite(&p2, sizeof(person_t), 1, f); fclose(f); f = fopen("persons.bin", "rb"); fread(&p3, sizeof(person_t), 1, f); fread(&p4, sizeof(person_t), 1, f); printf("p3: name: %s\t id: %ld\t age: %.2f\n", p3.name, p3.id, p3.age); printf("p4: name: %s\t id: %ld\t age: %.2f\n", p4.name, p4.id, p4.age); } ניתן לקרוא ולכתוב רשומה בפעולה אחת!
28
שמירה וטעינה מערך רשומות מקובץ בינארי (1)
#define SIZE 20 struct Person { char name[SIZE]; long id; float age; } typedef person_t; void main() FILE* f; person_t* personsSource, *personsDest; int sizeSource, sizeDest, i; printf("How many persons? "); scanf("%d", &sizeSource); // allocating the persons array personsSource = (person_t*)malloc(sizeSource*sizeof(person_t)); for (i=0 ; i < sizeSource ; i++) // reading persons.. printf("Enter name, id and age of person #%d: ", i+1); scanf("%s %ld %f", personsSource[i].name, &personsSource[i].id, &personsSource[i].age); }
29
f = fopen("persons.bin", "wb");
fwrite(&sizeSource, sizeof(int), 1, f); // writing the size to the file // writing all persons to the file fwrite(personsSource, sizeof(person_t), sizeSource, f); fclose(f); free(personsSource); // don’t forget to free the array!! f = fopen("persons.bin", "rb"); // reading the size from the file fread(&sizeDest, sizeof(int), 1, f); // allocating the new array personsDest = (person_t*)malloc(sizeDest*sizeof(person_t)); // reading all persons from the file fread(personsDest, sizeof(person_t), sizeDest, f); printf("There are %d persons in the file:\n", sizeDest); for (i=0 ; i < sizeDest ; i++) printf("Person #%d: Name=%s\t Id=%ld\t Age=%f\n", i+1, personsDest[i].name, personsDest[i].id, personsDest[i].age); // don’t forget to free the array!! free(personsDest); }
30
כתיבת רשומות המכילות מצביעים
יש לשים לב לא לכתוב מצביעים לתוך קובץ, שכן אין הבטחה שבפעם הבאה שהתוכנית תרוץ יהיו ערכים בכתובות הנוכחיות שאנו שומרים לכן, כאשר יש משתנה שהוא כתובת יש להקפיד לרשום את ערכו לקובץ נשים לב: לא נוכל להשתמש בשיטה של לרשום רשומה ע"י fwrite, אלא נהיה חייבים לכתוב את הרשומה לקובץ שדה-שדה בד"כ אם המצביע הוא למערך, נרשום כשדה נוסף את כמות האלמנטים במערך, ורק אח"כ את איבריו (כנ"ל עבור מחרוזת).
31
דוגמא – שמירה וטעינה של רשומה עם מצביעים
void main() { student_t stud1 = {"yoyo", 91.8}, stud2; FILE* f = fopen("students.bin", "wb"); int len1, len2; // check open succeed... len1 = strlen(stud1.name)+1; fwrite(&len1, sizeof(int), 1, f); fwrite(stud1.name, sizeof(char), len1, f); fwrite(&stud1.average, sizeof(float), 1, f); fclose(f); f = fopen("students.bin", "rb"); fread(&len2, sizeof(int), 1, f); stud2.name = (char*)malloc(len2*sizeof(char)); fread(stud2.name, sizeof(char), len2, f); fread(&stud2.average, sizeof(float), 1, f); printf("stud2: name=%s, average=%.2f\n", stud2.name, stud2.average); free(stud2.name); } #include <stdio.h> #include <string.h> #include <stdlib.h> struct Student { char* name; float average; } typedef student_t;
32
פקודה fseek מאפשר לטייל בקובץ בלי לקרוא חלק משדותיו
int fseek(FILE* f, // the file long int offset, // how much int origin (; // from where originיקבל אחד מהערכים הבאים: SEEK_SET – לזוז מתחילת הקובץ SEEK_END – לזוז לסוף הקובץ SEEK_CUR – לזוז מהמיקום הנוכחי הפונקציה תחזיר 0 אם הצליחה לזוז כמתבקש לידע כללי: יש מערכות הפעלה בהן fseek לא עובדת טוב על קבצי טקסט
33
fseek - דוגמא #include <stdio.h> int main () { FILE * f;
f = fopen("myfile.txt" , "w"); // check if open succeed fputs("This is an apple" , f); fseek (f , 9 , SEEK_SET); fputs(" sam" , f); fclose(f); }
34
fseek – דוגמא – החבר הכי טוב
#define MAX_LEN 20 typedef struct Friend } char name[MAX_LEN]; int numOfPresentsBoughtMe; } Friend; void sortFriendByPresents(Friend friends[], int size) Friend temp; int i, j; for (i=0 ; i < size ; i++) for (j=i+1 ; j < size ; j++) if (friends[i].numOfPresentsBoughtMe > friends[j].numOfPresentsBoughtMe) temp = friends[i]; friends[i] = friends[j]; friends[j] = temp; {
35
fseek – דוגמא – החבר הכי טוב (2)
void main() } FILE* f; Friend bestFriend; Friend myFriends[] = { {"momo", 5}, {"gogo", 2}, {"yoyo", 7} }; int numOfFriends = sizeof(myFriends) / sizeof(myFriends[0]); sortFriendByPresents(myFriends, numOfFriends); f = fopen("myFriends.bin", "wb"); // check open file succeed... fwrite(&numOfFriends, sizeof(int), 1, f); fwrite(myFriends, sizeof(Friend), numOfFriends, f); fclose(f); numOfFriends = 0; // just reset to see correct value is read from file.. // get the friend that bought me most presents f = fopen("myFriends.bin", "rb"); // check open file succeed... fread(&numOfFriends, sizeof(int), 1, f); fseek(f, sizeof(Friend)*(numOfFriends-1), SEEK_CUR); //OR: fseek(f, sizeof(Friend)*-1, SEEK_END); fread(&bestFriend, sizeof(Friend), 1, f); printf("The friend who bought me most presents: %s\n", bestFriend.name); {
36
הפקודה ftell מחזירה את מרחק הסמן מתחילת הקובץ long ftell (FILE * f);
דוגמא: קריאת גודל של קובץ #include <stdio.h> int main () { FILE* f; long size; f = fopen ("myFile.txt", "r"); // check if open succeed fseek (f, 0, SEEK_END); size = ftell(f); fclose (f); printf ("Size of myfile.txt: %ld bytes.\n",size); }
37
הפקודה rewind מחזירה את הסמן לתחילת הקובץ: void rewind(FILE* f);
דוגמא: קריאת וכתיבת כל ה- ABC int main () { int n; FILE *f; char buffer [27]; f = fopen ("allLetters.txt","w+"); // check if open succeed for ( n='A' ; n<='Z' ; n++) fputc ( n, f); rewind (f); fscanf(f, "%s", buffer); fclose (f); buffer[26]='\0'; puts (buffer); }
38
הפקודה fflush int fflush(FILE* f) int fflush()
מרוקנת את ה- buffer של הקובץ. בדיוק כמו שמנקים את ה- buffer מהמקלדת ע"י fflsh(stdin). מחזירה 0 אם הצליחה. int fflush() מרוקנת את ה- buffer'ים של כל ה- stream הפתוחים (קבצים, stdin וכד'). מחזירה 0 אם הצליחה.
39
הפקודה ferror פקודה זו מחזירה 0 במידה והפעולות שבוצעו על הקובץ תקינות
דוגמא: כאשר ננסה לכתוב לקובץ שנפתח לקריאה בלבד void main() { FILE* f = fopen("myfile.txt","r"); if (f == NULL) printf("Error opening file\n"); return; } fputc('x', f); if (ferror(f)) printf ("Error Writing to myfile.txt\n"); fclose(f);
40
דוגמא: ניהול קורסים וסטודנטים במכללה
דגשים לתוכנית: שימוש בקבועים פונקציות יעודיות להדפסה ולקבלת קלט מודולריות חלוקה לקבצים יצירת פונקציה עבור לוגיקה ספציפית, עבור תחזוקה עתידית למשל: getDepartmentCodeFromCourseCode
41
קובץ אינדקסים - מוטיבציה
בהינתן קובץ טקסט עם שורות (ניתן להניח שאורך כל שורה הוא מקסימום 255 תווים, אבל לא בהכרח) נרצה לקרוא תו ספציפי בשורה מסוימת הפתרון: נקרא שורה-שורה עד השורה המבוקשת, ובתוכה נזוז למיקום הרצוי דוגמא: בהינתן הקובץ הבא, נרצה להגיע לתו ה- 7 בשורה 4
42
הקוד פעולת הקריאה מקובץ היא פעולה יקרה ולכן נרצה מנגנון אחר שיחסוך זאת. כלומר, מנגנון שונה להגעה ישירה לשורה המבוקשת. void main() { int line, col, i; char text[256], ch; FILE* f = fopen("test.txt", "r"); printf("Enter line and col --> "); scanf("%d%d", &line, &col); for (i=1 ; i < line ; i++) fgets(text, 256, f); fseek(f, col-1, SEEK_CUR); ch = fgetc(f); printf("The char is '%c'\n", ch); fclose(f); } דילוג על השורות הראשונות. לא ניתן לדלג באמצעות fseek כי אורך השורות שונה. כאשר הסמן נמצא בתחילת השורה המבוקשת, נקפוץ ישירות למיקום התו אותו רוצים לקרוא.
43
קובץ אינדקסים - בפתרון כאשר רוצים לבצע קריאות רבות ונקודתיות מקובץ בעל אורך שורות שונה שאינו משתנה, נשתמש במנגנון הנקרא "קובץ אינדקסים" קובץ זה יכיל מספרים, כאשר המספר ה-i הוא מיקום התו הראשון בשורה ה- i בקובץ דוגמא: שימושים: למשל עבור ספר טלפונים (נתוניו קבועים), נרצה לקבל נתונים של רשומה אחת כל שינוי בקובץ המקורי יגרור שינוי בקובץ האינדקס
44
יצירת קובץ אינדקס פתיחת קובץ הטקסט לקריאה, וקובץ האינדקס בינארי לכתיבה
void main(int argc, char* argv[]) { char indexFileName[128], line[256]; FILE *textFile, *indexFile; int currentIndex, numOfChars; createIndexFileName(argv[1], indexFileName); textFile = fopen(argv[1], "r"); indexFile = fopen(indexFileName, "wb"); fseek(textFile, 0, SEEK_END); numOfChars = ftell(textFile); fseek(textFile, 0, SEEK_SET); currentIndex = 0; while (currentIndex < numOfChars) fwrite(¤tIndex, sizeof(int), 1, indexFile); fgets(line, 256, textFile); currentIndex = ftell(textFile); } fclose(textFile); fclose(indexFile); פתיחת קובץ הטקסט לקריאה, וקובץ האינדקס בינארי לכתיבה נמצא את כמות התווים בקובץ הטקסט נמצא את מיקום הסמן בתחילת כל שורה, ונכתוב ערך זה לקובץ האינדקסים קובץ האינדקס חייב להיות בינארי כדי שבקריאה נוכל לדלג כל פעם על int שלם
45
יצירת שם קובץ האינדקס פונקציה זו יוצרת את שם קובץ האינדקס כך:
עבור קובץ <file name>.txt שם קובץ האינדקס יהיה: <file name>_index.bin דוגמא: עבור test.txt שם ובץ האינדקס יהיה test_index.bin void createIndexFileName(const char* origName, char indexName[]) { strcpy(indexName, origName); strtok(indexName, "."); strcat(indexName, "_index.bin"); }
46
שימוש בקובץ אינדקס void main(int argc, char* argv[]) {
FILE *textFile, *indexFile; int col, row, lineStartIndex; char ch; textFile = fopen(argv[1], "r"); indexFile = fopen(argv[2], "rb"); printf("Enter row and col --> "); scanf("%d%d", &row, &col); fseek(indexFile, (row-1)*sizeof(int), SEEK_SET); fread(&lineStartIndex, sizeof(int), 1, indexFile); fseek(textFile, lineStartIndex+col-1, SEEK_SET); fscanf(textFile, "%c", &ch); printf("The char is %c\n", ch); fclose(textFile); fclose(indexFile); } פתיחת קובץ הטקסט וקובץ האינדקס הבינארי לקריאה קריאה מקובץ האינדקס את מיקום תחילת השורה הזזת הסמן בקובץ הטקסט למיקום המבוקש וקריאה
47
דוגמאת סיכום: קבצים, סיביות, variadic functions
כתוב פונקציה המקבלת שם של קובץ בינארי וכמות כלשהי של מספרים, שנתון שסכומם הוא 8 (המספר האחרון יהיה 0, ליצוג סיום הפרמטרים) כל מספר מייצג כמות סיביות המייצגות מספר. יש לקרוא את הקובץ הבינארי ולהציג את המספרים המקודדים בתוכו. למשל, עבור המספרים 4,1,3 והבתים הבאים שנקראו מהזכרון (abc): יודפסו למסך המספרים הבאים:
48
#include <stdio.h>
#include <stdlib.h> #include <string.h> #include <stdarg.h> unsigned char createMask(int high, int low); int getSubNumber(char ch, unsigned char mask, int high, int low); void readNumbers(const char* fileName, ...); void main() { char str[] = "abc"; // a: b: c: FILE* f = fopen("test.bin", "wb"); fwrite(str, sizeof(char), strlen(str), f); fclose(f); readNumbers("test.bin", 4, 1, 3, 0);
49
מוזמנים לקרוא את ההסבר לפונקציה זו בדפים שבאתר!
/* This function receives higher and lower bounds of bit indexes, and creates a mask with 1 in this range, and 0 in all other places. I.E: high=5, low=3, the mask char would be: */ unsigned char createMask(int high, int low) { return ( 1 << ( high + 1 ) ) - ( 1 << low ); 6 >> 3 >> 56=
50
void readNumbers(const char* fileName, ...)
{ FILE* f; va_list numbers; int highBit, lowBit, i, numOfNumbers=0, arr[8]; unsigned char ch; unsigned char* masks; f = fopen(fileName, "rb"); if (f == NULL) exit(1); // get the numbers va_start(numbers, fileName); arr[numOfNumbers] = va_arg(numbers, int); while (arr[numOfNumbers] != 0) } numOfNumbers++; // allocate the masks array masks = (char*)malloc(numOfNumbers*sizeof(unsigned char));
51
// creates the masks highBit=7; for (i=0 ; i < numOfNumbers ; i++) } lowBit = highBit - arr[i] + 1; masks[i] = createMask(highBit, lowBit); highBit = lowBit - 1; while (1) fread(&ch, sizeof(char), 1, f); if (feof(f)) break; printf("From char '%c' --> ", ch); { printf("%d ", ((ch & masks[i]) >> lowBit)); printf("\n"); fclose(f); free(masks);
52
דוגמא: יצירת קובץ בינארי המכיל קידוד תמונה
יש לייצר קובץ בינארי המכיל יצוג של תמונה. תמונה מורכבת מ- M*N פיקסלים, כך שלכל פיקסל יש צבע (יש 16 צבעים אפשריים). יש לכתוב לקובץ את מימדי התמונה ואח"כ את כל הפיקסלים לפי הסדר: הפיקסלים מהשורה הראשונה, השניה וכו'. על מנת לשמור כל צבע, ניתן להסתפק ב- 4 סיביות בכל byte ניתן לשמור נתונים עבור 2 פיקסלים תמונה עם M*N פיקסלים תשמר ב- N*M/2 + 2 בתים 2 בתים בהתחלה לשמירת מימדי התמונה
53
דוגמא 2: שינוי צבע לפיקסל מסוים בתמונה
יש לתת קאורדינטת x,y וצבע, ובגישה ישירה לעדכן את הפיקסל. יש לשים לב האם הצבע עבור הקאורדינטה המבוקשת נמצא בצד הימני אא בצד השמאלי של ה- byte בו הוא נשמר
54
אופרטורים לעבודה עם סיביות:
ביחידה זו למדנו: מוטיבציה אופרטורים לעבודה עם סיביות: & | ^ ~ >> <<
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.