# Need HELP

Discussion in 'C Programming' started by kupiko, Apr 1, 2005.

1. ### kupikoGuest

Please can anyone help me on this code? I want
to write all odd numbers in range from a to b but it doesn't work at all
cases mainly when a is higher than b and when i type in negative numbers.

Here is the code and i would appreciate anybody helping me. THANKS.

#include<stdio.h>
#include<math.h>
void odd(float x, float y);
void change(float x, float y);

void odd(float x, float y)
{
int i;
if (x>y) change(x,y);
x=roundf(x);
y=roundf(y);
for(i=1;i<(y-x)+1;i++)
if ( fmodf ((x+i),2)==1 || fmodf ((x+i),2)==-1 ) printf( "%f
",(x+i) );
}

void change(float x, float y)
{
float c;
c=x;
x=y;
y=c;
}

main()
{

float a,b;
printf("Type two real numbers :");
scanf("%f%f",&a,&b);
odd(a,b);
getchar();
getchar();
}

kupiko, Apr 1, 2005

2. ### Don MorrisGuest

kupiko wrote:
> Please can anyone help me on this code? I want
> to write all odd numbers in range from a to b but it doesn't work at all
> cases mainly when a is higher than b and when i type in negative numbers.
>
>
> Here is the code and i would appreciate anybody helping me. THANKS.
>
> #include<stdio.h>
> #include<math.h>
> void odd(float x, float y);
> void change(float x, float y);
>
> void odd(float x, float y)
> {
> int i;
> if (x>y) change(x,y);
> x=roundf(x);
> y=roundf(y);
> for(i=1;i<(y-x)+1;i++)
> if ( fmodf ((x+i),2)==1 || fmodf ((x+i),2)==-1 ) printf( "%f
> ",(x+i) );
> }
>
> void change(float x, float y)
> {
> float c;
> c=x;
> x=y;
> y=c;
> }

Just on first glance (i.e. I wouldn't swear that you don't have
other bugs...), your problem is in how you call change().
When you call a C function, the function works on local copies
of the parameters -- not on the values in the scope of the caller.

So here -- you have the following:

main gets a and b (main:a, main:b for short), calls odd with them.
odd gets copies of main:a, main:b which are named odd:x, odd:y.
main:a and main:b are (of course) unchanged).

odd calls change with odd:x, odd:y -- and change's copies are
called change:x, change:y.

change:x, change:y and change:c are modified and change returns..
leaving odd:x and odd:y unchanged.

So if you want to do this, I'd recommend one of the following:

i) Rewrite change to be a macro, not a function so that
you work with the actual variables you intend, such as:

#define SWAP_FLOAT(float __x, float __y ) \
do { \
float __temp; \
__temp = __x; \
__x = __y; \
__y = __temp; \
} while (0)

This lets you use SWAP_FLOAT as if it were a function,
having odd() do SWAP_FLOAT(x, y) will change the
variables in odd()'s scope [odd:x, odd:y] as you intend.

ii) Rewrite change to work with the addresses of the
variables, not the contents.

void change (float *x, float *y)
{
float temp;
if ( x == NULL || y == NULL ) {
/* Die with error? Your call on handling */
return;
}
temp = *x;
*x = *y;
*y = temp;
}

Don

>
> main()
> {
>
> float a,b;
> printf("Type two real numbers :");
> scanf("%f%f",&a,&b);
> odd(a,b);
> getchar();
> getchar();
> }
>

Don Morris, Apr 1, 2005

3. ### kupikoGuest

>void change (float *x, float *y)
>{
> float temp;
> if ( x == NULL || y == NULL ) {
> /* Die with error? Your call on >handling */
> return;
> }
> temp = *x;
> *x = *y;
> *y = temp;
>}

Thank you very much for this advice. It's first time I see how to use
pointers and it is useful as I see but still there are errors in my
rewritten code. And i don't know anything about pointers so i can't solve
I haven't much time otherwise i would not annoy you.

ERROR:
cannot convert `float' to `float*' for argument `1' to `void
vymen(float*, float*)'

CODE:

#include<stdio.h>
#include<math.h>

void odd(float x, float y);
void change(float *x, float *y);

void odd(float x, float y)
{
int i;
if (x>y) change(x,y);
x=roundf(x);
y=roundf(y);
for(i=1;i<(y-x)+1;i++)
if ( fmodf ((x+i),2)==1 || fmodf ((x+i),2)==-1 ) printf( "%f
",(x+i) );
}

void change(float *x, float *y)
{
float c;
if ( x==NULL || y==NULL ) return;
c=*x;
*x=*y;
*y=c;
}

main()
{
float a,b;
printf("Type two real numbers :");
scanf("%f%f",&a,&b);
odd(a,b);
getchar();
getchar();
}

kupiko, Apr 1, 2005
4. ### Don MorrisGuest

kupiko wrote:
>>void change (float *x, float *y)
>>{
>> float temp;
>> if ( x == NULL || y == NULL ) {
>> /* Die with error? Your call on >handling */
>> return;
>> }
>> temp = *x;
>> *x = *y;
>> *y = temp;
>>}

>
>
> Thank you very much for this advice. It's first time I see how to use
> pointers and it is useful as I see but still there are errors in my
> rewritten code. And i don't know anything about pointers so i can't solve
> I haven't much time otherwise i would not annoy you.

It isn't annoying me... just a sign my mind isn't focused on
work yet this morning. Sorry I wasn't more clear.

>
> ERROR:
> cannot convert `float' to `float*' for argument `1' to `void
> vymen(float*, float*)'

Right -- we've changed the function to take pointers, which means
you need to call it with pointers (aka the address of x, not x
itself).

>
> CODE:
>
> #include<stdio.h>
> #include<math.h>
>
> void odd(float x, float y);
> void change(float *x, float *y);
>
> void odd(float x, float y)
> {
> int i;
> if (x>y) change(x,y);

if ( x > y ) {
change(&x, &y);
}

Don

> x=roundf(x);
> y=roundf(y);
> for(i=1;i<(y-x)+1;i++)
> if ( fmodf ((x+i),2)==1 || fmodf ((x+i),2)==-1 ) printf( "%f
> ",(x+i) );
> }
>
> void change(float *x, float *y)
> {
> float c;
> if ( x==NULL || y==NULL ) return;
> c=*x;
> *x=*y;
> *y=c;
> }
>
> main()
> {
> float a,b;
> printf("Type two real numbers :");
> scanf("%f%f",&a,&b);
> odd(a,b);
> getchar();
> getchar();
> }
>
>

Don Morris, Apr 1, 2005
5. ### MacGuest

On Fri, 01 Apr 2005 14:07:53 +0000, Don Morris wrote:

> #define SWAP_FLOAT(float __x, float __y ) \

Is this a C99 thing? I've never seen a function-like macro defined this
way (with types) and my compiler won't accept it.

Maybe you meant to type:
#define SWAP_FLOAT(__x, __y ) \

> do { \
> float __temp; \
> __temp = __x; \
> __x = __y; \
> __y = __temp; \
> } while (0)

And why are you using the undercores in the identifier names? They seem
to me to be completely unnecessary. Couldn't you just do it like this:

#define SWAP_FLOAT(x, y ) \
do { \
float temp; \
temp = x; \
x = y; \
y = temp; \
} while (0)

--Mac

Mac, Apr 3, 2005
6. ### Artie GoldGuest

Mac wrote:
> On Fri, 01 Apr 2005 14:07:53 +0000, Don Morris wrote:
>
>
>>#define SWAP_FLOAT(float __x, float __y ) \

>
>
> Is this a C99 thing? I've never seen a function-like macro defined this
> way (with types) and my compiler won't accept it.

>
> Maybe you meant to type:
> #define SWAP_FLOAT(__x, __y ) \
>
>
>>do { \
>> float __temp; \
>> __temp = __x; \
>> __x = __y; \
>> __y = __temp; \
>>} while (0)

>
>
> And why are you using the undercores in the identifier names? They seem
> to me to be completely unnecessary. Couldn't you just do it like this:

Well, it was a misguided attempt at avoiding inadvertent variable
capture. Identifiers starting with an underscore are reserved for the
implementation.

>
> #define SWAP_FLOAT(x, y ) \
> do { \
> float temp; \
> temp = x; \
> x = y; \
> y = temp; \
> } while (0)
>

Consider, however, what happens if you have the following code:

void nonsensical() {
float temp = 3.0;
float other = 4.0;
printf("before swap, temp = %f, other = %f", temp, other);
SWAP_FLOAT(temp, other);
printf("after swap, temp = %f, other = %f", temp, other);
}

Macros can be useful -- but (particularly if they declare variables) can
bite you in the^H^H^H^H^H^H^H^H^H^H^H^H^H^H^Hcause problems.

HTH,
--ag

--
Artie Gold -- Austin, Texas
http://it-matters.blogspot.com (new post 12/5)
http://www.cafepress.com/goldsays

Artie Gold, Apr 3, 2005
7. ### Old WolfGuest

Artie Gold wrote:
> Mac wrote:
> >
> > #define SWAP_FLOAT(x, y ) \
> > do { \
> > float temp; \
> > temp = x; \
> > x = y; \
> > y = temp; \
> > } while (0)
> >

> Consider, however, what happens if you have the following code:
>
> void nonsensical() {
> float temp = 3.0;
> float other = 4.0;
> printf("before swap, temp = %f, other = %f", temp, other);
> SWAP_FLOAT(temp, other);
> printf("after swap, temp = %f, other = %f", temp, other);
> }

The problem is that 'temp' in the macro clashes with 'temp' in

#define SWAP_FLOAT(x, y) \
do { \
float x##y; \
x##y = x; \
x = y; \
y = x##y; \
} while (0)

No possibility of clashes now (even if 'x' and 'y' are #defined
to something else already, I think)

Old Wolf, Apr 4, 2005
8. ### Peter NilssonGuest

Old Wolf wrote:
> ...
> The problem is that 'temp' in the macro clashes with 'temp' in
>
> #define SWAP_FLOAT(x, y) \
> do { \
> float x##y; \
> x##y = x; \
> x = y; \
> y = x##y; \
> } while (0)

SWAP_FLOAT(er, rno);
SWAP_FLOAT(x, *y);

--
Peter

Peter Nilsson, Apr 4, 2005
9. ### Old WolfGuest

Peter Nilsson wrote:
> Old Wolf wrote:
> > ...
> > The problem is that 'temp' in the macro clashes with 'temp' in
> >
> > #define SWAP_FLOAT(x, y) \
> > do { \
> > float x##y; \
> > x##y = x; \
> > x = y; \
> > y = x##y; \
> > } while (0)

>
> SWAP_FLOAT(er, rno);

No problem, local errno takes precedence over global errno.

> SWAP_FLOAT(x, *y);

Ah, serious problem.I guess that takes us back to the
pick-something-weird-and-wacky option.

Old Wolf, Apr 4, 2005
10. ### Peter NilssonGuest

Old Wolf wrote:
> Peter Nilsson wrote:
> > Old Wolf wrote:
> > > ...
> > > The problem is that 'temp' in the macro clashes with 'temp' in
> > >
> > > #define SWAP_FLOAT(x, y) \
> > > do { \
> > > float x##y; \
> > > x##y = x; \
> > > x = y; \
> > > y = x##y; \
> > > } while (0)

> >
> > SWAP_FLOAT(er, rno);

>
> No problem, local errno takes precedence over global errno.

You don't seem to realise that, if <errno.h> is included,
errno is a _macro_ "...which expands to a modifiable lvalue
that has type int". [7.5p2] It needn't expand to the name of
a 'global'.

> > SWAP_FLOAT(x, *y);

>
> Ah, serious problem.I guess that takes us back to the
> pick-something-weird-and-wacky option.

Or to 'inline' under C99, if such an implementation is available.

--
Peter

Peter Nilsson, Apr 4, 2005