עבור לתוכן

שאלה נוספת - פונקציה בC

Featured Replies

פורסם

שלום

למה זה עף לי בשורה שהמוסמנת בכוכביות?

#include <stdio.h>
#include <stdlib.h>
#define N 20
void printFormat1(float );
void printFormat2(float );
void printMat(const float mat[][N],int , void(*)());
void printArray(const float [],int ,void(*)());
void main()
{
int n=0;
void (*print)();
float mat[][N]=
{
{7,2,3,5},
{1,0,0,0},
{2,0,0,1},
{0,0,0,-2.99F},
{0,1,-1,-5.123F},
{0,0,0,0}
};
puts("Press 1 if you want to print with only 1 digit precision.");
puts("Press any other number for 2 digits precision:");
scanf("%d",n);
print=n==1?&printFormat1:&printFormat2; ************************************
printMat(mat,sizeof(mat),print);
}
void printFormat1(float n)
{
printf("%.1f ",n);
}
void printFormat2(float n)
{
printf("%.2f ",n);
}
void printArray(const float mat[],int n,void (*print)())
{
if(n!=1)
printArray(mat,n-1,print);
if(mat[n])
{
print(mat[n]);
printArray(mat,n+1,print);
puts("");
}
if(!mat[n])
return;
}
void printMat(const float mat[][N],int n,void (*print)())
{
if(n!=1)
printMat(mat,n-1,print);
printArray(mat[n-1],N,print);
}

הסבר על התכנית:

print מצביע לפונקציה printformat1/2 בהתאם לקלט.

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

(אסור להשתמש בלולאות) >:(

פורסם

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

שנית, תוסיף סוגריים ותרווח. אף פעם לא מזיק.

תקלוט לscanf עם & לפני הN(אופרטור הכתובת).

פורסם
  • מחבר

לא מצאתי משהו יותר טיפשי להתקע עליו שעה :-X

פורסם

חוץ מהעניין עם ה scanf בקריאה ל printmat שלחת כפרמטר השני את sizeof(mat) כשאני חושב שהתכוונת ל sizeof(mat)/sizeof(mat[0]) .

פורסם
  • מחבר

נכון[br]פורסם בתאריך: 3.09.2007 בשעה 16:12:22


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

ניסתי פה להריץ את הn עד ל1 ואז בחזרה הרקורסיבית לשלוח את המערכים אבל mat[n-1] לא נותן לי מערך אלא אפס (ואני מבין למה)

void printMat(const float mat[][N],int n,void (*print)())
{

if(n!=1)
printMat(mat,n-1,print);
printArray(mat[n-1],N,print);
}

[br]פורסם בתאריך: 3.09.2007 בשעה 16:49:05


מקפיץ טיפה ;)
פורסם

א. אל תקפיץ.

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

פורסם
  • מחבר

הוא אמור להיות מסובך, זה אחד התרגילים המסכמים של כל הקורס בC

אסור ואף לולאה אחת.

חייב להשתמש בפונקציות הבאות:

void printArray(const float [],int ,?); //פונקציה מקבלת מערך וכמות האברים שלו ומצביע לפונקצית ההדפסה (הסימן שאלה)

void printMat(const float mat[][N],int ,?);//פונקציה מקבלת מטריצה וכמות השורות, ומצביע לפונקצית ההדפסה

אם הרעיון שלי בלתי אפשרי אשמח לקבל רעיונות אחרים.

[br]פורסם בתאריך: 3.09.2007 בשעה 17:49:28


בנוסף אסור להוסיף פרמטרים. :s07:
פורסם

הבנתי.

ודאי שהרעיון שלך אפשרי, הוא פשוט מסובך.

שים לב שב-printArray וב-printMat, הפרמטר print הוא פונקציה שלא מקבלת פרמטרים. זו צריכה להיות פונקציה שמקבלת float.

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

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

תיקון קוסמטי קטן - עדיף שהפרמטר ש-printArray מקבל ייקרא arr או array ולא mat (הוא הרי מערך חד-מימדי, לא מטריצה). זה לא באמת משנה, זה פשוט יותר קריא.

חוץ מזה, לא הבנתי למה השורה הזו:

if (mat[n])

השורה הזו תחזיר true אם הערך ה-n במערך שונה מ-0. לא הבנתי למה זה חשוב.

פורסם
  • מחבר

הפונקציה print אכן מקבלת FLOAT

פשוט בסינטקס הזה :

void (*print)()

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

התנאי :

if (mat[n])

הוא אמור להתכוון לכך: כל עוד קיים איבר , המשך

כי המערך הנתון הוא בגודל 4, אבל בשל היות התכנית כללית היא רצה עד N

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

printArray(mat[n-1],N,print);

עשיתי את השינויים הקוסמטים שהמלצת תודה.

פורסם

קודם כל, אבקש ממך כמה דברים:

אם אתה יכול להעלות את התרגיל לכאן זה יעזור (יש כמה דברים שאני לא בטוח איך הם אמורים לעבוד).

אתה יכול להעלות לכאן את הקוד השלם שלך אחרי כל התיקונים? זה יעזור לראות אם יש עוד שגיאות.

וחוץ מזה, למה אתה משתמש בהצמדה לשמאל ולא ב-code? זה די מעצבן.

הפונקציה print אכן מקבלת FLOAT

פשוט בסינטקס הזה :

void (*print)()

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

זה שהקוד מתקמפל לא אומר שהוא יעבוד כראוי. עדיף ללכת על בטוח (האמת היא שאני לא בטוח ב-100% איך בדיוק תתנהג התכנית ככה, זה מהדברים המגעילים האלה שמתעסקים עם ה-stack). בכל מקרה, אם אין לך סיבה לסבך את התכנית, אל תעשה את זה.

לגבי זה:

התנאי :

if (mat[n])

הוא אמור להתכוון לכך: כל עוד קיים איבר , המשך

כי המערך הנתון הוא בגודל 4, אבל בשל היות התכנית כללית היא רצה עד N

יכול להיות שלא הבנתי נכון את הכוונה של התרגיל (בגלל זה אני אשמח לראות את התרגיל עצמו). אני לא בטוח אם מה שאני רושם עכשיו רלוונטי, אבל אני ארשום את זה בכל זאת:

מה זאת אומרת "קיים איבר"? התנאי הזה פשוט שואל אם האיבר ה-n במערך שונה מ-0. ב-C אין כזה מושג של "קיים" או "לא קיים".

חוץ מזה, עוד משהו לגבי sizeof:

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

אם יש לך מערך כזה:

float arr[20] = { 1,2,3 };

אז ה-sizeof שלו יהיה 80 (20 floatים), ולא 12 (3 floatים).

המטריצה שהצהרת עליה - ה-sizeof של כל שורה יהיה N*sizeof(float) וה-sizeof של כולה יהיה הנ"ל כפול מספר השורות.

אתה צריך להעביר ל-printMat ו-printArray את הגודל המעשי של המטריצות, ולא את ה-sizeof שלהן.

ובכלליות:

הפונקציה printMat נראית בסדר, אבל שכחת שמערכים ב-C מתחילים מ-0, ולא מ-1. כלומר תנאי העצירה שלך צריך להיות (n!=0) ולא (n!=1).

הפונקציה printArray נראית בעייתית. למה אתה קורא ממנה פעמיים ל-printArray? זה יגרום לך לרקורסיה אינסופית.

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

פורסם
  • מחבר

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

אבל הבעיה היחידה שהיא לא כללית. תשים לב למטה איפה שרשום 4. אני לא יודע איך להעביר את גודל המערך אז אני מעביר את גודל המערך הנתון

בצורה הזאת זה אומנם יעשה הכל תקין אבל רק לגבי מערך בגודל 4 (כמו המטריצה הנתונה) והתוכנית לא תהיה כללית

בקשר לn=1 לא שכחתי שמערך מתחיל באפס, פשוט אם אני יריץ אותו עד אפס הוא ידפיס לי שורה אחת יותר מידי לכן אני מריץ עד 1 ושולח n-1

#include <stdio.h>
#include <stdlib.h>
#define N 20
typedef void (*pfunc)(float);
unsigned count(const float [],int n);
int comp(const void*,const void*);
void printFormat1(float );
void printFormat2(float );
void printMat(const float mat[][N],int , void(*)(float));
void printArray(const float [],int ,void(*)(float));
void main()
{
int n=0;
pfunc print;
float mat[][N]=
{
{7,2,3,5},
{1,0,0,0},
{2,0,0,1},
{0,0,0,-2.99F},
{0,1,-1,-5.123F},
{0,0,0,0}
};
qsort(mat,sizeof(mat)/sizeof(mat[0]),sizeof(mat[0]),comp);
puts("Press 1 if you want to print with only 1 digit precision.");
puts("Press any other number for 2 digits precision:");
scanf("%d",&n);
print=n==1?&printFormat1:&printFormat2;
printMat(mat,sizeof(mat)/sizeof(mat[0]),print);
}
unsigned count(const float mat[], int n)
{
if( n == 1 )
{
if( mat[n-1] == 0 )
{
return 1;
}
else
{
return 0;
}
}
else
{
if( mat[n-1] == 0 )
{
return 1 + count(mat, n-1);
}
else
{
return count(mat, n-1);

}
}
}
int comp(const void* el1,const void* el2)
{
int x,y;
x=count((float*)el1, N );
y=count((float*)el2, N );
return x-y;
}
void printFormat1(float n)
{
printf("%.1f ",n);
}
void printFormat2(float n)
{
printf("%.2f ",n);
}
void printArray(const float arr[],int n,void (*print)(float))
{
if(n!=1)
printArray(arr,n-1,print);
print(arr[n-1]);
}
void printMat(const float mat[][N],int n,void (*print)(float))
{

if(n!=1)
printMat(mat,n-1,print);
printArray(mat[n-1],4,print);
puts("");
}

פורסם

קודם - אם תשתמש בצומדיים בצורה הבאה:


if(n!=1)
}
printArray(arr,n-1,print);
print(arr[n-1]);
{

לא תצטרך לבדוק 1 ולשלוח n-1.

ובקשר ל- 4 -

תשלח פרמטר (int n2 למשל) שיכיל את מספר העמודות בשורה, ואותו תשלח ל printArray.

פורסם
  • מחבר

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

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

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

אני מחפש דרך לדעת את מספר העמודות באופן כללי כמו עם sizeof אבל כמו שכבר דיסקסנו מיקודם sizeof לא רלוונטי במקרה זה כי האורך תמיד יחזיר N

פורסם

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

ואתה חייב להכניס את רוחב המטריצה, ולכתוב את זה ידנית. אם אתה רוצה משהו יותר כללי, תהייה חייב ליצור מבנה שישמור את כל הנתונים האלה.

פורסם
  • מחבר

בשעה טובה הצלחתי! הכנסתי שינוי קטן בprintarray לא יודע אם זה אולי מה שהצעתי אבל זה נתן לי כיוון.

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

התכנית הסופית:

#include <stdio.h>
#include <stdlib.h>
#define N 20
typedef void (*pfunc)(float);
unsigned count(const float [],int n);
int comp(const void*,const void*);
void printFormat1(float );
void printFormat2(float );
void printMat(const float mat[][N],int , void(*)(float));
void printArray(const float [],int ,void(*)(float));
void main()
{
int n=0;
pfunc print;
float mat[][N]=
{
{7,2,3,5},
{1,0,0,0},
{2,0,0,1},
{0,0,0,-2.99F},
{0,1,-1,-5.123F},
{0,0,0,0}
};
qsort(mat,sizeof(mat)/sizeof(mat[0]),sizeof(mat[0]),comp);
puts("Press 1 if you want to print with only 1 digit precision.");
puts("Press any other number for 2 digits precision:");
scanf("%d",&n);
print=n==1?&printFormat1:&printFormat2;
printMat(mat,sizeof(mat)/sizeof(mat[0]),print);
}
unsigned count(const float mat[], int n)
{
if( n == 1 )
{
if( mat[n-1] == 0 )
{
return 1;
}
else
{
return 0;
}
}
else
{
if( mat[n-1] == 0 )
{
return 1 + count(mat, n-1);
}
else
{
return count(mat, n-1);

}
}
}
int comp(const void* el1,const void* el2)
{
int x,y;
x=count((float*)el1, N );
y=count((float*)el2, N );
return x-y;
}
void printFormat1(float n)
{
printf("%.1f ",n);
}
void printFormat2(float n)
{
printf("%.2f ",n);
}
void printArray(const float arr[],int n,void (*print)(float))
{
int x;
if(n!=1)
printArray(arr,n-1,print);
x=sizeof(arr[n-1]);
if(n<x)
print(arr[n-1]);
}
void printMat(const float mat[][N],int n,void (*print)(float))
{
if(n!=1)
printMat(mat,n-1,print);
printArray(mat[n-1],N,print);
puts("");
}

[br]פורסם בתאריך: 5.09.2007 בשעה 15:02:08


אני תוהה למה הSIZEOF הזה עבד בprintarray ולא עבד בprintmat

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

דיונים חדשים