Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Aug 16th, 2008, 10:27 PM   #1
Fengalon
Newbie
 
Join Date: Aug 2008
Location: Florida
Posts: 8
Rep Power: 0 Fengalon is on a distinguished road
looping fun

Hi all! I'm writing this little program that functions as a very rudimentary calculator. I'll be honest, it is part of an exercise from the tutorial I'm using but I am just stumped. What it's supposed to do is ask for two floats as well as a char that will tell it whether it will add, subtract, multiply and divide. It's also supposed to loop and keep asking for numbers and a char until its passed the q char, in which case it's supposed to quit. Here's what it's ACUALLY doing:

1. It will ask for the first and second number.
2. It will not ask for the char and instead asks for the first number again.
3. When is asks for the first number again, it also runs the code in the default case.
4. If I give the char when it asks for the first number (for the second time) it will run the proper case and calculation.

I know I'm overlooking SOMETHING here and know me, it's something pretty obvious but I just don't know what it is. Here's the code:

c Syntax (Toggle Plain Text)
  1. #include <stdio.h>
  2. float a, b, answer;
  3. char o;
  4.  
  5. int main() {
  6.  
  7. printf("I'm a basic calculator!\n");
  8. printf("I'm going to ask for two numbers and then\n");
  9. printf("I'm going to ask what you want to do with them.\n");
  10.  
  11.  
  12. while(o != 'q')
  13. {
  14. printf("What's the first number? ");
  15. scanf("%f", &a);
  16. printf("Ok, and the second number? ");
  17. scanf("%f", &b);
  18. printf("What do you want to do with these two numbers?\n");
  19. printf("Press only the specified keys or I'm gonna yell at you!\n\n");
  20. printf("a = add\n");
  21. printf("s = subtract\n");
  22. printf("* = multiply\n");
  23. printf("/ = divide\n");
  24. scanf("%c", &o);
  25.  
  26. switch(o)
  27. {
  28. case 'a':
  29. {
  30. answer = a + b;
  31. printf("%f + %f = %f\n", a, b, answer);
  32. a, b, answer = 0;
  33. break;
  34. }
  35. case 's':
  36. {
  37. answer = a - b;
  38. printf("%f - %f = %f\n", a, b, answer);
  39. a, b, answer = 0;
  40. break;
  41. }
  42. case '*':
  43. {
  44. answer = a * b;
  45. printf("%f * %f = %f\n", a, b, answer);
  46. a, b, answer = 0;
  47. break;
  48. }
  49. case '/':
  50. {
  51. answer = a / b;
  52. printf("%f / %f = %f\n", a, b, answer);
  53. a, b, answer = 0;
  54. break;
  55. }
  56. case 'q':
  57. {
  58. return 0;
  59. }
  60. default:
  61. {
  62. printf("Hey dammit! I told you to pick one of the choices specified! Raargh!\n");
  63. }
  64. }
  65. }
  66. }

I can't for the life of me understand why its skipping the scanf() at line 24 nor why it's acting like it is. I'm not asking for an answer as we all know that won't help me learn but maybe just a nudge in the right direction.
Fengalon is offline   Reply With Quote
Old Aug 17th, 2008, 7:00 AM   #2
lectricpharaoh
Caffeinated Neural Net
 
lectricpharaoh's Avatar
 
Join Date: Jun 2005
Location: Dry west coast of Canada
Posts: 1,009
Rep Power: 5 lectricpharaoh will become famous soon enough
Re: looping fun

I'm not gonna solve this one for you, but I'll give you a couple of suggestions.

First, whenever receiving input from the user- or any other source not under your absolute control (disk file, network connection, etc), you need to verify that the input given is indeed the type of input you expected. With scanf(), this means checking the return value. It will be EOF if there is an error (such as hitting end-of-file, trying to read from a closed stream, or having some hardware error). Otherwise, it will be the number of items successfully read in (scanf() will stop as soon as it hits bad input, so if the first, second, and fourth items were entered correctly, but the third wasn't, the return value will be 2, not 3). If you're asking for a single number, then the return value will be 1 if everything went as you hoped. If it's zero, it means the user did something stupid, such as entering a string. If it's EOF, you have an error as described above. You might find it easier to wrap the scanf() calls inside a function that does this kind of error-checking logic, and will re-prompt the user if they entter bad data, or alert them if something is wrong beyond your control. Then you can call getNumber() or something rather than scanf(), and know that your bases are still covered.

Second, remember that I/O in C is generally line buffered. In other words, when you read with scanf(), it will not actually read anything in until the user hits enter. Thus, the user must type a character followed by enter, rather than just the character itself. There are various ways around this, but many (most?) are not entirely portable. You might check and see if your compiler has the conio.h header file; if it does, there are often functions in there to read single characters, as well as special characters such as function keys.

On another note, kudos to you for using code tags, and posting an intro before a question. So few new users do either these days, much less both, and it's refreshing to see.
__________________
And once again, Probability proves itself willing to sneak into a back alley and service Drama as would a copper-piece harlot.
- Vaarsuvius, Order of the Stick
lectricpharaoh is offline   Reply With Quote
Old Aug 17th, 2008, 11:00 PM   #3
Fengalon
Newbie
 
Join Date: Aug 2008
Location: Florida
Posts: 8
Rep Power: 0 Fengalon is on a distinguished road
Re: looping fun

After battling this exercise all day, I have a new found respect for programmers. I have always read that computers are inherently dumb and most be told every stinking thing to do. I never realized how true that statement is until I was the one behind the drivers seat. I've had to really change my way of thinking to get it done. I shudder to think what assembly programmers have to go through... Well enough of my little rant. Here's my progress so far.

I stripped down the code to just it asking for the two floats and a char. I also added another printf() at the end so that I could see what exactly the scanf() asking for char was doing. Sure enough, it would be output NULL. I changed the char to a char array and had scanf() look for a string instead of a character and IT WORKED! .....but I have no idea why. When scanf() is asking for a %c and I input a single character, it is my understanding that that is all I am giving it. Or is it? I know in strings, I have to account for the string terminator (NULL or \0 I believe). Is there also a terminator in a char variable as well? Is scanf() just funny that way? Or is it something else I'm missing?

Well now that I know the input works, I had to see if the calculation part was working. I did some trial and error (mainly error) with the switch/cases as well but that didn't take too long to figure out. It doesn't loop to ask for a new set of numbers but it does the proper calculation based on what character you input. Here's the code as it stands now:

c Syntax (Toggle Plain Text)
  1. #include <stdio.h>
  2.  
  3. float a, b, answer;
  4. char o[2];
  5. int i;
  6.  
  7. int main()
  8. {
  9. printf("What's the first number? ");
  10. scanf("%f", &a);
  11. printf("Ok, and the second number? ");
  12. scanf("%f", &b);
  13. printf("What do you want to do with these two numbers?\n");
  14. printf("Press only the specified keys or I'm gonna yell at you!\n\n");
  15. printf("a = add\n");
  16. printf("s = subtract\n");
  17. printf("* = multiply\n");
  18. printf("/ = divide\n");
  19. scanf("%s", &o);
  20. printf("You picked %s. \n", o);
  21.  
  22.  
  23. switch (i[o])
  24. {
  25.  
  26. case 'a':
  27. {
  28. answer = a + b;
  29. printf("%f + %f = %f\n", a, b, answer);
  30. a, b, answer = 0;
  31. break;
  32. }
  33. case 's':
  34. {
  35. answer = a - b;
  36. printf("%f - %f = %f\n", a, b, answer);
  37. a, b, answer = 0;
  38. break;
  39. }
  40. case '*':
  41. {
  42. answer = a * b;
  43. printf("%f * %f = %f\n", a, b, answer);
  44. a, b, answer = 0;
  45. break;
  46. }
  47. case '/':
  48. {
  49. answer = a / b;
  50. printf("%f / %f = %f\n", a, b, answer);
  51. a, b, answer = 0;
  52. break;
  53. }
  54. case 'q':
  55. {
  56. return 0;
  57. }
  58. default:
  59. {
  60.  
  61. printf("Hey dammit! I told you to pick one of the choices specified! Raargh!\n");
  62. }
  63.  
  64. }
  65.  
  66. }

I know you said it would be better to wrap scanf() in another function and have it check for the proper type but I think that's a bit beyond me at the moment. The guide I'm following so far has taught me basic I/O(printf() and scanf()), arrays, do/while, switch/case, and if/else. Functions are in the next chapter. What sucks is that there are 3 exercises and this is only the first... I feel like I'm just asking for more punishment. (Thank you sir! May I have another!?)

I'm still fighting with the loop but I will continue that battle tomorrow. My brain is a bit fried at the moment.
Fengalon is offline   Reply With Quote
Old Aug 18th, 2008, 4:15 AM   #4
lectricpharaoh
Caffeinated Neural Net
 
lectricpharaoh's Avatar
 
Join Date: Jun 2005
Location: Dry west coast of Canada
Posts: 1,009
Rep Power: 5 lectricpharaoh will become famous soon enough
Re: looping fun

Quote:
Originally Posted by Fengalon
I stripped down the code to just it asking for the two floats and a char. I also added another printf() at the end so that I could see what exactly the scanf() asking for char was doing. Sure enough, it would be output NULL. I changed the char to a char array and had scanf() look for a string instead of a character and IT WORKED! .....but I have no idea why.
When the user inputs data at the keyboard, it is a string, at least as far as the input routines are concerned. When you tell scanf() or its brethren (fscanf(), etc) to read something like a number, it will need to convert it. The value 40 is not the same as the value "40". The first is a single value, of int type by default. The latter is a const pointer to a const sequence of characters, being '4', '0', and a char with a binary value zero ('\0' or (char)0). If you're familiar with ASCII or other text encoding methods (Unicode, etc), you will remember that a single digit's ASCII (or whatever) value is not necessarily the same as the value that digit represents. Here's a table.

Basically what I'm getting at is that because the input is already in string format, scanf() doesn't have to do any conversions, and basically cannot fail. More precisely, it should only return EOF on an error as described in my initial post, and should never return zero (actually, it might, if the string address you pass in is NULL, but that's another discussion). However, you do have to watch out for other things when inputting strings, though; foremost among these would be the dreaded 'buffer overflow' error. This happens when you allocate space for x characters (plus the terminating zero), and the user inputs more than x characters. It's also why languages such as C# and C++ that have dedicated string classes make this sort of problem a lot easier to avoid.
Quote:
Originally Posted by Fengalon
When scanf() is asking for a %c and I input a single character, it is my understanding that that is all I am giving it. Or is it? I know in strings, I have to account for the string terminator (NULL or \0 I believe). Is there also a terminator in a char variable as well? Is scanf() just funny that way? Or is it something else I'm missing?
When you input data with scanf(), it actually ignores whitespace (spaces, tabs, and newlines), except for (probably) needing a newline (ie, the user hitting the ENTER key) at the end of the line (see my earlier post regarding 'line buffered' input).

This means that scanf() will fill in the char variable whose address you pass with the first non-whitespace character the user enters. If the user doesn't enter anything, it will not fill anythign in (ie, scanf() will successfully convert fewer than the requested number of items).

Thus, if the single character you want to read is potentially a whitespace character, scanf() really isn't the tool for the job. You'd be better off using fgetc() for this:
char inputChar = fgetc(stdin);
You can also use the getchar() macro if you want to read from standard input; this is just an alias for fgetc(stdin). I'd recommend the former though, as it will make your code easier to modify if you later choose to read from a stream besides standard input (such as if you want your program to process a text file of commands for 'batch mode' operation).
Quote:
Originally Posted by Fengalon
I know you said it would be better to wrap scanf() in another function and have it check for the proper type but I think that's a bit beyond me at the moment. The guide I'm following so far has taught me basic I/O(printf() and scanf()), arrays, do/while, switch/case, and if/else. Functions are in the next chapter. What sucks is that there are 3 exercises and this is only the first... I feel like I'm just asking for more punishment. (Thank you sir! May I have another!?)
Heh, the only line from Animal House I know.

Anyways, I think you should read ahead. If you don't get something in the current chapter, later chapters might shed some light. Often, with programming, you have knowledge with circular dependencies; to fully understand concept A, you may need some knowledge of concept B, and vice-versa. In particular, I'm surprised you can make any sense of scanf() without at least a basic knowledge of pointers, which is probably not something you've covered yet.

Anyways, apologies if this post was less than coherent. I just got home a little while ago, and my brain isn't working too well at the moment.
__________________
And once again, Probability proves itself willing to sneak into a back alley and service Drama as would a copper-piece harlot.
- Vaarsuvius, Order of the Stick
lectricpharaoh is offline   Reply With Quote
Old Aug 18th, 2008, 12:19 PM   #5
Fengalon
Newbie
 
Join Date: Aug 2008
Location: Florida
Posts: 8
Rep Power: 0 Fengalon is on a distinguished road
Re: looping fun

So basically, when I have scanf() ask for a character like I did, scanf() still considers the input a string even though I'm inputting a single character? Well that makes sense why that works now.

Thanks for your help pharaoh! I'll most likely be back for more when I get home to tackle the looping part of it.
Fengalon is offline   Reply With Quote
Old Aug 18th, 2008, 12:56 PM   #6
lectricpharaoh
Caffeinated Neural Net
 
lectricpharaoh's Avatar
 
Join Date: Jun 2005
Location: Dry west coast of Canada
Posts: 1,009
Rep Power: 5 lectricpharaoh will become famous soon enough
Re: looping fun

Quote:
Originally Posted by Fengalon
So basically, when I have scanf() ask for a character like I did, scanf() still considers the input a string even though I'm inputting a single character? Well that makes sense why that works now.
Well, not quite. The original input is a string (in the sense of 'sequence of zero or more characters'), but it needs to be converted to the type you're telling scanf() to read. Thus, if you're looking for a string, no conversion is necessary (as long as scanf() is able to read something, it will work). Remember that the string can be zero characters plus the terminating zero.

If you want a single character, like I said, use a different function; this will allow you to check for whitespace characters as well.
Quote:
Originally Posted by Fengalon
Thanks for your help pharaoh! I'll most likely be back for more when I get home to tackle the looping part of it.
Just wait until you get to pointers. Those confuse a lot of people, but really, they're very simple; people just overthink them a lot because they have a reputation as being hard.
__________________
And once again, Probability proves itself willing to sneak into a back alley and service Drama as would a copper-piece harlot.
- Vaarsuvius, Order of the Stick
lectricpharaoh is offline   Reply With Quote
Old Aug 19th, 2008, 12:42 AM   #7
Fengalon
Newbie
 
Join Date: Aug 2008
Location: Florida
Posts: 8
Rep Power: 0 Fengalon is on a distinguished road
Re: looping fun

VICTORY! It asks for the two numbers and a which calculation you want done. It also keeps looping until you give it the q command in which case it quits. I know you're all probably thinking "Hoohum, I could do that in my sleep," but I feel like I'm finally getting somewhere. I can't wait till I get to the pointers section that I hear everyone had such a hard time with!

C Syntax (Toggle Plain Text)
  1. #include <stdio.h>
  2.  
  3. float a, b, answer;
  4. char o[2];
  5. char s;
  6. int i;
  7.  
  8. int main()
  9. {
  10. for(s ='q'; i[o] != s;)
  11. {
  12. printf("What's the first number? ");
  13. scanf("%f", &a);
  14. printf("Ok, and the second number? ");
  15. scanf("%f", &b);
  16. printf("What do you want to do with these two numbers?\n");
  17. printf("Press only the specified keys or I'm gonna yell at you!\n\n");
  18. printf("a = add\n");
  19. printf("s = subtract\n");
  20. printf("* = multiply\n");
  21. printf("/ = divide\n");
  22. printf("Press 'q' to quit\n\n\n");
  23. printf("Please enter your selection: ");
  24. scanf("%s", &o);
  25. printf("You picked %s. \n", o);
  26.  
  27. switch (i[o])
  28. {
  29. case 'a':
  30. {
  31. answer = a + b;
  32. printf("%f + %f = %f\n", a, b, answer);
  33. a, b, answer = 0;
  34. break;
  35. }
  36. case 's':
  37. {
  38. answer = a - b;
  39. printf("%f - %f = %f\n", a, b, answer);
  40. a, b, answer = 0;
  41. break;
  42. }
  43. case '*':
  44. {
  45. answer = a * b;
  46. printf("%f * %f = %f\n", a, b, answer);
  47. a, b, answer = 0;
  48. break;
  49. }
  50. case '/':
  51. {
  52. answer = a / b;
  53. printf("%f / %f = %f\n", a, b, answer);
  54. a, b, answer = 0;
  55. break;
  56. }
  57. case 'q':
  58. {
  59. return 0;
  60. }
  61. default:
  62. {
  63.  
  64. printf("Hey dammit! I told you to pick one of the choices specified! Raargh!\n");
  65. }
  66. }
  67. }
  68. }

Feel free to criticize away! Please let me know if I can do anything better. Better that I hear about it now than learn about it later on the hard way.
Fengalon is offline   Reply With Quote
Old Aug 19th, 2008, 1:02 AM   #8
BstrucT
Hobbyist Programmer
 
BstrucT's Avatar
 
Join Date: Dec 2007
Location: Durban, South-Africa
Posts: 175
Rep Power: 1 BstrucT is on a distinguished road
Re: looping fun

Quote:
Originally Posted by lectricpharaoh View Post
Just wait until you get to pointers.
Eek!
__________________
The more the human race tries to change everything, when not needed, the less will they be able to change themselves when they need to.
BstrucT is offline   Reply With Quote
Old Aug 19th, 2008, 1:08 AM   #9
BstrucT
Hobbyist Programmer
 
BstrucT's Avatar
 
Join Date: Dec 2007
Location: Durban, South-Africa
Posts: 175
Rep Power: 1 BstrucT is on a distinguished road
Re: looping fun

This thread reminds me of when I was busy with the same type of program long time ago, when I started learning C.

see here

I know it sucks, but it might show you what not to do, hehe
__________________
The more the human race tries to change everything, when not needed, the less will they be able to change themselves when they need to.
BstrucT is offline   Reply With Quote
Old Aug 19th, 2008, 1:01 PM   #10
Fengalon
Newbie
 
Join Date: Aug 2008
Location: Florida
Posts: 8
Rep Power: 0 Fengalon is on a distinguished road
Re: looping fun

I looked through some of that code and came across this little gem:

return (main());

I was like "wha...?" but then Grumpy's post cleared that all up. Real nice.
Fengalon is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
error trappring and looping mrynit Java 5 Jan 22nd, 2007 7:58 AM
Looping effect, when entering string in an int variable lamefif C++ 7 Jan 5th, 2006 11:29 AM
Endless looping >_< jch02140 C 13 Aug 4th, 2005 6:43 AM
looping in awk gwilliam Sed and Awk 3 Jun 20th, 2005 9:12 AM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 12:00 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC