נושאים פעיליםנושאים פעילים  הצגת רשימה של חברי הפורוםרשימת משתמשים  חיפוש בפורוםחיפוש  עזרהעזרה
  הרשמההרשמה  התחברותהתחברות RSS עדכונים
תיכנות
RSS UnderWarrior Forums : RSS תיכנות
נושא

נושא: בעיה בקוד בשפת ++C .

שליחת תגובהשליחת נושא חדש
כותב
הודעה << נושא קודם | נושא הבא >>
AC-Milan
משתמש חבר
משתמש חבר
סמל אישי

הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת
הודעות: 176
נשלח בתאריך: 13 January 2006 בשעה 23:28 | IP רשוּם
ציטוט AC-Milan

קוד:

#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++ וכשאני מריץ זה רושם שגיאה :

ציטוט:

 parse error before `else

חזרה לתחילת העמוד הצג את כרטיס החבר של AC-Milan חפש הודעות אחרות של AC-Milan
 
אורח
אורח
אורח


הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין
הודעות: 12647
נשלח בתאריך: 14 January 2006 בשעה 00:05 | IP רשוּם
ציטוט אורח

goto start;
s/;/:
חזרה לתחילת העמוד הצג את כרטיס החבר של אורח חפש הודעות אחרות של אורח בקר בדף הבית של אורח
 
ששש
אורח
אורח


הצטרף / הצטרפה: 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
משתמש חבר
משתמש חבר
סמל אישי

הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת
הודעות: 176
נשלח בתאריך: 14 January 2006 בשעה 12:17 | IP רשוּם
ציטוט AC-Milan

ציטוט:

קוד:

#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 חפש הודעות אחרות של AC-Milan
 
ניר
מנהל האתר
מנהל האתר
סמל אישי

הצטרף / הצטרפה: 12 January 2005
מדינה: Israel
משתמש: מנותק/ת
הודעות: 3296
נשלח בתאריך: 14 January 2006 בשעה 13:48 | IP רשוּם
ציטוט ניר

  1. אורחים - צריך להרוג את מי שמדבר כמוכם. העפתי לכם את ההודעות.
  2. AC - ציטוט ממה שמורה אמר לי פעם בכיתה על GOTO:
    "עכשיו נלמד על הפקודה GOTO. המילה GOTO היא מילה שמורה בשפת C/C++,  כלומר אסור לכם ליצור פונקציה או משתנה שקוראים להם goto. זה כל מה שאתם צריכים לדעת על הפקודה הזו."
    אין שום סיבה הגיונית, למעט במקרים סופר מיוחדים (בד"כ תוכניות שמיוצרות באופן אוטומטי שאדם לא נוגע בהן) להשתמש ב-goto.
  3. בשפת C/C++ אין כזו אפשרות לכתוב age=0 מכיוון שאז אתה מציב ב-age את הערך 0. האם התכוונת ל- (age == 0) ?


__________________
מספר האייסיקיו שלי ו/או כתובת ה-MSN שלי אינם מהווים מוקד תמיכה
חזרה לתחילת העמוד הצג את כרטיס החבר של ניר חפש הודעות אחרות של ניר בקר בדף הבית של ניר
 
AC-Milan
משתמש חבר
משתמש חבר
סמל אישי

הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת
הודעות: 176
נשלח בתאריך: 14 January 2006 בשעה 14:14 | IP רשוּם
ציטוט AC-Milan

כן , התכוונתי לבדוק אם 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 ושיחזור מההתחלה . [לבקש מהמשתמש את גילו שוב] .

 

חזרה לתחילת העמוד הצג את כרטיס החבר של AC-Milan חפש הודעות אחרות של AC-Milan
 
Fate
פורומיסט על
פורומיסט על
סמל אישי

הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת
הודעות: 571
נשלח בתאריך: 14 January 2006 בשעה 14:14 | IP רשוּם
ציטוט Fate

2. goto יכול להיות שימושי ולגיטימי בחלק מהמקומות...
אבל אף אחד מהמקומות האלה זה לא בא במקום איזה מבנה תיכנותי קיים.
אם אתם מתעקשים אני אוכל לשים פה דוגמא למקום שבו goto שימושי ונקי.
3. יש אפשרות ליכתוב age=0 הבעיה היא שזה לא בודק אם זה 0 אלא זה מציב 0 בage, ומחזיר את ה0 הלאה, ז"א התנאי תמיד לא נכון ז"א עם ה! לפניו הוא תמיד נכון....

עכשיו בקשר לקוד...
אתה יודע מה זה לולאת While?
חזרה לתחילת העמוד הצג את כרטיס החבר של Fate חפש הודעות אחרות של Fate
 
AC-Milan
משתמש חבר
משתמש חבר
סמל אישי

הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת
הודעות: 176
נשלח בתאריך: 14 January 2006 בשעה 14:52 | IP רשוּם
ציטוט AC-Milan

כן יודע ...
חזרה לתחילת העמוד הצג את כרטיס החבר של AC-Milan חפש הודעות אחרות של AC-Milan
 
pitbull
משתמש חבר
משתמש חבר
סמל אישי

הצטרף / הצטרפה: 14 May 2005
משתמש: מנותק/ת
הודעות: 209
נשלח בתאריך: 14 January 2006 בשעה 14:56 | IP רשוּם
ציטוט pitbull

אז אם אתה יודע, מה דחף אותך להשתמש ב  goto ?
כמו שניר אמר, זה לא טוב בכלל..
תשמש בלולאת while .
חזרה לתחילת העמוד הצג את כרטיס החבר של pitbull חפש הודעות אחרות של pitbull
 
shoshan
מנהל האתר
מנהל האתר
סמל אישי

הצטרף / הצטרפה: 16 July 2005
מדינה: Israel
משתמש: מנותק/ת
הודעות: 4637
נשלח בתאריך: 14 January 2006 בשעה 15:35 | IP רשוּם
ציטוט shoshan

טוב...הוא קלט...אל תתחילו לחזור על אותם הדברים...

__________________
עד מתי רשעים יעלוזו?

עַל כֵּן אֶמְאַס וְנִחַמְתִּי עַל עָפָר וָאֵפֶר.
חזרה לתחילת העמוד הצג את כרטיס החבר של shoshan חפש הודעות אחרות של shoshan בקר בדף הבית של shoshan
 
AC-Milan
משתמש חבר
משתמש חבר
סמל אישי

הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת
הודעות: 176
נשלח בתאריך: 14 January 2006 בשעה 16:05 | IP רשוּם
ציטוט AC-Milan

נסיתי להשתמש בלולאת 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 כשאני רושם תוו במקום מספר . אני לא מצליח למצוא את הבעיה שגורמת לכך .

 

חזרה לתחילת העמוד הצג את כרטיס החבר של AC-Milan חפש הודעות אחרות של AC-Milan
 
אורח
אורח
אורח


הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין
הודעות: 12647
נשלח בתאריך: 14 January 2006 בשעה 17:17 | IP רשוּם
ציטוט אורח

במקרה שלא שמת לב, הגדרת את המשתנה כsigned int
זאת אומרת שאם תנסה להכניס אליו ערך שאינו מספר הוא יקרוס או
שהוא יכניס "זבל" לתוך המשתנה כי הוא למעשה לא יודע מה לעשות איתו
אתה יכול לפתור את הבעיה בלהגדיר משתנה מסוג char
ולבדוק את הערך.
חזרה לתחילת העמוד הצג את כרטיס החבר של אורח חפש הודעות אחרות של אורח בקר בדף הבית של אורח
 
Fate
פורומיסט על
פורומיסט על
סמל אישי

הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת
הודעות: 571
נשלח בתאריך: 14 January 2006 בשעה 18:15 | IP רשוּם
ציטוט Fate

כמו שאמרתי מקודם....
אין שום מספר שלא מקיים את התנאי:
if (age == 0 || age > 0 || age < 0)

וage יכול להיות רק מספר...
חזרה לתחילת העמוד הצג את כרטיס החבר של Fate חפש הודעות אחרות של Fate
 
AC-Milan
משתמש חבר
משתמש חבר
סמל אישי

הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת
הודעות: 176
נשלח בתאריך: 14 January 2006 בשעה 18:48 | IP רשוּם
ציטוט AC-Milan

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

חזרה לתחילת העמוד הצג את כרטיס החבר של AC-Milan חפש הודעות אחרות של AC-Milan
 
Fate
פורומיסט על
פורומיסט על
סמל אישי

הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת
הודעות: 571
נשלח בתאריך: 14 January 2006 בשעה 19:04 | IP רשוּם
ציטוט Fate

קוד:

printf("enter your age:");
while (0 == scanf("%d",&num)) {
 printf("enter a number...");
}
printf("your age is %d",num);
חזרה לתחילת העמוד הצג את כרטיס החבר של Fate חפש הודעות אחרות של Fate
 
אלצ'קו
אחראי פורומים
אחראי פורומים
סמל אישי
ג2ר פ33תי

הצטרף / הצטרפה: 20 January 2006
משתמש: מנותק/ת
הודעות: 609
נשלח בתאריך: 20 January 2006 בשעה 07:06 | IP רשוּם
ציטוט אלצ'קו

Fate, אתה יכול לתת את הדוגמה שאמרת שיש לך מתי goto "שימושי ולגיטימי"(ב-CPP כמובן)?
זה נורא מעניין אותי.
חזרה לתחילת העמוד הצג את כרטיס החבר של אלצ'קו חפש הודעות אחרות של אלצ'קו
 
Fate
פורומיסט על
פורומיסט על
סמל אישי

הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת
הודעות: 571
נשלח בתאריך: 20 January 2006 בשעה 15:45 | IP רשוּם
ציטוט Fate

נניח אתה רוצה לחבר שני סוקטים ולפני זה לאתחל מבנה חדש או משהו...
אז יש לך בקוד 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


וזה רק דוגמא של פונקציה שבה רק שלושה דברים שורשים ניקוי יכולים להכשל...
בפונקציות גדולות זה בד"כ יותר...

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

חזרה לתחילת העמוד הצג את כרטיס החבר של Fate חפש הודעות אחרות של Fate
 
אורח
אורח
אורח


הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין
הודעות: 12647
נשלח בתאריך: 21 January 2006 בשעה 12:36 | IP רשוּם
ציטוט אורח

אין שום צורך להשתמש ב goto
אפשר להגדיר פונקציה שעושה ניקוי, ופשוט לקרוא לה.

חזרה לתחילת העמוד הצג את כרטיס החבר של אורח חפש הודעות אחרות של אורח בקר בדף הבית של אורח
 
Fate
פורומיסט על
פורומיסט על
סמל אישי

הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת
הודעות: 571
נשלח בתאריך: 21 January 2006 בשעה 14:18 | IP רשוּם
ציטוט Fate

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



ומה יהיה הפורמט שלה?
קוד:

void cleanup(char * buf);
void cleanup(char * buf, SOCKET s1);
void cleanup(char * buf, SOCKET s1,SOCKET s2);

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

חזרה לתחילת העמוד הצג את כרטיס החבר של Fate חפש הודעות אחרות של Fate
 
אורח
אורח
אורח


הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין
הודעות: 12647
נשלח בתאריך: 21 January 2006 בשעה 15:28 | IP רשוּם
ציטוט אורח

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

if(buf!=NULL(
free(buf);

וכנ"ל עם השקעים



חזרה לתחילת העמוד הצג את כרטיס החבר של אורח חפש הודעות אחרות של אורח בקר בדף הבית של אורח
 
Fate
פורומיסט על
פורומיסט על
סמל אישי

הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת
הודעות: 571
נשלח בתאריך: 21 January 2006 בשעה 16:22 | IP רשוּם
ציטוט Fate

זה אפשרי,

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

וgoto בכל מקרה הרבה יותר יעיל מבחינת זמן ביצוע וOverhead בEXE.
חזרה לתחילת העמוד הצג את כרטיס החבר של Fate חפש הודעות אחרות של Fate
 
AC-Milan
משתמש חבר
משתמש חבר
סמל אישי

הצטרף / הצטרפה: 27 July 2005
משתמש: מנותק/ת
הודעות: 176
נשלח בתאריך: 23 January 2006 בשעה 19:20 | IP רשוּם
ציטוט AC-Milan

הבעיה שלי נפתרה , בסוף ראיתי מישו שכתב תגובה למישו אחר באותו נושא , הוא השתמש בלולאת Do While .

אם אתם לא צריכים יותר את הנושא , אתם יכולים לנעול .

חזרה לתחילת העמוד הצג את כרטיס החבר של AC-Milan חפש הודעות אחרות של AC-Milan
 
אורח
אורח
אורח


הצטרף / הצטרפה: 01 October 2003
משתמש: אונליין
הודעות: 12647
נשלח בתאריך: 24 January 2006 בשעה 13:12 | IP רשוּם
ציטוט אורח

למה לנעול?
יש לי עוד דבר לומר בנושא של ה goto.

ניתן לפתור את הבעיה הזו ב C++, ע"י פונקציה "הורסת".
בקשר ל C, אני מניח שהשימוש ב goto יהיה הרבה יותר אלגנטי.

חזרה לתחילת העמוד הצג את כרטיס החבר של אורח חפש הודעות אחרות של אורח בקר בדף הבית של אורח
 
Fate
פורומיסט על
פורומיסט על
סמל אישי

הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת
הודעות: 571
נשלח בתאריך: 24 January 2006 בשעה 18:36 | IP רשוּם
ציטוט Fate

אורח כתב:
למה לנעול?
יש לי עוד דבר לומר בנושא של ה goto.

ניתן לפתור את הבעיה הזו ב C++, ע"י פונקציה "הורסת".
בקשר ל C, אני מניח שהשימוש ב goto יהיה הרבה יותר אלגנטי.



פונקציה הורסת יש רק בקלאסים, לא כל פונקציה (אלא אם כן כל הפונקציות שלך הן חלק מקלאסים :)..

ובC++ באמת יש פתרון אחר למשל Exceptions...
שזה יותר סוג של אותו מבנה כמו הgoto...


חזרה לתחילת העמוד הצג את כרטיס החבר של Fate חפש הודעות אחרות של Fate
 
אלצ'קו
אחראי פורומים
אחראי פורומים
סמל אישי
ג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
פורומיסט על
פורומיסט על
סמל אישי

הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת
הודעות: 571
נשלח בתאריך: 14 August 2006 בשעה 01:49 | IP רשוּם
ציטוט Fate

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

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


חזרה לתחילת העמוד הצג את כרטיס החבר של Fate חפש הודעות אחרות של Fate
 
shoshan
מנהל האתר
מנהל האתר
סמל אישי

הצטרף / הצטרפה: 16 July 2005
מדינה: Israel
משתמש: מנותק/ת
הודעות: 4637
נשלח בתאריך: 14 August 2006 בשעה 02:08 | IP רשוּם
ציטוט shoshan

נראה לי שאתה יכול לשים את כל ההתחברויות ב-try אחד [ואולי אחרי כל אחד לשמור במשתנה שההתחברות מוצלחת],
וב-fianally של ה-try הזה לסגור את ההתחברויות שהצליחו [אולי תעשה try-ים נפרדים לסגירת כל אחד מהןף כדי שכישלון שגירה אחד לא ישפיעה על סגירה אחרת].


__________________
עד מתי רשעים יעלוזו?

עַל כֵּן אֶמְאַס וְנִחַמְתִּי עַל עָפָר וָאֵפֶר.
חזרה לתחילת העמוד הצג את כרטיס החבר של shoshan חפש הודעות אחרות של shoshan בקר בדף הבית של shoshan
 
אלצ'קו
אחראי פורומים
אחראי פורומים
סמל אישי
ג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
פורומיסט על
פורומיסט על
סמל אישי

הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת
הודעות: 571
נשלח בתאריך: 14 August 2006 בשעה 19:02 | IP רשוּם
ציטוט Fate

כמו שאמרתי בC++ יש דרכים לכתוב משהו הרבה יותר יפה ואלגנטי בגלל הDestructors.

אבל בC אתה צריך ידנית להשמיד כל אוביקט אם נוצר כזה...
ז"א אם אתה יוצר 5 קטעי זיכרון אחר אחרי השני וצריך לנקות אותם לפני הReturn...
אז בתוך הcatch שלך יהיה כמות הולכת וגודלת של free של מה שהצליח לפני...


חזרה לתחילת העמוד הצג את כרטיס החבר של Fate חפש הודעות אחרות של Fate
 
אלצ'קו
אחראי פורומים
אחראי פורומים
סמל אישי
ג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
פורומיסט על
פורומיסט על
סמל אישי

הצטרף / הצטרפה: 25 October 2005
משתמש: מנותק/ת
הודעות: 571
נשלח בתאריך: 14 August 2006 בשעה 21:25 | IP רשוּם
ציטוט Fate

אם אתה משחרר את ה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;
}

חזרה לתחילת העמוד הצג את כרטיס החבר של Fate חפש הודעות אחרות של Fate
 
אלצ'קו
אחראי פורומים
אחראי פורומים
סמל אישי
ג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
משתמש מתחיל
משתמש מתחיל


הצטרף / הצטרפה: 24 August 2006
מדינה: Israel
משתמש: מנותק/ת
הודעות: 6
נשלח בתאריך: 24 August 2006 בשעה 16:15 | IP רשוּם
ציטוט aassaa1

רק בשביל ידע כללי הדרך היחדה ששפת מכונה מבצעת לולאות בדיקות וכדו' זה ע"י goto (באסמבלי זה jmp)
חזרה לתחילת העמוד הצג את כרטיס החבר של aassaa1 חפש הודעות אחרות של aassaa1
 

אם ברצונך להגיב לנושא זה עליך קודם להתחבר
אם אינך רשום/ה כבר עליך להרשם

  שליחת תגובהשליחת נושא חדש
גרסת הדפסה גרסת הדפסה

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