PDA

View Full Version : Simple C code help




PowerFullMac
Nov 4, 2008, 11:46 AM
I have this C app I am trying to make, basically what it does is takes two numbers then adds, subtracts, divides or multiplies the number depending on what the user enters. However, it doesent work... For example it seems to think 1+1 is 1... What am I doing wrong?

#include <stdio.h>
main()

{
int a,b,c,d;
printf ("Command-line calculator tool by Josh. \n");
printf ("Enter the first number ");
scanf ("%d" ,&a);
printf ("Enter the second number ");
scanf ("%d" ,&b);
printf ("Do you want to +, -, * or /? ");
scanf ("%d",&c);
d=a,c,b;
printf ("The answer is %d \n" ,d);
}



robbieduncan
Nov 4, 2008, 11:49 AM
1st tip: use the CODE UBB tags :)

Now, can you explain, exactly, what you think the like I have quoted is doing?

d=a,c,b;

Now that you've done that, have a read of what the comma operator (http://www.eskimo.com/~scs/cclass/int/sx4db.html) really does...

PowerFullMac
Nov 4, 2008, 11:52 AM
1st tip: use the CODE UBB tags :)

Now, can you explain, exactly, what you think the like I have quoted is doing?



Now that you've done that, have a read of what the comma operator (http://www.eskimo.com/~scs/cclass/int/sx4db.html) really does...

Just did :D

Its meant to take a and d and do the operation defined by c.

robbieduncan
Nov 4, 2008, 11:56 AM
Its meant to take a and d and do the operation defined by c.

Well it doesn't. Not even close. It evaluates the first expression. Which is a so this just evaluates to a. Then the second, which is another comma expression so gets broken down the same way so it evaluates c, which is c and finally evaluates b. As this is the end of the compound expression this is the final value of the expression.

To the best of my knowledge there is no direct operator in plain C that does what you are trying to do: you actually have to write code. You need to write some conditional logic to work out which operator was supplied (and complain if something else was supplied) and evaluate the correct expression in each case...

PowerFullMac
Nov 4, 2008, 12:03 PM
Thats annoying, its such a simple operation!

I'll make it do all operations for now then, thats way easier.

robbieduncan
Nov 4, 2008, 12:45 PM
Thats annoying, its such a simple operation!

I'll make it do all operations for now then, thats way easier.

You may think it's simple, bit for C it's not. C is not a very dynamic language. On fact it's very static. It expects to know the address of function calls, their definition, everything at complile time. These operators are basically built I'm function calls. You cannot expect the system to dynamically look up the function and use different memory addresses at run time: that's not how a C function call works. Worse than that you are trying to use the name of re function, which is meaningless at runtime!

PowerFullMac
Nov 4, 2008, 12:48 PM
I'm new give me a break! :D

The new approach worked... I will try doing it again when I know a bit more.

This is the first program I wrote without using a tutorial, yay! :)

lee1210
Nov 4, 2008, 12:54 PM
What you're likely looking for is a switch statement:

char c;
int a,b,d;
//... (do input, etc.)
switch (c) {
case '+':
d= a + b;
break;
case '-':
d= a - b;
break;
case '/':
if(b == 0) {
fprintf(stderr,"Cannot divide by 0");
d=0;
} else {
d= a / b;
}
break;
case '*':
d= a * b;
break;
default:
d=0;
fprintf(stderr,"Invalid operator, %c, entered.",c);
break;
}
printf("The value of %d %c %d is: %d\n",a,c,b,d);


no, it isn't as simple, but you can't take a character like '+' and "perform" it. it's just a value, namely a byte with the value 43. With your original example, with 4 entered for a, 2 for b, and '+' for c, the statement you had was:
d = 4,43,2;
So d would be assigned 2, for the reasons Cromulent stated above.

-Lee

PowerFullMac
Nov 4, 2008, 12:59 PM
Thanks, Lee.

Makes sense... Seems the hardest thing with C is having to write your own code for things which seem easy at the surface but obviously are not that simple for C!

I'm learning... :)

robbieduncan
Nov 4, 2008, 01:05 PM
Thanks, Lee.

Makes sense... Seems the hardest thing with C is having to write your own code for things which seem easy at the surface but obviously are not that simple for C!

I'm learning... :)

I think that's one of the great things about C. It's about as close to the metal as you can get without dropping the assembly. It forces you to actually think about howthe machine works and what's really going on. In general I find this makes people write better, tighter code on other languages. Keep at it :)

PowerFullMac
Nov 4, 2008, 01:07 PM
I think that's one of the great things about C. It's about as close to the metal as you can get without dropping the assembly. It forces you to actually think about howthe machine works and what's really going on. In general I find this makes people write better, tighter code on other languages. Keep at it :)

Indeed :)

I also intend to learn Assembly, too, after C! I wanna make my own operating system! :)

robbieduncan
Nov 4, 2008, 01:22 PM
Indeed :)

I also intend to learn Assembly, too, after C! I wanna make my own operating system! :)

Oh dear. Your one of those sort of beginners. You'll soon get over it :p

PowerFullMac
Nov 4, 2008, 01:27 PM
Oh dear. Your one of those sort of beginners. You'll soon get over it :p

LOL I dont really expect to make something amazing, it will just be a project I can work on when I am not doing anything else and its especially good for that because it can never really be finished :)

yeroen
Nov 4, 2008, 01:42 PM
Indeed :)

I also intend to learn Assembly, too, after C! I wanna make my own operating system! :)

Well, you can check hubris and delusions of grandeur off your list of necessary stops on the road to becoming a successful coder.

lee1210
Nov 4, 2008, 01:55 PM
You also have the early benefit of a nasty run-in with the comma operator. Some people go years without doing so. Just last week I found a bug with it, as follows:

#define V_DBCMD_NEXT 1 //Made this up, it was actually from an include
V_TAG *time_tags = NULL;
V_SYS *vptr = NULL;
char reqbuf[256], msgbuf[256];
char *res = NULL;
time_tags = VSI_Server_Olog_Get,(vptr,reqbuf,0,V_DBCMD_NEXT,msgbuf);
res = some_other_call(time_tags);

VSI_Server_Olog_Get returns a V_TAG *. The comma after VSI_Server_Olog_Get was committed inadvertently at some point. But the code still compiled, it ran OK, but the results were wrong. What this line:

time_tags = VSI_Server_Olog_Get,(vptr,reqbuf,0,V_DBCMD_NEXT,msgbuf);

was actually doing was:
Evaluating the address of VSI_Server_Olog_Get, and discarding it.
Evaluating vptr's address, and discarding it
Evaluating 0, and discarding it
Evaluating V_DBCMD_NEXt, and discarding it
Evaluating msgbuf's address, and assigning it to time_tags

So at the end of the line, time_tags is pointing to some chars in memory instead of a V_TAG structure. some_other_call was into something that expected a V_TAG *, so it's behavior was indeterminate (after some other tweaks, this would reliably cause a crash). After pulling out the errant comma, everything worked as expected, and VSI_Server_Olog_Get was actually called, instead of simply having its address evaluated and discarded.

The moral is two-fold:
One, pay attention to compiler warnings. This was the only indication that the comma had mucked things up.
Two, Be weary of the comma. It can bite you in ways you would not imagine possible.

-Lee