כותב |
|
AC-Milan משתמש חבר
![משתמש חבר](forum_images/3_star_rating.gif)
![סמל אישי](avatars/Sphere_animated_small_ neg2.gif)
הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת הודעות: 176
|
נשלח בתאריך: 13 January 2006 בשעה 23:28 | | IP רשוּם
|
|
|
|
קוד:
#include <iostream.h> #include <stdlib.h> signed int age; int main() { start : cout<<"Enter your age : \n"; cin>>age; if(!(age < 0) && !(age > 0) && !(age = 0)) cout<<"Not good . \n"<<endl; goto start; else cout<<"\nYou are : "<<age<<" years old . \n"<<endl; system("PAUSE"); return 0; }
|
|
|
מישהו יודע מה הבעיה פה ? כתבתי את הקוד במהדר Dev-C++ וכשאני מריץ זה רושם שגיאה :
|
חזרה לתחילת העמוד |
|
|
אורח אורח
![אורח](forum_images/0_star_rating.gif)
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 14 January 2006 בשעה 00:05 | | IP רשוּם
|
|
|
|
goto start; s/;/:
|
חזרה לתחילת העמוד |
|
|
ששש אורח
![אורח](forum_images/0_star_rating.gif)
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 14 January 2006 בשעה 02:24 | | IP רשוּם
|
|
|
|
קוד:
#include <iostream.h> #include <stdlib.h> signed int age;
int main() {
start: cout<<"Enter your age : \n"; cin>>age; if(!(age < 0) && !(age > 0) && !(age = 0)) { cout<<"Not good . \n"<<endl; goto start; }
else cout<<"\nYou are : "<<age<<" years old . \n"<<endl; system("PAUSE"); return 0;
}
|
|
|
כאשר משתמשים ב-if ובגוף התנאי יש יותר משורה אחת - רושמים את הגוף בבלוק {}
קוד:
if(תנאי)
{
שורות קוד...
.............
}
|
|
|
|
חזרה לתחילת העמוד |
|
|
AC-Milan משתמש חבר
![משתמש חבר](forum_images/3_star_rating.gif)
![סמל אישי](avatars/Sphere_animated_small_ neg2.gif)
הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת הודעות: 176
|
נשלח בתאריך: 14 January 2006 בשעה 12:17 | | IP רשוּם
|
|
|
|
ציטוט:
קוד:
#include <iostream.h> #include <stdlib.h> signed int age;
int main() {
start: cout<<"Enter your age : \n"; cin>>age; if(!(age < 0) && !(age > 0) && !(age = 0)) { cout<<"Not good . \n"<<endl; goto start; }
else cout<<"\nYou are : "<<age<<" years old . \n"<<endl; system("PAUSE"); return 0;
}
| | |
כאשר משתמשים ב-if ובגוף התנאי יש יותר משורה אחת - רושמים את הגוף בבלוק {}
קוד:
if(תנאי)
{
שורות קוד...
.............
} | |
|
|
|
תודה אחי , עובד . אבל עכשיו יש בעיה אחרת , אני נתקל בלולאה אינסופית , יש לך דרך אחרת לעשות את מה שאני רוצה ?
|
|
חזרה לתחילת העמוד |
|
|
ניר מנהל האתר
![מנהל האתר](forum_images/5_star_rating.gif)
![סמל אישי](avatars/moon.jpg)
הצטרף / הצטרפה: 12 January 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 3296
|
נשלח בתאריך: 14 January 2006 בשעה 13:48 | | IP רשוּם
|
|
|
|
- אורחים - צריך להרוג את מי שמדבר כמוכם. העפתי לכם את ההודעות.
- AC - ציטוט ממה שמורה אמר לי פעם בכיתה על GOTO:
"עכשיו נלמד על הפקודה GOTO. המילה GOTO היא מילה שמורה בשפת C/C++, כלומר אסור לכם ליצור פונקציה או משתנה שקוראים להם goto. זה כל מה שאתם צריכים לדעת על הפקודה הזו." אין שום סיבה הגיונית, למעט במקרים סופר מיוחדים (בד"כ תוכניות שמיוצרות באופן אוטומטי שאדם לא נוגע בהן) להשתמש ב-goto. - בשפת C/C++ אין כזו אפשרות לכתוב age=0 מכיוון שאז אתה מציב ב-age את הערך 0. האם התכוונת ל- (age == 0) ?
__________________ מספר האייסיקיו שלי ו/או כתובת ה-MSN שלי אינם מהווים מוקד תמיכה
|
חזרה לתחילת העמוד |
|
|
AC-Milan משתמש חבר
![משתמש חבר](forum_images/3_star_rating.gif)
![סמל אישי](avatars/Sphere_animated_small_ neg2.gif)
הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת הודעות: 176
|
נשלח בתאריך: 14 January 2006 בשעה 14:14 | | IP רשוּם
|
|
|
|
כן , התכוונתי לבדוק אם age שווה 0 .
הקוד שיש לי עכשיו :
קוד:
#include <iostream.h> #include <stdlib.h> signed int age; int main() { start : cout<<"Enter your age : \n\n"; cin>>age; if (!(age < 0) && !(age > 0) && !(age == 0)) { cout<<"Not good . \n"<<endl; goto start; } else cout<<"\nYou are : "<<age<<" years old . \n"<<endl; system("PAUSE"); return 0; }
|
|
|
כעת , אם המשתמש מקיש תוו במקום מספר , זה רושם לו שגילו 0 , אני רוצה שזה ירשום not good ושיחזור מההתחלה . [לבקש מהמשתמש את גילו שוב] .
|
חזרה לתחילת העמוד |
|
|
Fate פורומיסט על
![פורומיסט על](forum_images/4_star_rating.gif)
![סמל אישי](avatars/shapes_taran.jpg)
הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת הודעות: 571
|
נשלח בתאריך: 14 January 2006 בשעה 14:14 | | IP רשוּם
|
|
|
|
2. goto יכול להיות שימושי ולגיטימי בחלק מהמקומות...
אבל אף אחד מהמקומות האלה זה לא בא במקום איזה מבנה תיכנותי קיים.
אם אתם מתעקשים אני אוכל לשים פה דוגמא למקום שבו goto שימושי ונקי.
3. יש אפשרות ליכתוב age=0 הבעיה היא שזה לא בודק אם זה 0 אלא זה מציב 0
בage, ומחזיר את ה0 הלאה, ז"א התנאי תמיד לא נכון ז"א עם ה! לפניו הוא
תמיד נכון....
עכשיו בקשר לקוד...
אתה יודע מה זה לולאת While?
|
חזרה לתחילת העמוד |
|
|
AC-Milan משתמש חבר
![משתמש חבר](forum_images/3_star_rating.gif)
![סמל אישי](avatars/Sphere_animated_small_ neg2.gif)
הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת הודעות: 176
|
נשלח בתאריך: 14 January 2006 בשעה 14:52 | | IP רשוּם
|
|
|
|
כן יודע ...
|
חזרה לתחילת העמוד |
|
|
pitbull משתמש חבר
![משתמש חבר](forum_images/3_star_rating.gif)
![סמל אישי](avatars/side_smile.jpg)
הצטרף / הצטרפה: 14 May 2005
משתמש: מנותק/ת הודעות: 209
|
נשלח בתאריך: 14 January 2006 בשעה 14:56 | | IP רשוּם
|
|
|
|
אז אם אתה יודע, מה דחף אותך להשתמש ב goto ? כמו שניר אמר, זה לא טוב בכלל.. תשמש בלולאת while .
|
חזרה לתחילת העמוד |
|
|
shoshan מנהל האתר
![מנהל האתר](forum_images/5_star_rating.gif)
![סמל אישי](uploads/shoshan/2005-08-27_154130_SnowDog64x64.jpg)
הצטרף / הצטרפה: 16 July 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 4637
|
נשלח בתאריך: 14 January 2006 בשעה 15:35 | | IP רשוּם
|
|
|
|
טוב...הוא קלט...אל תתחילו לחזור על אותם הדברים...
__________________ עד מתי רשעים יעלוזו?
עַל כֵּן אֶמְאַס וְנִחַמְתִּי עַל עָפָר וָאֵפֶר.
|
חזרה לתחילת העמוד |
|
|
AC-Milan משתמש חבר
![משתמש חבר](forum_images/3_star_rating.gif)
![סמל אישי](avatars/Sphere_animated_small_ neg2.gif)
הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת הודעות: 176
|
נשלח בתאריך: 14 January 2006 בשעה 16:05 | | IP רשוּם
|
|
|
|
נסיתי להשתמש בלולאת While וזה מה שיצא :
קוד:
#include <iostream.h> #include <stdlib.h> signed int age; int main() { cout<<"Enter your age : \n\n"<<endl; cin>>age; if (age == 0 || age > 0 || age < 0) { cout<<"\nYou are : "<<age<<" years old . \n"<<endl; } else while (!(age < 0) && !(age > 0) && !(age == 0)) { cout<<"\n\nNot good . \n"<<endl; cout<<"Enter your age again : \n\n"<<endl; cin>>age; if (age == 0 || age > 0 || age < 0) { break; cout<<"\nYou are : "<<age<<" years old . \n"<<endl; } else continue; } system("PAUSE"); return 0; }
|
|
|
אני עדיין מקבל שהגיל הוא 0 כשאני רושם תוו במקום מספר . אני לא מצליח למצוא את הבעיה שגורמת לכך .
|
חזרה לתחילת העמוד |
|
|
אורח אורח
![אורח](forum_images/0_star_rating.gif)
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 14 January 2006 בשעה 17:17 | | IP רשוּם
|
|
|
|
במקרה שלא שמת לב, הגדרת את המשתנה כsigned int
זאת אומרת שאם תנסה להכניס אליו ערך שאינו מספר הוא יקרוס או
שהוא יכניס "זבל" לתוך המשתנה כי הוא למעשה לא יודע מה לעשות איתו
אתה יכול לפתור את הבעיה בלהגדיר משתנה מסוג char
ולבדוק את הערך.
|
חזרה לתחילת העמוד |
|
|
Fate פורומיסט על
![פורומיסט על](forum_images/4_star_rating.gif)
![סמל אישי](avatars/shapes_taran.jpg)
הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת הודעות: 571
|
נשלח בתאריך: 14 January 2006 בשעה 18:15 | | IP רשוּם
|
|
|
|
כמו שאמרתי מקודם....
אין שום מספר שלא מקיים את התנאי:
if (age == 0 || age > 0 || age < 0)
וage יכול להיות רק מספר...
|
חזרה לתחילת העמוד |
|
|
AC-Milan משתמש חבר
![משתמש חבר](forum_images/3_star_rating.gif)
![סמל אישי](avatars/Sphere_animated_small_ neg2.gif)
הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת הודעות: 176
|
נשלח בתאריך: 14 January 2006 בשעה 18:48 | | IP רשוּם
|
|
|
|
מישהו יכול להביא לי קוד שיבדוק אם הקלט הוא מספר או לא ? ככה אני אדע אם הקלט הוא מספר אז התוכנה תמשיך רגיל , אם לא אז היא תציג הודעת שגיאה מתאימה ותחזור מההתחלה .
|
חזרה לתחילת העמוד |
|
|
Fate פורומיסט על
![פורומיסט על](forum_images/4_star_rating.gif)
![סמל אישי](avatars/shapes_taran.jpg)
הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת הודעות: 571
|
נשלח בתאריך: 14 January 2006 בשעה 19:04 | | IP רשוּם
|
|
|
|
קוד:
printf("enter your age:");
while (0 == scanf("%d",&num)) {
printf("enter a number...");
}
printf("your age is %d",num);
|
|
|
|
חזרה לתחילת העמוד |
|
|
אלצ'קו אחראי פורומים
![אחראי פורומים](/images/forum/moderator.gif)
ג2ר פ33תי
הצטרף / הצטרפה: 20 January 2006
משתמש: מנותק/ת הודעות: 609
|
נשלח בתאריך: 20 January 2006 בשעה 07:06 | | IP רשוּם
|
|
|
|
Fate, אתה יכול לתת את הדוגמה שאמרת שיש לך מתי goto "שימושי ולגיטימי"(ב-CPP כמובן)?
זה נורא מעניין אותי.
|
חזרה לתחילת העמוד |
|
|
Fate פורומיסט על
![פורומיסט על](forum_images/4_star_rating.gif)
![סמל אישי](avatars/shapes_taran.jpg)
הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת הודעות: 571
|
נשלח בתאריך: 20 January 2006 בשעה 15:45 | | IP רשוּם
|
|
|
|
נניח אתה רוצה לחבר שני סוקטים ולפני זה לאתחל מבנה חדש או משהו...
אז יש לך בקוד 5 נקודות כשלון שדורשות 3 ניקוים...
קוד:
buf = new (std::nothrow) char[5];
s1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
connect(s1, ...);
s2 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
connect(s2, ...);
|
|
|
להשאיר את הקוד ככה לא סביר כי אם משהו יכשל אתה לא תדע מזה ויהיו תוצאות לא צפויות..
(כמובן שזה לא קוד שלם, זה בדילוגים)
מה שדורש בדיקת שגיאה עבור כל אחד מהם...
אבל מה עושים בכל אחד מהם אם יש שגיאה?
השיטה הרגילה זה return SOME_ERROR;
הבעיה בשיטה הזאת שאתה כל פעם צריך לנקות את מה שכן הצליח לפני זה...
קוד:
buf = new (std::nothrow) char[5];
if (NULL == buf) {
return NEW_ERROR;
}
s1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (INVALID_SOCKET_HANDLE == s1) {
delete(buf[]);
return SOCKET1_ERROR;
}
if (!connect(s1, ...)) {
delete(buf[]);
closehandle(s1);
return SOCKET1_ERROR;
}
s2 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (INVALID_SOCKET_HANDLE == s2) {
delete(buf[]);
closehandle(s1);
return SOCKET2_ERROR;
}
if (!connect(s2, ...)) {
delete(buf[]);
closehandle(s1);
closehandle(s2);
return SOCKET2_ERROR;
}
.
.
.
delete(buf());
closehandle(s1);
closehandle(s2);
return SUCCESS;
|
|
|
והשיטה הנקייה יותר כמובן זה עם goto...
קוד:
res = SUCCESS;
buf = new (std::nothrow) char[5];
if (NULL == buf) {
res = NEW_ERROR;
goto func_cleanup;
}
s1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (INVALID_SOCKET_HANDLE == s1) {
res = SOCKET1_ERROR;
goto func_cleanup;
}
if (!connect(s1, ...)) {
res = SOCKET1_ERROR;
goto func_cleanup;
}
s2 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (INVALID_SOCKET_HANDLE == s2) {
res = SOCKET2_ERROR;
goto func_cleanup;
}
if (!connect(s2, ...)) {
res = SOCKET2_ERROR;
goto func_cleanup;
}
.
.
.
//fall through from onrmal code to cleanup:
func_cleanup:
if (NULL != buf) {
delete(buf[]);
}
if (SOCKET_INVALID_HANDLE != s1) {
closehandle(s1);
}
if (SOCKET_INVALID_HANDLE != s2) {
closehandle(s2);
}
return res;
// end of function
|
|
|
וזה רק דוגמא של פונקציה שבה רק שלושה דברים שורשים ניקוי יכולים להכשל...
בפונקציות גדולות זה בד"כ יותר...
וככה גם לא קורה מצב נפוץ שקשה מאד לאתר של יציאה באמצע על שגיאה כאשר יש איזה משהו ששכחנו לשחרר...
|
חזרה לתחילת העמוד |
|
|
אורח אורח
![אורח](forum_images/0_star_rating.gif)
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 21 January 2006 בשעה 12:36 | | IP רשוּם
|
|
|
|
אין שום צורך להשתמש ב goto
אפשר להגדיר פונקציה שעושה ניקוי, ופשוט לקרוא לה.
|
חזרה לתחילת העמוד |
|
|
Fate פורומיסט על
![פורומיסט על](forum_images/4_star_rating.gif)
![סמל אישי](avatars/shapes_taran.jpg)
הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת הודעות: 571
|
נשלח בתאריך: 21 January 2006 בשעה 14:18 | | IP רשוּם
|
|
|
|
אורח כתב:
אין שום צורך להשתמש ב goto
אפשר להגדיר פונקציה שעושה ניקוי, ופשוט לקרוא לה.
|
|
|
ומה יהיה הפורמט שלה?
קוד:
void cleanup(char * buf);
void cleanup(char * buf, SOCKET s1);
void cleanup(char * buf, SOCKET s1,SOCKET s2);
|
|
|
זה נראה לך נקי יותר?
וזה עדיין לא פותר את הקטע של לשכוח לנקות משהו ביציאה, כי אם תטעה ותקרא לא לנכונה יש לך דליפה\דברים לא מנוקים...
|
חזרה לתחילת העמוד |
|
|
אורח אורח
![אורח](forum_images/0_star_rating.gif)
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 21 January 2006 בשעה 15:28 | | IP רשוּם
|
|
|
|
אין צורך להשתמש בחפיפת פונקציות במקרה הזה.
אתה יכול לקרוא לפונקציה, ובמידה ואחד השקעים לא פתוח, או זיכרון עוד לא הוקצא, לקרוא לה עם פרמטר NULL.
ואז בתוך הפונקצייה להוסיף בדיקה
if(buf!=NULL(
free(buf);
וכנ"ל עם השקעים
|
חזרה לתחילת העמוד |
|
|
Fate פורומיסט על
![פורומיסט על](forum_images/4_star_rating.gif)
![סמל אישי](avatars/shapes_taran.jpg)
הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת הודעות: 571
|
נשלח בתאריך: 21 January 2006 בשעה 16:22 | | IP רשוּם
|
|
|
|
זה אפשרי,
אבל זה נראה לי יותר מסורבל...
הדוגמא פה זה רק 3 דברים, ורק לפונקציה אחת...
אז כל פונקציה אתה תכתוב עוד פונקציית ניקוי עם כמות פרמטרים ככמות המקומות שיכולים להכשל ודורשים ניקוי?
וgoto בכל מקרה הרבה יותר יעיל מבחינת זמן ביצוע וOverhead בEXE.
|
חזרה לתחילת העמוד |
|
|
AC-Milan משתמש חבר
![משתמש חבר](forum_images/3_star_rating.gif)
![סמל אישי](avatars/Sphere_animated_small_ neg2.gif)
הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת הודעות: 176
|
נשלח בתאריך: 23 January 2006 בשעה 19:20 | | IP רשוּם
|
|
|
|
הבעיה שלי נפתרה , בסוף ראיתי מישו שכתב תגובה למישו אחר באותו נושא , הוא השתמש בלולאת Do While .
אם אתם לא צריכים יותר את הנושא , אתם יכולים לנעול .
|
חזרה לתחילת העמוד |
|
|
אורח אורח
![אורח](forum_images/0_star_rating.gif)
הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין הודעות: 12647
|
נשלח בתאריך: 24 January 2006 בשעה 13:12 | | IP רשוּם
|
|
|
|
למה לנעול?
יש לי עוד דבר לומר בנושא של ה goto.
ניתן לפתור את הבעיה הזו ב C++, ע"י פונקציה "הורסת".
בקשר ל C, אני מניח שהשימוש ב goto יהיה הרבה יותר אלגנטי.
|
חזרה לתחילת העמוד |
|
|
Fate פורומיסט על
![פורומיסט על](forum_images/4_star_rating.gif)
![סמל אישי](avatars/shapes_taran.jpg)
הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת הודעות: 571
|
נשלח בתאריך: 24 January 2006 בשעה 18:36 | | IP רשוּם
|
|
|
|
אורח כתב:
למה לנעול?
יש לי עוד דבר לומר בנושא של ה goto.
ניתן לפתור את הבעיה הזו ב C++, ע"י פונקציה "הורסת".
בקשר ל C, אני מניח שהשימוש ב goto יהיה הרבה יותר אלגנטי.
|
|
|
פונקציה הורסת יש רק בקלאסים, לא כל פונקציה (אלא אם כן כל הפונקציות שלך הן חלק מקלאסים :)..
ובC++ באמת יש פתרון אחר למשל Exceptions...
שזה יותר סוג של אותו מבנה כמו הgoto...
|
חזרה לתחילת העמוד |
|
|
אלצ'קו אחראי פורומים
![אחראי פורומים](/images/forum/moderator.gif)
ג2ר פ33תי
הצטרף / הצטרפה: 20 January 2006
משתמש: מנותק/ת הודעות: 609
|
נשלח בתאריך: 13 August 2006 בשעה 01:52 | | IP רשוּם
|
|
|
|
בדיוק. במקום goto-ים ו-free-ים ובלאגן אטומי, הקוד אמור להראות בערך כך:
קוד:
string buf;
scoket s1, s2;
try
{
s1.allocsocket();
}
catch (bla)
{
...
}
try
{
s1.connect(...);
}
catch (bla bla)
{
...
}
...
try
{
s2.connect(...);
}
catch (bla bla bla)
{
...
}
// at the end-of-scope the following are called:
// buf.~string
// s1.~socket
// s2.~socket
// that free allocated resources properly,
// and since they're on the stack, the objects themselves are then freed.
|
|
|
וזה הרבה יותר נקי, ברור ובטיחותי.
|
חזרה לתחילת העמוד |
|
|
Fate פורומיסט על
![פורומיסט על](forum_images/4_star_rating.gif)
![סמל אישי](avatars/shapes_taran.jpg)
הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת הודעות: 571
|
נשלח בתאריך: 14 August 2006 בשעה 01:49 | | IP רשוּם
|
|
|
|
הבעיה בקוד שלך כאן זה שאם החיבור הראשון נכשל... הוא ממשיך ומבצע את החיבור השני... אני לא רוצה שהוא יעשה את זה...
ואם השני נכשל אני רוצה שהוא יסגור את הראשון ולא ימשיך לשלישי... כרגע אצלך בקוד זה עושה ניקוי נכון של הכל אבל מריץ את כל השלושה במקום לצאת בכשלון.
|
חזרה לתחילת העמוד |
|
|
shoshan מנהל האתר
![מנהל האתר](forum_images/5_star_rating.gif)
![סמל אישי](uploads/shoshan/2005-08-27_154130_SnowDog64x64.jpg)
הצטרף / הצטרפה: 16 July 2005 מדינה: Israel
משתמש: מנותק/ת הודעות: 4637
|
נשלח בתאריך: 14 August 2006 בשעה 02:08 | | IP רשוּם
|
|
|
|
נראה לי שאתה יכול לשים את כל ההתחברויות ב-try אחד [ואולי אחרי כל אחד לשמור במשתנה שההתחברות מוצלחת], וב-fianally של ה-try הזה לסגור את ההתחברויות שהצליחו [אולי תעשה try-ים נפרדים לסגירת כל אחד מהןף כדי שכישלון שגירה אחד לא ישפיעה על סגירה אחרת].
__________________ עד מתי רשעים יעלוזו?
עַל כֵּן אֶמְאַס וְנִחַמְתִּי עַל עָפָר וָאֵפֶר.
|
חזרה לתחילת העמוד |
|
|
אלצ'קו אחראי פורומים
![אחראי פורומים](/images/forum/moderator.gif)
ג2ר פ33תי
הצטרף / הצטרפה: 20 January 2006
משתמש: מנותק/ת הודעות: 609
|
נשלח בתאריך: 14 August 2006 בשעה 06:59 | | IP רשוּם
|
|
|
|
Fate כתב:
הבעיה בקוד שלך כאן זה שאם החיבור הראשון נכשל... הוא ממשיך ומבצע את החיבור השני... אני לא רוצה שהוא יעשה את זה...
ואם השני נכשל אני רוצה שהוא יסגור את הראשון ולא ימשיך לשלישי... כרגע אצלך בקוד זה עושה ניקוי נכון של הכל אבל מריץ את כל השלושה במקום לצאת בכשלון. |
|
|
זו לא באמת בעיה. הנה שינוי כמו שאתה רוצה:
קוד:
string buf;
scoket s1, s2;
try
{
s1.allocsocket();
}
catch (bla)
{
...
return cBadSocketAlloc;
}
try
{
s1.connect(...);
}
catch (bla bla)
{
...
return cConnectionFailure;
}
...
try
{
s2.connect(...);
}
catch (bla bla bla)
{
...
return cConnectionFailure;
}
|
|
|
וזה עדיין הרבה יותר נקי וברור מהגרסה עם ה-goto-ים. הסיבה שהקוד
למעלה לא היה בדיוק מה שביקשת היא שפשוט לא הבנתי את הקוד עם ה-goto-ים.
זה הייתרון היחיד שלו - הוא מבלבל אנשים אחרים.
shoshan כתב:
נראה לי שאתה יכול לשים את כל ההתחברויות ב-try אחד [ואולי אחרי כל אחד לשמור במשתנה שההתחברות מוצלחת],
וב-fianally
של ה-try הזה לסגור את ההתחברויות שהצליחו [אולי תעשה try-ים נפרדים
לסגירת כל אחד מהןף כדי שכישלון שגירה אחד לא ישפיעה על סגירה אחרת].
|
|
|
ב-CPP אין בלוק finally (לפחות היום; יש תכנון להוסיף אחד ל-C++0x), ולפי
סרטוסרטופ מסיבה טובה - כל מה שעושים ב-finally אפשר לעשות במפרקים. הקוד
שלי לא צריך בלוק finally כדי לשחרר משאבים, כי הסוקטים משתחררים במפרקים
של האובייקטים ממחלקת socket, הזיכרון של הבאפר משתחרר במפרק של האובייקט
ממחלקת string וכו.
|
חזרה לתחילת העמוד |
|
|
Fate פורומיסט על
![פורומיסט על](forum_images/4_star_rating.gif)
![סמל אישי](avatars/shapes_taran.jpg)
הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת הודעות: 571
|
נשלח בתאריך: 14 August 2006 בשעה 19:02 | | IP רשוּם
|
|
|
|
כמו שאמרתי בC++ יש דרכים לכתוב משהו הרבה יותר יפה ואלגנטי בגלל הDestructors.
אבל בC אתה צריך ידנית להשמיד כל אוביקט אם נוצר כזה... ז"א אם אתה יוצר 5 קטעי זיכרון אחר אחרי השני וצריך לנקות אותם לפני הReturn... אז בתוך הcatch שלך יהיה כמות הולכת וגודלת של free של מה שהצליח לפני...
|
חזרה לתחילת העמוד |
|
|
אלצ'קו אחראי פורומים
![אחראי פורומים](/images/forum/moderator.gif)
ג2ר פ33תי
הצטרף / הצטרפה: 20 January 2006
משתמש: מנותק/ת הודעות: 609
|
נשלח בתאריך: 14 August 2006 בשעה 20:59 | | IP רשוּם
|
|
|
|
Fate כתב:
כמו שאמרתי בC++ יש דרכים לכתוב משהו הרבה יותר יפה ואלגנטי בגלל הDestructors.
אבל בC אתה צריך ידנית להשמיד כל אוביקט אם נוצר כזה... ז"א אם אתה יוצר 5 קטעי זיכרון אחר אחרי השני וצריך לנקות אותם לפני הReturn... אז בתוך הcatch שלך יהיה כמות הולכת וגודלת של free של מה שהצליח לפני...
|
|
|
שני דברים בקשר לזה:
ראשית, כותרת האשכול אומרת CPP, ואנחנו עוסקים בפתרונות עבור CPP. ב-C יש המון בעיות שנפתרות טריוויאלית ב-C, וזו רק אחת מהן.
שנית, גם ב-C אפשר לכתוב קוד נקי ויפה במקרה הזה. לא נקי ויפה כמו ב-CPP,
אבל הרבה יותר נקי מאשר קוד שכולל goto-ים (שישר נופל למקום האחרון, מה
שלא יהיה).
במקום המחלקה socket נגדיר struct בשם זה, ובמקום הפונקציות החברות שלה,
יהיו לנו פונקציות רגילות (פונקציות חברות, אגב, גם הן פונקציות "רגילות",
שמקבלות את this כ"פרמטר חבוי").
נוכל לעשות משהו כזה:
קוד:
typedef socket* psocket
pscoket s1, s2;
bool succ;
enumErrType retval;
initsocketstruct(s1)
initsocketstruct(s2)
succ = allocsocket(s1)
if (!succ) {retval=etBadSocketAlloc;}
else
{
succ = connect(s1,...);
if (!succ) {retval=etConnectionFailure;}
}
...
succ = connect(s1,...);
if (!succ) {retval=etConnectionFailure;}
...
release(s1);
release(s2);
return retval;
|
|
|
אנחנו "משחררים" את כל הסוקטים שלנו בכל מקרה בסוף. ה-struct שומר את
כל המידע בפנים, וכך אם הסוקט מחובר, הוא מתנתק בתוך release (ואם לא, אז
לא)ף אם הוא מאותחל הוא משוחרר למערכת (ואם לא, אז לא), וכו'.
אם עניין ה-if-ים מטריד אותך (חיבור רק if איתחול הסוקט הצליח), אפשר
לעשות את כל השיחרורים אחרי כל בדיקת שגיאה, וזה יפעל טוב באותה מידה (ולא
יהיה קטע של "בכל מצב צריך לשחרר משהו אחר" - תמיד משחררים הכל, ופונקציות
השחרור דואגות לפרטים). לא כתבתי את זה כי זה סתם היה עושה את הקוד קצת
יותר ארוך, ולא משנה שום דבר מהותי.
|
חזרה לתחילת העמוד |
|
|
Fate פורומיסט על
![פורומיסט על](forum_images/4_star_rating.gif)
![סמל אישי](avatars/shapes_taran.jpg)
הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת הודעות: 571
|
נשלח בתאריך: 14 August 2006 בשעה 21:25 | | IP רשוּם
|
|
|
|
אם אתה משחרר את הstructים בסוף אז אתה תמיד מגיע לסוף הפונקציה... גם כשיש לך שגיאה בסוקט אתה ממשיך לחבר עוד סוקטים למרות שצריך כבר לנקות ולצאת...
אתה יכול לפתור את זה עם if שבודק את הretval לפני כל כניסה לעוד חיבור סוקט. ואז זה הופך את זה למגעיל שוב....
או שאתה ממשיך עם הקטע של הif והמשך החיבורים של הסוקטים הם בתוך הelse.. ואז אתה מגיע ל10 nesting של if שגורם לקוד להראות כמו גוש חרא :P...
כדי לא להסתבך עם מקרים תיאורטיים בוא נגיד שהפונקצייה שלנו מקבלת באפר, וצריכה להחזיר 4 העתקים שלו בפרמטרים, וTRUE כשהוא מצליח. כמובן שכאשר אילקוץ אחד נכשל אז לא מבזבזים זיכרון וממשיכים לאלקץ עוד.
כמובן בסי....
הערה: הנושא המקורי מזמן הסתיים, כרגע אנחנו מדיינים אם שימוש בgoto לגיטימי במקרה כלשהו או לא...
הנה איך שקוד שלי היה נראה....
קוד:
BOOL Copy4Buf(char * szSrc,char ** pszDst1,char ** pszDst2,char ** pszDst3,char ** pszDst4) { unsigned long dwLen = strlen(szSrc) + 1; bool bRet = FALSE;
*pszDst1 = malloc(dwLen); if (NULL == *pszDst1) { goto clean; } *pszDst2 = malloc(dwLen); if (NULL == *pszDst2) { goto clean; } *pszDst3 = malloc(dwLen); if (NULL == *pszDst3) { goto clean; } *pszDst4 = malloc(dwLen); if (NULL == *pszDst4) { goto clean; }
strcpy(*pszDst1,szSrc); strcpy(*pszDst2,szSrc); strcpy(*pszDst3,szSrc); strcpy(*pszDst4,szSrc);
bRet = TRUE;
clean: if (NULL != *pszDst1) { free(*pszDst1); } if (NULL != *pszDst2) { free(*pszDst2); } if (NULL != *pszDst3) { free(*pszDst3); } if (NULL != *pszDst4) { free(*pszDst4); } return bRet; }
|
|
|
|
חזרה לתחילת העמוד |
|
|
אלצ'קו אחראי פורומים
![אחראי פורומים](/images/forum/moderator.gif)
ג2ר פ33תי
הצטרף / הצטרפה: 20 January 2006
משתמש: מנותק/ת הודעות: 609
|
נשלח בתאריך: 14 August 2006 בשעה 22:45 | | IP רשוּם
|
|
|
|
Fate כתב:
אם אתה משחרר את הstructים בסוף אז אתה תמיד מגיע לסוף הפונקציה... גם כשיש לך שגיאה בסוקט אתה ממשיך לחבר עוד סוקטים למרות שצריך כבר לנקות ולצאת...
אתה יכול לפתור את זה עם if שבודק את הretval לפני כל כניסה לעוד חיבור סוקט. ואז זה הופך את זה למגעיל שוב....
או שאתה ממשיך עם הקטע של הif והמשך החיבורים של הסוקטים הם בתוך הelse.. ואז אתה מגיע ל10 nesting של if שגורם לקוד להראות כמו גוש חרא :P...
|
|
|
ההודעה שכתבתי נמחקה לי, אז נקצר בפעם השניה:
בדיקת if (bcontinue) בכלב שלב היא רק שורה אחת יותר, בדיוק כמו שורת
ה-goto. כולל הסוגריים המסולסלות זה עוד שתי שורות(!!), אבל לא נראה לי
שזה ממש נורא.
האפשרות השניה, כפי שציינתי, היא ביצוע כל השחרורים כל פעם, ו-return
במקום, אבל זה מאריך את הקוד. (אפשר להתגבר על זה ע"י פונקציה ייעודית,
שתסבך את הקוד לדעתי, וסביר להניח שתפגום בביצועים במידה זו או אחרת)
הגרסה שלי לקוד שלך תהיה משהו בסגנון:
שות משהו כזה:
קוד:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef char* pchar;
int strangecpy(pchar ssrc, pchar* sdst1, pchar* sdst2, pchar* sdst3, pchar* sdst4)
{
char lastno;
int slen;
slen = strlen(ssrc);
*sdst1 = (pchar) malloc(slen);
if (sdst1)
{
lastno=1;
*sdst2 = (pchar) malloc(slen);
}
if (sdst3)
{
lastno=2;
*sdst3 = (pchar) malloc(slen);
}
if (sdst3)
{
lastno=3;
*sdst4 = (pchar) malloc(slen);
}
if (*sdst4)
{
lastno = 4;
strcpy(*sdst1, ssrc);
strcpy(*sdst2, ssrc);
strcpy(*sdst3, ssrc);
strcpy(*sdst4, ssrc);
return 1;
}
switch (lastno)
{
case 3:
free(*sdst3);
case 2:
free(*sdst2);
case 1:
free(*sdst1);
}
return 0;
}
int main(void)
{
char *s1;
char *s2,*s3,*s4,*s5;
int retval;
s1 = (char*)malloc(13);
s1 = "hello world!";
retval = strangecpy(s1,&s2,&s3,&s4,&s5);
if (retval) printf("s1: %s\ns2: %s\ns3: %s\ns4: %s\ns5: %s\n", s1, s2, s3, s4, s5);
else printf("bummer, only\ns1: %s\n", s1);
return 0;
}
|
|
|
קצת מזעזע, אבל כל קוד ב-C קצת מזעזע, במקרה הטוב. זה לא הרבה יותר נורא מהעסק עם ה-goto-ים, ולא מרגיל אותנו להשתמש בהם.
|
חזרה לתחילת העמוד |
|
|
aassaa1 משתמש מתחיל
![משתמש מתחיל](forum_images/1_star_rating.gif)
הצטרף / הצטרפה: 24 August 2006 מדינה: Israel
משתמש: מנותק/ת הודעות: 6
|
נשלח בתאריך: 24 August 2006 בשעה 16:15 | | IP רשוּם
|
|
|
|
רק בשביל ידע כללי הדרך היחדה ששפת מכונה מבצעת לולאות בדיקות וכדו' זה ע"י goto (באסמבלי זה jmp)
|
חזרה לתחילת העמוד |
|
|