יש בעיה קטנה

andav

New member
יש בעיה קטנה

אז ככה,יש לי תוכנית קטנה שאמורה לקבל 4 תווים (פעם באותיות גדולות ופעם בקטנות) ואז להדפיס למסך את האותיות וסכום הערכים שלהם ב- ascii. הבעיה היא שזה לא עובד. הנה התוכנית:
#include <stdio.h> #include <conio.h> int main() { char a,b,c,d; printf("please write your four first letter's name in capital letters - "); scanf ("%c%c%c%c",&a,&b,&c,&d ); printf ("the letters are : %c %c %c %c and their sum is %d \n\n",a, b, c, d, a+b+c+d ); printf("please write your four first letter's name in small letters - "); scanf ("%c%c%c%c",&a,&b,&c,&d ); printf ("the letters are : %c %c %c %c and their sum is %d ",a, b, c, d, a+b+c+d ); return 0; }​
מצורפת תמונה של הפלט עם קלט של התווים : a a a a שימו לב שהקוד לא משתנה ובשתי הפעמים אני מכניס את : a a a a ,אבל התוצאה שונה. מה אני עושה לא טוב? תודה.
 

shaiby

New member
אתה לא עושה FLUSH בין הקריאות.

שים לב שב- SCAN הראשון התוכנית מכניסה לכל אחד מהמשתנים a , b , c , d את הערכ 'a', וגם מדפיסה לך 4 פעמים 'a' על המסך. בפעם השנייה מודפס רק שלוש פעמים 'a', והפלט הזה מופיעה שורה אחת מתחת לשאר הטקסט. למה ? משום שהתו הראשון שנקרא הוא לא ה 'a' שהקלדת , אלא התו ENTER שלחצת כדי לסיים את ה SCAN הראשון !! לכן, כשמדפיסים ENTER אחד ועוד 3 פעמים 'a' , מקבלים את מה שקיבלת - 3 עותקים של 'a' - בשורה חדשה ! כמובן שגם הסכומים משתנים בהתאם. איכ פותרים ? מבצעים FLUSH ל BUFFER של SCANF . (ואם הייתי זוכר מה הפקודה המדוייקת - בחיי שהייתי רושם לך... אין לי קובץ HELP ראוי לשמו בבית, ואני פשוט לא זוכר בע"פ...) בהצלחה.
 

annefan

New member
אתה לא יכול

לפחות לא באופן פורטבילי. ב-VC יש את flushall_. ב-gcc לדעתי אין שום דבר כזה. אם הייתי ממליץ להשתמש ב-scanf (ואני לא!) הייתי מוסיף עוד משתנה דמה.
 

vinney

Well-known member
FFLUSH היא הסטנדרטית

flushall בסה"כ מממש קריאה לFFLUSH עם פרמטר שהוא NULL. הרי תמצית התנ"ך:
The fflush function flushes a stream. If the file associated with stream is open for output, fflush writes to that file the contents of the buffer associated with the stream. If the stream is open for input, fflush clears the contents of the buffer. fflush negates the effect of any prior call to ungetc against stream. Also, fflush(NULL) flushes all streams opened for output. The stream remains open after the call. fflush has no effect on an unbuffered stream.​
 

annefan

New member
ציטוטים מ-MSDN??

Description If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.​
(זה הסטנדרט של C, אגב. בסטנדרט של ++C אין שום שינוי ממנו).
 

vinney

Well-known member
K&R דווקא. בדקתי שוב במיוחד בשבילך

הוצאה שניה (ANSI), כך שזה די בטוח
 

annefan

New member
לא מספיק בטוח

K&R הוא לא הסטנדרט של C, כמו שסטרוסטרופ הוא לא הסטנדרט של ++C. בקומפיילר זניח למדי (gcc), לדוגמא, flushall לא קיימת, ו-flush(stdin) לא עובדת כמו שאתה חושב. כמו בציטוט שהבאתי מהסטנדרט, ההנהגות אכן לא מוגדרת, ולא במקרה. כדי לתמוך ב-buffer של input ולנקות אותו כשהוא פתוח תריך תמיכה של OS. אם יש, נהדר! אם אין, או שאין פורטביליות, אז אין. זו התנהגות לא מוגדרת.
 

vinney

Well-known member
אתה סתם מתווכח

וזה לא כזה משנה... אבל הנה עוד כמה ציטוטים
הMAN דוגמא לקוד על RED HAT (אם אני לא טועה הם מספקים GCC?) עם שימוש בFFLUSH בדיוק כמו שתיארתי. שים לב לתחילת לולאה אחרי /* clear a 'queue' */.
 

annefan

New member
זה מה שקורה כשכותבים ב-1:16 בלילה

אתה רואה באיזה מקום fflush(stdin)? הדוגמא עושה fflush אחרי printf, כלומר ל-stdout. ה-MAN לא אומר מילה על input או על stdin. (אגב, בדיקה מעניינת יכולה להיות להריץ את התוכנית על חלונות ולינוקס ולראות תחת gcc ולראות האם היא עובדת. בחלונות, היא לא. בלינוקס לא בדקתי.) ועוד אגב, RH לא קשורים ל-gcc שהם מספקים.
 

vinney

Well-known member
ברור

FFLUSH NULL זה רק לפלטים, לקלטים הוא מאפס באפרים, אם יש, וזה כתוב בכל הציטוטים שהבאתי, החל מK&R אז על מה אנחנו לא מסכימים?
 

annefan

New member
הא?

Description If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.
זה הסטנדרט. הנה לך FAQ. לגבי הציטוטים, חוץ מ-K&R אף קישור לא מדבר על flush ל-stdin. אם הקומפיילר שלך מבטיח לך מה הוא עושה במקרה של Undefined Behaviour, תהיה בריא. מאותו רגע, אתה א. תלוי ביצרן הקומפיילר וב. מתעסק בתוכנית שיכולה לעשות (לפי הסטנדרט!!) מה שמתחשק לה באותו רגע.
 

vinney

Well-known member
בגלל זה לא צריך להגיע למצב הזה

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

annefan

New member
בודאי

להשתמש ב-scanf מזמין צרות. להשתמש ב-fflush(stdin) מזמין עוד צרות.
 

annefan

New member
אם הוא היה ממשיך

הוא היה מקבל גם תשובות בפייתון, ב-java וב-VB...
 

selalerer

New member
אפשר להשתמש בfread על stdin לתוך

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

andav

New member
באמת תודה רבה../images/Emo13.gif + שאלות

דבר ראשון,אכן עובד. ולשאלות? מדוע זה קורה(או שאני טועה)רק ב- char ולא ב- int ,לדוגמה? איפה בדיוק נמצא ה- "ENTER" החמקמק הזה כלומר,היכן הוא מאוכסן כאשר אני לפני הקליטה השנייה של התווים? האם ל- ENTER אין קוד ascii משלו? אם יש לו,אז איך התוכנה יודעת מה להדפיס כלומר,או הורדת שורה(כמו שקרה)או את הסכום של זה:
ENTER + a + a + a​
??? תודה רבה לך.
 

andav

New member
הקפצה + תתעלמו(בבקשה) מהשאלה

השלישית(היא ברורה לי). תודה רבה.
 

vinney

Well-known member
תוכל להסביר מה ניסית לשאול?

קצת לא ברור לי....
 
למעלה