ABA


"למה שאני קולט תו בC צריך לנקות את הBuffer?"
גירסת הדפסה        
קבוצות דיון פיתוח, תיכנות ובניית אתרים נושא #15745 מנהל    סגן המנהל    מפקח   Winner    צל"ש   מומחה  
אשכול מספר 15745
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   11:54   28.02.10   
אל הפורום  
  למה שאני קולט תו בC צריך לנקות את הBuffer?  
 
   ערכתי לאחרונה בתאריך 28.02.10 בשעה 12:04 בברכה, ronen333
 
עשיתי את התוכנית הבאה לצורך הכנת שיעורי הבית שלי, ואני בשוק שלא נתקלתי בזה קודם לכן:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
int code;
char name[10];
char sex;
}worker;
void input_workers(worker **arr,int n)
{
int i;
worker *a=*arr;
for(i=0;i<n;i++)
{
printf("please insert worker code:\n");
scanf("%d",&a->code);
printf("please insert worker name:\n");
scanf("%s",a->name);
printf("please insert worker sex:\n");
scanf("%c",&a->sex);
a++;
}
}
//... ( some code here)

int main()
{
int n;
worker * arr;
n=5;
arr=malloc(sizeof(worker)*n);
input_workers(&arr,n);


return 0;
}


רציתי לקלוט תו לשדה סקס תו במבנה worker שיצרתי , ופתאום אני קולט שזה מדלג לי על זה.. ואז נזכרתי על איזה משהו שהמרצה זרק בשיעור (ועוד בשיעור באסמבלי) לגבי ניקוי BUFFER עם תווים ..אז חיפשתי קצת באינטרנט וגילתי שצריך להוסיף fflush(stdin);
מוזר לי לגמרי שרק עכשיו אני נתקל בזה.. אמ מישהו יכול להסביר לי את התופעה? X=


                                שתף        
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

  האשכול     מחבר     תאריך כתיבה     מספר  
  רגע, שאני אבין, ה-fflush פתר לך את הבעיה? ldan192  28.02.10 18:22 1
     כן. ronen333  28.02.10 18:57 3
  כן, זה תלוי מימוש פנימי בהתאם לקומפיילר. Deuce  28.02.10 18:36 2
     סבבה תודה אייל =] ronen333  28.02.10 19:04 4
     בדיוק, כי fflush מיועד לנקות את הקאש לבאפר בריבוי חוטים ldan192  28.02.10 19:16 5
         צריך לדעת איך ממומש sacnf. Deuce  28.02.10 19:26 6
             מוסכם לגמרי :) ldan192  28.02.10 19:28 7
  אם אני לא טועה (ובדקתי את זה חלקית..) פאביו ג'וניור 01.03.10 01:14 8
     זה תלוי קומפיילר. Deuce  01.03.10 01:45 9
         הפונקציה עובדת ברור אבל לא תמיד עושה מה שהתכנת חשב.. פאביו ג'וניור 01.03.10 02:32 10
             אתה תמיד יכול לממש משהו בעצמך עם sgetc למשל ldan192  01.03.10 11:48 11
                 ברור אבל זאת לא הנקודה :) פאביו ג'וניור 01.03.10 13:27 12

       
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   18:22   28.02.10   
אל הפורום  
  1. רגע, שאני אבין, ה-fflush פתר לך את הבעיה?  
בתגובה להודעה מספר 0
 


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   18:57   28.02.10   
אל הפורום  
  3. כן.  
בתגובה להודעה מספר 1
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   18:36   28.02.10   
אל הפורום  
  2. כן, זה תלוי מימוש פנימי בהתאם לקומפיילר.  
בתגובה להודעה מספר 0
 
בפלטפורמות מסויימות ה-Buffer (של ה-STDIN או ה-STDOUT) מתמלא ולא פולט מיד את המידע החוצה. אתה רגיל בעיקר לעבוד מול מסך מחשב, בעוד שבעולם האמיתי המון פעמים אתה עובד בלי מסך בכלל, לכן יש הגיון של אופטמיזציות מסויימות לפעמים לאגור מעט את ה-BUFFER. ספציפית לגבי stdin לא עולה לי סיבה טובה למה זה ככה, אבל מניח שיש כזאת.

אפשר לחשוב על דוגמא מעניינת יותר - אם כבר נפתח הדיון - שאתה כותב תכנית כמו:


{
printf("Hello World\n");
fork();
printf("\n");
}

בגרסאות מסויימות אם תריץ את זה, יודפס Hello World פעמיים וזה כי printf מעתיקה לפעמים לבאפר, עדיין לא מדפיסה. fork() משכפל את הבאפר ולכן יודפס פעמיים. יש בזה הגיון לאגור את כל המידע ורק אז לשחרר אותו.
(fflush אחרי ה-printf של Hello World היה פותר את הבעייה)

כמו שהמרצה שלך אמר, הפתרון הוא לנקות את הבאפרים בעזרת fflush(stdout) או fflush(stdin) בהתאם למה שאתה צריך לעשות.

באופן כללי אני נגד לקלוט המון דברים בעזרת scanf. מומלץ לקלוט דברים דרך ה-args, במידה ויש ריבוי קלטים עדיף להשתמש ב-vscanf, משתמשים גלובלים הם גם אפשרות.






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ronen333 
חבר מתאריך 20.2.03
6069 הודעות
   19:04   28.02.10   
אל הפורום  
  4. סבבה תודה אייל =]  
בתגובה להודעה מספר 2
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   19:16   28.02.10   
אל הפורום  
  5. בדיוק, כי fflush מיועד לנקות את הקאש לבאפר בריבוי חוטים  
בתגובה להודעה מספר 2
 
ערכתי לאחרונה בתאריך 28.02.10 בשעה 19:20 בברכה, ldan192
 
ותהליכים (מבאפר זמני לבאפר בזכרון).
לא רואה איך המקרה הנ"ל עזר לפתרון הבעיה.
הבעיה נובעת מכך שה-scanf בולע את ירידת השורה ב-printf הקודם שלו.
הדבר היחיד שעולה בדעתי זה בגלל שנקראת פונקצית אחרת (fflush) אז זה קוטע את רצף הבליעות בלולאה.
באותה מידה, אם תשים גם פונקציה "ריקה" (אבל שלא תוסר באופטימיזציה) בסוף הלולאה - זה לדעתי יתן אותו אפקט.

בקיצור, לא רואה ממש קשר ל-fflush...


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   19:26   28.02.10   
אל הפורום  
  6. צריך לדעת איך ממומש sacnf.  
בתגובה להודעה מספר 5
 
כמו שרשמתי למעלה, לא מצאתי דוגמא למה זה צריך להיות ככה, אבל לך תדע.
או שהוא עשה flush ל-stdout.

אבל הוא אומר שהוא עשה flush ל-stdin וזה עבד, וזה סה"כ תלוי קומפיילר.






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   19:28   28.02.10   
אל הפורום  
  7. מוסכם לגמרי :)  
בתגובה להודעה מספר 6
 


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
פאביו ג'וניור

   01:14   01.03.10   
אל הפורום  
  8. אם אני לא טועה (ובדקתי את זה חלקית..)  
בתגובה להודעה מספר 0
 
   ערכתי לאחרונה בתאריך 01.03.10 בשעה 01:18 בברכה, פאביו ג'וניור
 
יש איזה פאק בקריאת מחרוזות עם SCANF...
אם תשים לב מה שקורה זה שהוא לא קלט את ה\n מהמחרוזת שהכנסת.. (מהשם)
ובגלל זה תמיד לתוך sex נכנס לך \n
כמו שאם תעשה fgets מstdin הוא תמיד יקלוט לך עם האנטר בסוף...
למה הוא לא מנקה אנטרים שאתה קולט מחרוזות? אני לא יודע... אני זוכר שבשיעורים הראשונים בC ממזמן המרצה אמרה לנו את זה :P

יותר מזה... אם תכתוב בname משהו כמו: name m
תשים לב איזה דבר מוזר קורה :P

הפתרון לזה זה באמת לקלוט שמות עם gets... ככה הוא גם יקרא עם רווחים (כידוע scanf קולט עד רווח או אנטר..) או לעשות עוד getch אחרי שקלטת name שהוא "ינקה" את האנטר הזה


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Deuce 
חבר מתאריך 1.9.08
6225 הודעות
   01:45   01.03.10   
אל הפורום  
  9. זה תלוי קומפיילר.  
בתגובה להודעה מספר 8
 
אין באמת "פאק", זאת סה"כ פונקציה שעובדת בסדר. אני אישית מעדיף להשתמש ב-vscanf ובהזדמנות אני אסביר למה.






                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
פאביו ג'וניור

   02:32   01.03.10   
אל הפורום  
  10. הפונקציה עובדת ברור אבל לא תמיד עושה מה שהתכנת חשב..  
בתגובה להודעה מספר 9
 
   כמו שfgets קולטת את השורה כולל האנטר... הגיוני? אני לא חושב... אבל זה "לדעת המתכנת"..
כן אני מניח שזה תלוי קומפיילר.. אבל סה"כ אמור להיות איזה סטנדריזציה בפונקציות C בסיסיות לא?


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   11:48   01.03.10   
אל הפורום  
  11. אתה תמיד יכול לממש משהו בעצמך עם sgetc למשל  
בתגובה להודעה מספר 10
 


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
פאביו ג'וניור

   13:27   01.03.10   
אל הפורום  
  12. ברור אבל זאת לא הנקודה :)  
בתגובה להודעה מספר 11
 
  


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

תגובה מהירה  למכתב מספר: 
 
___________________________________________________________________

___________________________________________________________________
למנהלים:  נעל | תייק בארכיון | מחק | העבר לפורום אחר | מחק תגובות | עגן אשכול
       



© כל הזכויות שמורות ל-רוטר.נט בע"מ rotter.net