פורסם 2012 בינואר 113 שנים אוקי זה התרגיל:יש לכתוב פונקציה myscanf המממשת גירסא פשוטה של scanf, המקבלת שני פרמטרים בלבד: הפרמטר הראשון - מחרוזת(קבועה) היכולה להכיל אך ורק %d %f %s - כל מחרוזת אחרת שתתקבל תגרום לשגיאה.הפרמטר השני הוא פוינטר גנרי מסוג void המהווה פרמטר פלט** יש כל מיני הנחיות ליישום התרגיל אך זה כבר נוגע לכתיבת הקודהבעיה היא שאני לא מבין את השאלהאיזה נתונים אני שולח ל myscanf ומה זה פוינטר גנרי מסוג void?
פורסם 2012 בינואר 113 שנים הטיפוס *void הוא טיפוס שמציין "מצביע", בלי לומר למה הוא בדיוק מצביע. הוא יכול לקבל כל ערך של מצביע.ראה דוגמה להלן:int x = 5;int* p = &x; // legal, obviouslyvoid* s = &x; // legal - anything can be converted to void*char* q = &x; // illegal - x is not charבניגוד למצביעים רגילים, ל-*void אי אפשר לעשות dereference, כי הם לא מצביעים לטיפוס אמיתי. דהיינו:int x = 5;void* p = &x;int y = *p; // illegal - *p has no typeלמה זה טוב? בדרך כלל, משתנה יכול להחזיק רק טיפוס אחד - int, char וכד'. שימוש ב-*void מאפשר לך להחזיק משתנה שהטיפוס שלו לא ידוע מראש. אבל מה, בשביל להשתמש בו באופן אקטיבי, תצטרך לבצע המרה - לדוגמה, בשביל שהקוד הנ"ל יעבוד אנחנו צריכים לכתוב ככה:int x = 5;void* p = &x;int y = *((int*)p);הקוד קצת מבלבל - אנחנו קודם כל ממירים את p מ-*void ל-*int, ואז אנחנו עושים לו dereference.מה שכן, צריך להיזהר עם *void - כיוון שאנחנו לא יודעים את הטיפוס האמיתי של המצביע בזמן הקומפילציה, אפשר להמיר אותו לכל טיפוס שרוצים. לדוגמה, הקוד הבא יתקמפל וירוץ:int x = 0;void* p = &x;float y = *((float*)p);מה שיקרה הוא שהערך שיושב בתוך x (כלומר, במקום בזכרון שבו יושב x) יפורש כ-float, למרות שהוא מטיפוס int. התוצאה היא בלתי צפויה (המבנה של int ושל float בזכרון של המחשב שונים לחלוטין).על מנת לדעת מה הטיפוס המקורי של המצביע, אתה צריך לשמור את המידע הזה במקום בצד.ככה בעצם עובדת scanf - הפונקציה מקבלת פרמטרים מטיפוס *void בלבד. אז איך היא יודעת מהם הטיפוסים המקוריים? לפי המחרוזת שהעברת אליה - אם היא מכילה d% אז המצביע הוא במקור מטיפוס *int, אם היא מכילה f% אז הוא מטיפוס *float, וכן הלאה. שים לב שאם תעביר לה *int יחד עם f% אז הקוד יתקמפל וירוץ, אבל התוצאה תהיה לא צפויה.
פורסם 2012 בינואר 113 שנים מחבר אוקי אני חושב שהבנתי אבל רק בזמן כתיבת התוכנית אני אדע אם באמת הבנתי...ובקשר לשאלה עצמהמה שהתוכנית צריכה בעצם לעשות זה 1) לקלוט כמות (לא ידועה) של תווים2) לחפש אחר רצף מתאים של תווים3) ולהמיר אותם לערך המתאים?לדוגמא אם כתבו לי "i need to ask you 2 questions"את האותיות יומרו לcharוהמספר יומר ל int?התרגיל הזה בילבל אותי קצת...
פורסם 2012 בינואר 113 שנים למי איכפת מה כתבו לך? אתה רק צריך לכתוב את myscanf. תן למי שמשתמש ב-myscanf להתחבט איתה.תתחיל מלכתוב את החתימה של myscanf.הפואנטה היא שאתה צריך להיות מסוגל להריץ את הקוד הבא:int x;float y;myscanf("%d", &x);myscanf("%f", &y);myscanf("blabla", &x); // this should return an error
פורסם 2012 בינואר 113 שנים מחבר אוקי הבנתי פחות או יותר, תודה.כרגע נתקלתי בבעיהאתה יכול להסביר לי שוב איך אני מחזיר את התוצאה הסופית למשתנה הגנרי void *?אני מתכוון שאני רוצה לשלוח מהפונקציה החדשה myscanf את הערך של ה-output לפונקציה שקוראת לmyscanfאבל אני לא מצליח לעשות את זה...עריכה: הסדרתי... תודה על כל העזרה :-)
פורסם 2012 בינואר 113 שנים מחבר יש לי רק בעיה אחת עם התוכנית שבניתיכאשר אני מנסה להכניס מספר float הפלט שלי יוצא לא כל כך מדוייקמה הכוונה:לדוגמא הכנסתי את המספר 123.1111הפלט שלי בסופו של דבר כאשר אני מדפיס את המספר הבנוי מחדש הוא:123.111099 while((c=getchar()) !=EOF && c != '\n' && c!=' ') { if((!isspace(c) && isdigit(c)) || c=='.') { if(c=='.') { f_c++; f=f_a; f_a=0; } else if(isdigit(c)) { f_a *= 10; f_a += (c-'0'); if(f_c>0) i*=10; } } else { puts("Error: Unwanted char has been entered!\n"); return 0; break; } } f=(float)f+(float)f_a/(float)i;זה הקוד שנמצא בתוך פונקציה ארוכה
פורסם 2012 בינואר 313 שנים float אינו מדוייק. גם double אינו מדוייק אבל float במיוחד אינו מדויק.לא ניתן לייצג כל מספר בעזרת float (כנ"ל double אבל העיה פחות חריפה שם), ולכן לאורך ההצבות והחישובים מצטברות טעויות.הכלל הראשון שכעובדים עם נקודה צפה (floating point) זה לזכור שהם לא מדוייקים לגמרי.
פורסם 2012 בינואר 313 שנים מחבר אוקי תודה, ואתה צודק בדקתי את הדבר עם scanf רגיל והדפסה של הנתון ויצא לי אותה סטייה
ארכיון
דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.