בעיה מוזרה

pitbol3

New member
בעיה מוזרה

אהלן חברים,

רצ"ב קטע קוד מתוכנית כלשהי(לא באמת משנה איזה תוכנית, זהו החלק הראשון, הקלט של התכנית).

כשאני מריץ את התוכנית, כשאני מכניס קלט שגוי בכוונה, למשל מספר 5, אני מקבל פעמיים את הפלט משום מה.... מה הבעיה? למה זה חוזר על עצמו?

תודה רבה!
 

pitbol3

New member
רק שימו לב

שזה ששמרתי את פלייר ואת טמפ כצ'ארים זה כי ככה זה אמור להיות לפי התוכנית... ובגלל שהקוד אסקי של 1 הוא 49, אז יש את התנאי בסוף, כדי לוודא שאכן הוכנס רק 1 או 2.
 

BravoMan

Active member
כי גם Enter הוא תו קלט.

אחרי שקלטת את מספר השחקן, נשאר עוד תו אחד בקלט - תו ה-Enter שחלצת כדי לסמן סוף קלט.

הוא לא עבר עיבוד, ולכן בפעם השנייה שהלולאה עוברת הוא נקלט לתוך player.

כדי להימנע מזה, תוסיף getchar אחרי ה-scanf.
 

pitbol3

New member
מעולה תודה ועוד משהו קצת דומה..

רצ"ב התוכנית כולה...

מבלי שתצטרך להתעמק בפרטי התוכנית(היא עובדת), אלא רק בבעיה דומה נוספת.

כאשר מכניסים את הקלט : 1 , ואז 5 ואז 1 ואז כל מספר בין 0 ל 9, לאחר מכן התפריט הראשי מופיע פעמיים( כנראה מאותה הסיבה?).

(שים לב שמדובר ממש על השורות הראשונות בפונקציה הראשית...)
אשמח לדעת מדוע זה קורה ואיך פותרים את זה...

תודה :)
 

BravoMan

Active member
לא, מדובר בבעיה שונה.

בניגוד ל-scanf, הפונקציה gets קוראת גם את תו ה-Enter מהקלט, כך שאין צורך לבצע איבוד מיוחד עבורו.

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

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

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

בהצלחה!
 

pitbol3

New member
למדתי לדבג

אבל זה לא ממש פותר את הבעיה...

אני שם לב שאם אני נכנס לmenu==5, הוא מבצע את הפלט של התפריט פעמיים,

הסיבה פשוט לא ברורה לי...

תודה !
 

make clean

New member
אחרי שאתה מקיש

את האנטר נכנס ל stdin שני תווים - מה שהקשת (5) וגם האנטר . לכן בפעם הבאה שהוא נכנס ללולאה יש לו כבר CHAR מוכן והSCANF לא מחכה למשתמש אלא שם לתוך PLAYER את הערך של n\ -אנטר שכבר אדור אצלו.מכיוון שהוא לא '1' או '2' הוא שוב נכנס לתוך הIF ומדפיס את אותה ההודעה . תנסה להדפיס גם את הערך שקיבלת ולא רק את הודעת השגיאה ותראה .
 

make clean

New member
סליחה,כתבתי את הודעה הקודמת

לפני שראיתי שענו לך.
לדעתי זו דווקא כן אותה בעיה :
אתה חוזר אחרי התפריט החמישי בצורה כזו:
printf("Select column:");
scanf("%d",&col);


ושוב מחכה לך אנטר שגורם ל GETS לחזור מיד עם מחרוזת ריקה ולא להכנס ב SWITCH בשום מקום מה שמחזיר אותך שוב לתחילת הלולאה ולאותו פלט שוב.

כמה הערות כלליות :
1.אל תשתמש בערך הASCII - של 0 -48 כמו שהוא יותר קריא ויותר בריא '0' .
2. הערות בC במקור נכתבו רק ע"י /**/ ולא ע"י // . מכיוון שיש קומפילרים שזה מפריע להם , לדעתי עדיף להמנע (למרות שזה כבר כן בתקן).
3. MAIN אמור להחזיר INT .
 

pitbol3

New member
תודה רבה!

ככה,

קודם כל, זה פתר לי את הבעיה :)

לגבי 3, זה לא ככה ב VS ולא ככה דרך איפה שאני לומד, תוכל להסביר את העקרון שמאחורי זה?

האם כל פעם אחרי שאני עושה SCANF אני אמור לשים getchar? כי הscanf לוקח אליו רק את מה שהוא צריך( מספר שלם, תו וכו') ואז בחוצץ נשאר

הרווח טאב או אנטר.

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


ושוב תודה רבה!
 

BravoMan

Active member
תשובות:

VS הוא קומפיילר די סלחן, שלא ממש אכפת לו מהתקן של שפת C.

לפי התקן, פונקציה main חייבת להחזיר int, והערך הזה חוזר למערכת הפעלה ויכול לסמן אם התוכנית הסתיימה בהצלחה או קרתה שגיאה.

בד"כ לא מתייחסים לערך הזה, אבל הוא עשוי להיות שימושי לקבצי batch.

לגבי scanf:
היא קוראת את הקלט הסטנדרטי (בד"כ מקלדת), ומנסה להוציא ממנו בדיוק את מה שאמרת לה להוציא.
אם אמרת לקורא תו אחד, היא תקרא תו אחד.
אם אמרת לה לקרוא מספר שלם (int) היא תנסה לקרוא מספר שלם.

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

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

nocgod

New member
אני מאוד מקווה שהוא לא מנסה לקרוא

מחרוזת עם scanf מאחר והיא לא קוראת מעבר ל whitespace הראשון אותו פוגשת...כלומר רק את המילה הראשונה, כל השאר נשאר בbuffer
לדוגמא

#include <stdio.h>

void main()
{
char s[128];

scanf("%s", s); // reads only the first word up-to (not including) the first white space
puts(s); // prints what we read
gets(s); // reads the rest of the input from the buffer including the white space
puts(s); // prints the rest of the input
}
 

pitbol3

New member
הסבר מעולה תודה!

ברור שאני אעדיף שלא לקלוט מחרוזות עם scanf אלא עם gets.
 
למעלה