slimshady21 פורסם 2006 בספטמבר 14 Share פורסם 2006 בספטמבר 14 שלום.הכנתי תוכנית לניהול נתונים של מוצרים בחנות (דוק,תיאור,ומחיר) בעזרת מערך של מצביעים (כשכל מצביע מאותחל במבנה מוצר) . בניתי כבר את התוכנית והכל בסדר. אבל עכשיו הוספתי גם אפשרות של שמירה לקובץ בינארי. בשמירה- אני כאילו קודם רושם לקובץ את מספר המוצרים שיש (כדי שמתי שירצו לטעון נתונים מהקובץ התוכנית תדע כמה נתונים לטעון). ואחרי מספר המוצרים אני רושם לקובץ את כל המבנים אחד אחרי השני בלולאת FOR .הפונקציה שטוענת את הנתונים מהמוצר קוראת קודם את מספר הנתונים שהיא צריכה לטעון, מקצה זכרון עבור מערך בגודל כזה, וטוענת את הנתונים לכל המבנים בלולאה. זה עובד די בסדר, רק שהתיאור (שהוא בתווים) לא יוצא טוב, מודפסים לי הרבה חרבושים. הנה הקוד- רק הורדתי את כל הפונקציות הלא חשובות:#define filename "binary.bin"typedef struct{ long code; char *des; float price;}store;int LoadFile(store ***a,int n){int counter,check=0,size=0; FILE *file=fopen(filename,"rb"); if(file==NULL) { clrscr(); printf("Can't open file"); return n; }check=fread(&size,sizeof(int),1,file); if(size==0 || check==0) { printf("No data on file"); return n; }// Begining to free all the array::: for(counter=0;counter<size;counter++) free((*a)[counter]->des); for(counter=0;counter<size;counter++) free((*a)[counter]); free(*a); // END free(*a)=(store**)calloc(size,sizeof(store*)); for(counter=0;counter<size;counter++) (*a)[counter]=(store*)calloc(1,sizeof(store));for(counter=0;counter<size;counter++) fread((*a)[counter],sizeof(store),1,file);printf("\n\nAll data have been loaded from the file\n\n");return size;}void SaveFile(store **a,int size){int counter,check=0; FILE *file=fopen(filename,"wb"); if(file==NULL) { printf("cant open file"); getch(); exit(1); }fwrite(&size,sizeof(int),1,file);for(counter=0;counter<size;counter++) check+=fwrite(a[counter],sizeof(store),1,file);if(check!=size){ printf("Error writing to file"); getch(); fclose(file); exit(1);}fclose(file);printf("\n\nData have been saved to the file successfully\n\n");}void PrintList(store **a,int size){ int counter;printf("\n\n# Code Description Price\n");printf("------------------------------------------------------------------\n");for(counter=0;counter<size;counter++) printf("%d.%-13ld%-20s %-4f\n",counter+1,a[counter]->code,a[counter]->des,a[counter]->price);putchar('\n');}int main(){store **a=NULL;char ch;int size=0,counter;printf("-----SlimShady's program for store managment-----\n\n");do{ ch=Menu(); switch(ch) { case 'p': { PrintList(a,size); break; } case 's': { SaveFile(a,size); break; } case 'l': { size=LoadFile(&a,size); break; } case 'q': continue; }}while(ch!='q');return 0;} קישור לתוכן שתף באתרים אחרים More sharing options...
Zelig פורסם 2006 בספטמבר 14 Share פורסם 2006 בספטמבר 14 זה בגלל שלא שמרת את המחרוזות לקובץ אלא את המצביעים אל המחרוזות.יש לך בגדול שתי אופציות:1) לשנות את מבנה store כך שיכיל לא מצביע למחרוזת אלא מערך של char-ים כלומר מחרוזת באורך קבוע: char description[DESC_SIZE]2) לשמור כמו שצריך את המחרוזות לקובץ. אל תשכח לטעון אותן כמו שצריך (הקצאת זכרון למחרוזת, ואז טעינת).בכל מקרה תזכור כמה דברים:אם str הוא char* אז sizeof(str) הוא תמיד גודל של מצביע ל-char, ללא קשר לאורך המחרוזת.אם str הוא char[20] אז sizeof(str) הוא תמיד 20 ללא קשר לאורך המחרוזת.אם אורך המחרוזת ב-str הוא 15, אז אל תשכח שהגודל שלא הוא 16 כלומר strlen(str) +1. תזכור את זה כשתקצה זכרון, תשמור ותטען מקובץ. קישור לתוכן שתף באתרים אחרים More sharing options...
slimshady21 פורסם 2006 בספטמבר 14 מחבר Share פורסם 2006 בספטמבר 14 וואלה אחי תודהההה. איך שכחתי שצריך להקצות זכרון גם למחרוזות יאללה . טוב, אז- לעשות את המחרוזות כמערכים סטטיים אני יודע שאני יכול, אבל אני רוצה להתמודד עם הבעיה לא לברוח ממנה... אז אני ישאיר אותם דינמיים, אבל השמירה של המחרוזות לקובץ עשיתי טוב לא? הרי אם למשל *str זה מצביע למחרוזת, אז אתה פשוט שומר אותו ואז כל המחרוזת נשמרת לא? אחרת אז איך? ממה שהבנתי הבעיה בזה שאני טוען את המחרוזות- אז אני לא מקצה להם זכרון קודם. אבל יש לך רעיון איך להקצות זכרון מתאים? כאילו איך אני אדע מה האורך של המחרוזת שאני הולך לטעון? חשבתי למשל, להכניס לקובץ את אורך המחרוזת שנמצאת במבנה שאני עומד לשמור עליו. הכוונה- לשמור את אורך מחרוזת מספר 1, ואז את מבנה מספר 1. אחר כך לשמור את אורך מחרוזת מספר 2, ואז את מבנה מספר 2. ואז בקריאה לקובץ אני יוכל להתאים כבר את האורך של המחרוזות. מה אתה אומר זה יעבוד? ולגבי מה שאמרת בסוף- אני לא שומר ככה בכלל, נגיד אני רוצה לכתוב את המחרוזת str לקובץ אני עושה: fwrite(str,sizeof(char),strlen(str)+1,file) a לא טוב? קישור לתוכן שתף באתרים אחרים More sharing options...
שניצל פורסם 2006 בספטמבר 14 Share פורסם 2006 בספטמבר 14 למה שלא תשתמש ב-fprintf במקום? זו פונקציה שמיועדת לטיפול במחרוזות. קישור לתוכן שתף באתרים אחרים More sharing options...
Zelig פורסם 2006 בספטמבר 14 Share פורסם 2006 בספטמבר 14 ראשית אם אתה שומר את הערך של str אז לא שמרת את המחרוזת, שמרת מצביע.הדרך לשמור את המחרוזת היא בדיוק כמו שהצעת: fwrite(str,sizeof(char),strlen(str)+1,file) אכן צדקת: בעקרון, עדיף לשמור את אורך המחרוזת ואז את המחרוזת. אני מציע שתשנה את המבנה כך שיכיל את אורך המחרוזת בנוסף למצביע. זה יותר נכון.שימוש ב-fprintf לא מומלץ בקבצים בינריים. קישור לתוכן שתף באתרים אחרים More sharing options...
slimshady21 פורסם 2006 בספטמבר 14 מחבר Share פורסם 2006 בספטמבר 14 תודה, ניסיתי לעשות את מה שאמרתי מקודם- קודם לשמור מספר INT שהוא אורך המחרוזת, ואז לשמור את המבנה. ואז בטעינה לטעון את אורך המחרוזת- להקצות זכרון בהתאם, ואז לקלוט נתונים אל המבנה. וקרה משהו הכי מעצבן- לפעמים זה עובד טוב ולפעמים זה לא. כאילו לפעמים אני יכול לטעון והכל יטען ויוצג כראוי, ובפעמים אחרות יש חירבושים. אני הכי לא סובל את המקרים האלה, איך אני אמור לדעת מה לא בסדר, אם לפעמים זה כן עובד??לגבי הדרך שלך- אם למשל אני יכניס למבנה עוד משתנה INT שיכיל את אורך המחרוזת (אם זה מה שהתכוונת), אז איך אני יוכל קודם לקלוט אותו, ואז להקצות זכרון בהתאם למחרוזת? הרי כשאני קולט נתונים אז אני קולט מבנה שלם בקריאה אחת, אז זה יקרא לי ישר את אורך המחרוזת ואת המחרוזת עצמה (שעוד לא הקציתי לה זכרון) בפעם אחת.הנה הקוד עכשיו:#define filename "binary.log"typedef struct{ long code; char *des; float price;}store;int LoadFile(store ***a,int n){int counter,check=0,size=0,lenght=0; FILE *file=fopen(filename,"rb"); if(file==NULL) { clrscr(); printf("Can't open file"); getch(); exit(1); }check=fread(&size,sizeof(int),1,file); if(size==0 || check==0) { printf("No data on file"); return n; } for(counter=0;counter<size;counter++) free((*a)[counter]->des); for(counter=0;counter<size;counter++) free((*a)[counter]); free(*a);(*a)=(store**)calloc(size,sizeof(store*)); for(counter=0;counter<size;counter++) (*a)[counter]=(store*)calloc(1,sizeof(store));for(counter=0;counter<size;counter++) { fread(&lenght,sizeof(int),1,file); (*a)[counter]->des=(char*)calloc(lenght,sizeof(char)); fread((*a)[counter],sizeof(store),1,file); }printf("\n\nAll data have been loaded from the file\n\n");return size;}void SaveFile(store **a,int size){int counter,check=0,check2=0,lenght=0; FILE *file=fopen(filename,"wb");fwrite(&size,sizeof(int),1,file);for(counter=0;counter<size;counter++) { lenght=strlen(a[counter]->des)+1; printf("%d,",lenght); check+=fwrite(&lenght,sizeof(int),1,file); check2+=fwrite(a[counter],sizeof(store),1,file); }if(check!=size || check2!=size || check!=check2){ printf("Error writing to file"); getch(); fclose(file); exit(1);}fclose(file);printf("\n\nData have been saved to the file successfully\n\n");}int main(){store **a=NULL;char ch;int size=0,counter;do{ ch=Menu(); switch(ch) { case 'S': case 's': { SaveFile(a,size); break; } case 'L': case 'l': { size=LoadFile(&a,size); break; } case 'q': continue; }}while(ch!='q');return 0;} קישור לתוכן שתף באתרים אחרים More sharing options...
Ghosthunter פורסם 2006 בספטמבר 14 Share פורסם 2006 בספטמבר 14 אם אתה כותב INT לתוך הקובץ, אז תצפה לקרוא INT ממנו.אם תראה INT, אין שום סיבה שגם כל שאר הטקסט שרשמת יכנס לתוך המשתנה.אתה לא צריך לשים במבנה שלך את אורך המחרוזת. תכניס את זה כל פעם למשתנה זמני כלשהו שרק ישמש אותך להקצאת הזיכרון. אתה תמיד יכול להשיג את אורך המחרוזת בהמשך התוכנית ע"י strlen. קישור לתוכן שתף באתרים אחרים More sharing options...
slimshady21 פורסם 2006 בספטמבר 14 מחבר Share פורסם 2006 בספטמבר 14 נו זה בדיוק מה שעשיתי. אני קורא קודם את המספר INT -שהוא אורך המחרוזת ששמרתי מקודם. אני מכניס אותו למשתנה זמני lenght , מקצה זכרון למחרוזת בהתאם, ואז קולט את הנתונים למבנה. סתכל על פונקציה LoadFile . אבל זה לא עובד טוב. לפעמים זה בסדר, אבל לפעמים יש חירבושים, לפעמים התוכנית משתגעת, ולפעמים היא פשוט קורסת. וזה גם שונה עם סוגי קבצים שונים (log, bin,db). אז מה אני אמור לעשות? קישור לתוכן שתף באתרים אחרים More sharing options...
Ghosthunter פורסם 2006 בספטמבר 14 Share פורסם 2006 בספטמבר 14 תעשה DEBUG ותראה איפה אתה מקבל שגיאה... קישור לתוכן שתף באתרים אחרים More sharing options...
slimshady21 פורסם 2006 בספטמבר 15 מחבר Share פורסם 2006 בספטמבר 15 ת'אמת, אני עובד בC כבר הרבה זמן ואין לי מושג מה זה DEBUG. אני חשבתי שכל ההודעות שגיאה שאני מקבל למטה זה הDEBUG ...בכל מקרה, נכנסתי עכשיו לתוכנה וראיתי תפריט DEBUG , אבל אז מה אני עושה שם? לחצתי סתם על INSPECT אבל הוא ביקש שאני ארשום משהו.אז מה לעשות?יש לי borland turbo C++ 3.1 for DOS קישור לתוכן שתף באתרים אחרים More sharing options...
rosesr פורסם 2006 בספטמבר 15 Share פורסם 2006 בספטמבר 15 #include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct store { long code; float price; char* desc;} store;store* loadStore(const char* file, int* size) { FILE* in; store* s; int i, len; if( (in=fopen(file, "rb")) == NULL ) { printf("Error opening"); return NULL; } if( fread(size, sizeof(int), 1, in) != 1 ) { printf("Error getting length!"); return NULL; } if( (s=calloc(*size, sizeof(store))) == NULL ) { printf("Error getting space!"); return NULL; } for(i=0;i<(*size);++i) { /* Add tests to make sure getting data corretly!! */ fread(&s[i].code, sizeof(long), 1, in); fread(&s[i].price, sizeof(float), 1, in); fread(&len, sizeof(int), 1, in); s[i].desc = calloc(len, sizeof(char)); fread(s[i].desc, sizeof(char), len, in); } fclose(in); return s;}void saveStore(const char* file, store* s, int size) { FILE* out; int i, len; /* Add tests to make sure setting data corretly!! */ if( (out=fopen(file, "wb")) == NULL ) { printf("Error opening"); return; } fwrite(&size, sizeof(int), 1, out); for(i=0;i<size;++i) { fwrite(&s[i].code, sizeof(long), 1, out); fwrite(&s[i].price, sizeof(float), 1, out); len = strlen(s[i].desc)+1; fwrite(&len, sizeof(int), 1, out); fwrite(s[i].desc, sizeof(char), len, out); } fclose(out);}void freeStore(store** s, int size) { int i; store* ss = *s; for(i=0;i<size;++i) { free(ss[i].desc); } free(*s);}int main() { store* s = calloc(25, sizeof(store)); int i, size; for(i=0;i<25;++i) { s[i].code=i; s[i].price=i*0.5; s[i].desc=strdup("Test"); } saveStore("C:\\Test.txt", s, 25); freeStore(&s, 25); s = loadStore("C:\\Test.txt", &size); printf("%d\n",size); for(i=0;i<size;++i) { printf("%d %f %s\n",s[i].code,s[i].price,s[i].desc); } freeStore(&s, size); system("PAUSE"); return 0;}הקוד לא מושלם וצריך לעשות בדיקות תקינות קישור לתוכן שתף באתרים אחרים More sharing options...
slimshady21 פורסם 2006 בספטמבר 15 מחבר Share פורסם 2006 בספטמבר 15 כן תודה אחי, אבל בדיוק כרגע, אחרי שעבדתי איזה שעה על הקוד- הצלחתי! עשיתי בדיוק מה שאתה עשית- במקום לכתוב ולקרוא את הנתונים כמבנה שלם (בפעולת קריאה/כתיבה אחת) , פיצלתי את זה לכל המשתנים במבנה - code , desc, price וזה עבד טוב! אבל זה לא אמור להיות ככה, אני לא מבין מה הבעיה שלו בלקרוא/לכתוב מבנה שלם כמו שצריך.....ראיתי שעשית מערך של מבנים ולא של מצביעים- אז יש לי שאלה, קראתי שמערך של מצביעים למבנים,הוא יותר יעיל ממערך של מבנים. אבל למה ? הבנתי שהיתרון של זה- זה שלא צריך שיהיה זכרון רציף לכל המבנים , צריך רק שיהיה מספיק זכרון ולא משנה איך. אבל יש לזה גם חסרונות- קודם כל המצביעים עצמם לוקחים עוד זכרון, ואצלהם כן צריך שהזכרון יהיה רציף (אם אני לא טועה), אז מה באמת יותר עדיף?בכל אופן, אשמח גם אם תגידו לי מה זה בדיוק הDEBUGGER הזה ואיך להשתמש בו קישור לתוכן שתף באתרים אחרים More sharing options...
Ghosthunter פורסם 2006 בספטמבר 15 Share פורסם 2006 בספטמבר 15 הדיבאגר זה כלי שמאפשר לך לרוץ שורה שורה ולראות איפה אתה מקבל ערכים(במשתנים בסויימים) שלא היו צריכים להתקבל.העבודה עם הדיבאגר משתנה בין סביבת עבודה לסביבת עבודה. קישור לתוכן שתף באתרים אחרים More sharing options...
Zelig פורסם 2006 בספטמבר 15 Share פורסם 2006 בספטמבר 15 כן תודה אחי, אבל בדיוק כרגע, אחרי שעבדתי איזה שעה על הקוד- הצלחתי! עשיתי בדיוק מה שאתה עשית- במקום לכתוב ולקרוא את הנתונים כמבנה שלם (בפעולת קריאה/כתיבה אחת) , פיצלתי את זה לכל המשתנים במבנה - code , desc, price וזה עבד טוב! אבל זה לא אמור להיות ככה, אני לא מבין מה הבעיה שלו בלקרוא/לכתוב מבנה שלם כמו שצריך.....ראיתי שעשית מערך של מבנים ולא של מצביעים- אז יש לי שאלה, קראתי שמערך של מצביעים למבנים,הוא יותר יעיל ממערך של מבנים. אבל למה ? הבנתי שהיתרון של זה- זה שלא צריך שיהיה זכרון רציף לכל המבנים , צריך רק שיהיה מספיק זכרון ולא משנה איך. אבל יש לזה גם חסרונות- קודם כל המצביעים עצמם לוקחים עוד זכרון, ואצלהם כן צריך שהזכרון יהיה רציף (אם אני לא טועה), אז מה באמת יותר עדיף?בכל אופן, אשמח גם אם תגידו לי מה זה בדיוק הDEBUGGER הזה ואיך להשתמש בונראה שכבר התחלת להבין שאין כאן "יותר עדיף". זה תלוי בצרכים שלך. לפעמים עדיף להקצות מערך של מבנים, ולפעמים עדיף מערך של מצביעים למבנים.מדובר ב-tradeoff. הרבה דברים בתוכנה (ובהנדסה) הם ככה. קישור לתוכן שתף באתרים אחרים More sharing options...
slimshady21 פורסם 2006 בספטמבר 17 מחבר Share פורסם 2006 בספטמבר 17 טוב תודה.אבל עדיין לא הבנתי בדיוק איך אני משתמש בדיבאגר. מה הכוונה מקבל ערכים שלא היו אמורים להתקבל ואיך אני בודק את זה? את הסביבת שאני משתמש בה אמרתי כבר.וחשבתי עכשיו- יכול להיות שהבעיה בקריאה/כתיבה של כל המבנה לקובץ, כמו שניסיתי בהתחלה, הייתה כי לא השתמשתי כלל בפונקציה fflush ? פתאום נזכרתי בפונקציה הזאת שקשורה לקבצים, וחשבתי אולי זה בגללה קישור לתוכן שתף באתרים אחרים More sharing options...
Recommended Posts
ארכיון
דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.