עבור לתוכן

עזרה בC

Featured Replies

פורסם

שלום

אני לא מצליח להעביר לprintBinary את המשתנים המעודכנים אחרי השינויים שנעשו בהם בfunc

ניסתי להעביר לfunc את הכתובות שלהם כדי שהשינוי יבוא לידי ביטוי גם במיין אבל אז (אני חושב) זה היה בלתי אפשרי לבצע את הפעולות שfunc מבצעת

יש איזה רעיון? (אילוצים: אסור לשנות כלום במיין ולא להוסיף משתנים, מותר רק לשנות את מה שהפונקציות מקבלות ואת המימוש שלהן)

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

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

(שתי הפונקציות עובדות באופן תקין, אני רק לא יודע איך לקשר בניהם)

#include <stdio.h>
#include <stdarg.h>
#define ARG 3
#define AND &
#define XOR ^
#define SIZE(x) sizeof(x)*2
void printBinary (int n,...)
{
int i,j;
char num;
va_list arg_ptr;
va_start(arg_ptr,n);
for(j=0;j<n;j++)
{
i=SIZE(arg_ptr)-1;
printf("%d: ",*arg_ptr);
num=va_arg(arg_ptr,char);
while (i>=0)
{
printf ("%d",num&1<<i--?1:0);
}
puts("");
}
va_end(arg_ptr);
}
void func(int n,...)
{
int i,x,y,size,j,k;
va_list arg_ptr;
va_start(arg_ptr,n);
size=SIZE(arg_ptr);
x=1&(va_arg(arg_ptr,char)>>0);
for(i=0;i<n-1;i++)
{

y=1&((va_arg(arg_ptr,char))>>0);
x=x AND y;
}
va_start(arg_ptr,n);
j=1&((va_arg(arg_ptr,char))>>(size-1));
for(i=0;i<n-1;i++)
{
k=1&((va_arg(arg_ptr,char))>>(size-1));
j=j XOR k;
}
va_start(arg_ptr,n);
if(x>j)
{
for(i=0;i<n;i++)
{
*arg_ptr&=~(1<<(size-1));
va_arg(arg_ptr,char)|=(1<<0);
}
}
if(x<j)
{
for(i=0;i<n;i++)
{
*arg_ptr|=(1<<(size-1));
va_arg(arg_ptr,char)&=~(1<<0);
}
}
else
va_end(arg_ptr);
}
void main()
{
char a=-101,b=-107,c=-2;
func(ARG,a,b,c);
printBinary(ARG,a,b,c);
}

תודה.

פורסם

ניסית לשלוח char * ולקרוא בעזרת *va_arg(arg_ptr,char)?

פורסם

^^ what he said

כשאתה מעביר פרמטרים לפונקציה, הם עוברים by value - כלומר, הם מועתקים. כל שינוי שאתה עושה בהם לא יישמר (הם יימחקו ברגע שתצא מהפונקציה).

ב-C, על מנת שזה יעבוד, אתה צריך להעביר מצביע.

יענו, במקום:

void increaseBy1(int x)
{
x += 1;
}

אתה צריך

void increaseBy1(int *x)
{
*x += 1;
}

(וכשאתה קורא לפונקציה כמובן אתה צריך להעביר מצביע)

חוץ מזה, למה עשית define ל-and ול-xor? מומלץ למעט ב-define-ים...

תגיד לי, מי המורה הסאדיסט שנותן לכם כאלה תרגילים?

פורסם
  • מחבר

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

unsignedinteger ניסתי כל מיני וריאציות

הוריאציה הזאת ודומיה :

*va_arg(arg_ptr,char)

לא מתקמפלים.

שניצל:

גם המורה מזוכיסט וגם השפה מזוכיסטית. הdefines הלא מחוייבים המציאות האלה הם אילוץ...

אולי זה יעזור אם אני יעלה את התרגיל?

פורסם

ניסית

va_arg(arg_ptr, char*)

ולקרוא לפונקציה ככה:

func(ARG, &a, &b, &c)

כמו ש-UI אמר?

פורסם
  • מחבר

אכן זה היה הדבר הראשון שניסיתי

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

לא יודע אני מנסה למצוא כיוונים.

בכל אופן הסינטקס של va_arg לא מוכן לקבל שום דבר חוץ מטיפוסים רגילים int char וכו ולא מצביעים.

ונראה לי הגיוני כי זה בסך הכל אומר לו בכמה בתים לקפוץ קדימה , זה לא אומר לו באיזה פורמט לקרוא.

מה שunsigned הציע נישמע לי מאוד הגיוני

*va_arg(arg_ptr,char)

כי va arg מחזירה את התוכן של המצביע (שזה הכתובת) ואז הכוכבית מחזירה את התוכן של הכתובת

אבל מה לעשות שזה לא מתקמפל אבל :\

פורסם

אני הצעתי את מה ששניצל רשם.

ד.א. אני לא יודע איך המימוש הפנימי של המאקרו הזה הולך, אבל תנסה לעטוף את char* בסוגריים.

פורסם

הקוד הזה:

*va_arg(arg_ptr, char)

לא יעבוד, כיוון שאתה מנסה לעשות dereferencing ל-char (שאינו מצביע כמובן).

הקוד צריך להיות ככה (בכל המקומות):

*va_arg(arg_ptr, char*)

va_arg כן יודע לקבל כל טיפוס (ראה דוגמא כאן)

שים לב גם שהקריאה האחרונה שלך ל-va_end לא תמיד תיקרא (אם קראת ל-va_start, אתה חייב לקרוא ל-va_end).

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

פורסם
  • מחבר

איי כן זה בדיוק מה שברח לי מהראש.

עכשיו הכל תקין, אני צריך כמה המלצות:

איך אפשר לעשות שהתוכנית תהיה כללית לכל טיפוס?

ניסיתי ככה:

sizeof(arg_ptr)*

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

c:\users\יעקובי אורן\documents\visual studio projects\dfdfddd\sdcfs.c(32): error C2059: syntax error : ')'

ואין שם שום ( מיותר או חסר

ועוד משהו

אולי אתם תבינו מה הוא רוצה פה:

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

התכנית עד כה: (כעיקרון גמורה)

#include <stdio.h>
#include <stdarg.h>
#define ARG 3
#define AND &
#define XOR ^
#define SIZE(x) sizeof(x)*2
void printBinary (int n,...)
{
int i,j;
char num;
va_list arg_ptr;
va_start(arg_ptr,n);
for(j=0;j<n;j++)
{
i=SIZE(arg_ptr)-1;
printf("%d: ",*arg_ptr);
num=va_arg(arg_ptr,char);
while (i>=0)
{
printf ("%d",num&1<<i--?1:0);
}
puts("");
}
va_end(arg_ptr);
}
void func(int n,...)
{
int i,x,y,size,j,k;
va_list arg_ptr;
va_start(arg_ptr,n);
size=SIZE(arg_ptr);
x=1&(*va_arg(arg_ptr, char*)>>0);
for(i=0;i<n-1;i++)
{
y=1&(*va_arg(arg_ptr, char*)>>0);
x=x AND y;
}
va_end(arg_ptr);
va_start(arg_ptr,n);
j=1&(*va_arg(arg_ptr, char*)>>(size-1));
for(i=0;i<n-1;i++)
{
k=1&(*va_arg(arg_ptr, char*)>>(size-1));
j=j XOR k;
}
va_end(arg_ptr);
va_start(arg_ptr,n);
if(x>j)
{
for(i=0;i<n;i++)
{
*arg_ptr&=~(1<<(size-1));
*va_arg(arg_ptr, char*)|=(1<<0);
}
}
if(x<j)
{
for(i=0;i<n;i++)
{
*arg_ptr|=(1<<(size-1));
*va_arg(arg_ptr, char*)&=~(1<<0);
}
}
else
va_end(arg_ptr);
}
void main()
{
char a=-101,b=-107,c=-2;
func(ARG,&a,&b,&c);
printBinary(ARG,a,b,c);
}

תודה.

פורסם

הוא רוצה שתשתמש בSIZEOF עם מאקרו כלשהו.

ואתה לא יכול לרשום sizeof(..)*

אין כזה דבר.

אתה יודע מה אתה הולך לקבל (מה שאתה רושם ב va_arg). פשוט תעשה SIZEOF של הדבר שאתה אמור לקבל.

פורסם
  • מחבר

אבל הסינטקס של va_arg דורש גם טיפוס

אז אני לא יכול לקבל את הערך ממנו בלי לתת לו טיפוס

או שלא הבנתי למה אתה מתכוון

פורסם

הסיינטקס דורש טיפוס->אתה חייב לדעת את הטיפוס->הטיפוס ידוע מראש(או ע"י SWITCH כלשהו)->אתה יכול לעשות לו SIZEOF.

פורסם
  • מחבר

הגעתי למסקנה שהתכנית כללית גם ככה. כי בכל מקרה הפונקציה מקבלת מצביע וגודל המצביע תמיד 4

כך שגם אם ישאר צ'אר בפונקציה זה ירוץ טוב.

שאלה אחרונה:

יש עוד אפשרות לעשות את התכנית הזאת רק בלי הARG?( ובלי לשים זקיף בסוף)

ככה שאם משנים את מספר הארגומנטים לא יצטרכו לשנות גם את הARG

פורסם

קודם כל, הפונקציה חייבת לדעת כמה משתנים יש לה (על מנת לדעת כמה פעמים לקרוא ל-va_arg).

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

פורסם
  • מחבר

כן זה מה שחשבתי...

ארכיון

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

דיונים חדשים