Link to home
Start Free TrialLog in
Avatar of indy500fan
indy500fan

asked on

Need logic help, play or exit on a console app.

Friends,

I am trying to work through the logic, but I obviously have something really wrong (I have attached the code I have so far).

What I am trying to do, is start a game, and then, once the player has done it once, I want to give them the choice of playing again or exiting.

If they don't type 1 or 2, i want to give them an error message.

Looking for syntax help specifically, please!

Thanks in advance!
int main()
{
printf("Hi!  Let's play the name game!!!\n");
printf("Please type your name and then press Return...\n\n");

scanf ("%s",screenName);
formatName();
	  while (i != 2 || i != 1)
	  {
		printf ( "Type 1 to play again..." );
		printf ( "Type 2 to exit..." );

		scanf ("%d",&i);
		if (i == 2 || i == 1)
		{
			if(i=1)
			{
				scanf ("%s",screenName);
      			formatName();
			}
			else
			{
				return 0;
			}

		}
		else
		{
		printf("Uh, I didn't quite catch that, please try again...\n\n");
		}
	  }
	 
}

Open in new window

Avatar of Kent Olsen
Kent Olsen
Flag of United States of America image

Hi Indy,

An easy way to do that is to set i to 1 or 2 before the while() statement.  It will evaluate TRUE to enter the loop, then the player is prompted for his selection.


Good Luck,
Kent
Avatar of indy500fan
indy500fan

ASKER

Kent,

Need more help than that.  It didn't work.
You probably should become aware of the switch statement:
     http://www.cprogramming.com/tutorial/lesson5.html

>>If they don't type 1 or 2, i want to give them an error message.
The default usage in the switch statement is useful for handling invalid cases.
What didn't work?

One thing that will bite you is your format string.  Scanf() is a little trick sometimes.

The integer should be read using a format string that also skips the trailing newline, otherwise you wind never pausing for the next input.


  scanf (%d\n", &i);



Kent

Alternatively, you can also call fflush (stdin) before every call to scanf().  This is non-standard (not part of the C official protocol) but works for every version of C that I know of.


Kent
Kent,

I wanted to give an error message, but I can't figure out a way to do it.  For 500 points, I am really looking for specific syntax help within my problem, not general suggestions.

This will work, I would just like to add the error message (if they type g, instead of 1 or 2), but this will work:


int main()
{
	while (i < 3) 
		{
		iCounter++;
		if (iCounter == 1)
		{
			printf ("Hi!  Let's play the name game!!!\n\n");
			printf ( "Type 1 to play, followed by Return...\n" );
			printf ( "Type 2 to exit, followed by Return...\n" );
		}
		else
		{
			printf ("Would you like to play the name game again???\n\n");
			printf ( "Type 1 to play again, followed by Return...\n" );
			printf ( "Type 2 to exit, followed by Return...\n" );
		}
		scanf ("%d", &i);

		
			if (i < 1 || i > 2)   // Sanity check and exit
			break;
			if (i==1)
			{
				printf("Please type your name and then press Return...\n\n");
				scanf ("%s",screenName);
      			formatName();
			}
			else if (i==2)
			{
				break;
			}
		}	

		if ( i == 2 )
		{
		return 0;
		}
}

Open in new window

You did not show us the error messages or issue things you have got..

In the above code,

1. there is not declaration and intialization of i in the main()

           

           
 int main()
           {
              int i;
              ..some other declarations ...
             and your while()}
           loop

Open in new window

2. use fflush(stdin) as other said in the other suggestions,and he gave the easy  soultion already ,
  validate the i value before calling main

      like from main

       
int main()
{
      int i,
      scanf("%d",&d);
      if(i<0 && i>2)
      {
           printf(" Error message ");
           return 0;
          }
} 

Open in new window



 or use the switch statement as the phoffic asked

Here experts did not give the exact  code (coded solution)you have wanted that breaks the expert-exchange academic assignment agreement .instead allowed to give suggestions
follow up the suggestions and if you got errors comback to us some other expert will avaliable here to help yu
   


 
           
Sorry, but I just have to comment on this :

>> 2. use fflush(stdin) as other said in the other suggestions

Given that fflush(stdin) is not guaranteed to work (as has been mentioned by Kdo), I recommend against using it.

Instead, the proper way of reading input, is line-by-line. Use fgets to read a line of input, and then parse it with sscanf eg.
Doing it this way, you will not have to worry about the stream going into an invalid state, nor will you have to worry about any invalid characters that need to be "flushed" from the stream.

Learning things properly from the start will help you a lot in the long run (because it's difficult to unlearn bad habits).



And one more remark : one of the reasons your original code didn't work, was that the loop condition caused the loop to loop forever. This :

>>         while (i != 2 || i != 1)

is always true.
Hi Indy,

Going back to your original source code, changing it up just a little bit should do the job.

By the way, if this were written in to the C++ language, or a couple of the extended C compilers, the do{}while; syntax would be what you want.  But that's nowhere near universal in C.

I've made four small changes to your code.

1.  while(1).  Instead of testing the loop condition at the start, always loop.  The controls in the loop will exit.
2.  The if/else block was a little muddled.  This is cleaner.
3.  The scanf() format strings now scan until a newline is found.  Still not perfect, but it will at least work now.
4.  ==  Your conditions in the *if* statements were actually assignments, not comparisons.  In the C language, a single equal sign is replacement (the variable on the left gets set to the value on the right), a double equal sign compares the two.  There are subtle side behaviors that you need to know.  *i=1* will set the value of *i* to 1.  If that syntax is used in the *if* statement, *i* will get set to 1, and the condition will test for true or false based on the value of *i*.  Since it was set to 1, the value is true.  That is seldom what you want to do!


Good Luck,
Kent


int main()
{
  printf("Hi!  Let's play the name game!!!\n");
  printf("Please type your name and then press Return...\n\n");

  scanf ("%s",screenName);
  formatName();

  while (1)    // loop until an input sets an exit.
  {
    printf ( "Type 1 to play again..." );
    printf ( "Type 2 to exit..." );

    scanf ("%d\n",&i);
    if (i==1)
    {
      scanf ("%s\n",screenName);
      formatName();
    }
    else if (i==2)
    {
      return 0;
    }
    else
    {
      printf ("Uh, I didn't quite catch that, please try again...\n\n");
    }
  }
}

Open in new window

Your code should have been something like this . I assume you have function for formatName and definition for screenName
int main()
{
int i =1;
printf("Hi!  Let's play the name game!!!\n");
printf("Please type your name and then press Return...\n\n");

scanf ("%s",screenName);
formatName();

while (i != 2 || i != 1)
 {

                printf ( "Type 1 to play again..." );
                printf ( "Type 2 to exit...\n" );

                scanf ("%d",&i);
               
               switch(i)
              {

               case 1:
                         printf("Hi!  Let's play the name game!!!\n");
                         printf("Please type your name and then press Return...\n\n");
                         scanf ("%s",screenName);
                         formatName();

               break;
               case 2: return 0;
               break;
               default:
                  printf("Uh, I didn't quite catch that, please try again...\n\n");
               break;

               };
          }

}

kent,

Your suggestion, doesn't actually every run the name game or exit, no matter what is typed...

I attached a screen shot of it running to demonstrate what I mean.

asurianu,

Your suggestion works when I choose 1 or 2, but if I were to type the letter g, it runs the name game with the letter g.

So far, while admittedly clumsy, is the only one that works.

Kent,  you are right.  I have a friend taking a class and he is struggling (I have a background in programming VB), and together we are trying to learn C.

I do best when I have a pertinant example, that I can apply to a present problem, and then I add that routine to my mental database.

Thanks
ASKER CERTIFIED SOLUTION
Avatar of Kent Olsen
Kent Olsen
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hint : to avoid all these problems, simply use fgets to read a line of input into a memory buffer, and then parse that buffer to get the data you need (as I suggested earlier).

Get used to that, and you'll be happy you did. No more worries with keeping input streams consistent.
Kent, this last version does work better; however, if I type the letter g, instead of 1 or 2, it runs throught the name game instead of throwing my error message.

Infinity08,

I'd love to try it.  Can you show me with my example?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Kent,

I'm sorry, and I hope I don't come off as rude, but I am really struggling.

I work best if I have an overall example, to see how everything is integrated (including how vars are declared).

I tried to plug in the fgets example you had and I get the following error.

Error      3      error C2664: 'fgets' : cannot convert parameter 1 from 'FILE *' to 'char *'      c:\documents and settings\owner\my documents\visual studio 2008\projects\project7\project7\project7.cpp      152      project7

I don't even know what this means.
Sorry Indy,

There are a slew of I/O functions available in C.  Unfortunately, they don't have a consistent parameter scheme.  Most of the related functions use a common parameter scheme, but when moving to a different set of APIs to do something similar you may run into a different order.

What I typed was essentially correct, but I gave you a bad parameter list.  Again, apologies....

 fgets (Buffer, 100, stdin);


Replace the call to fgets() with the line above.  That should do fine.



Kent
Kent,

We are inching closer...Thanks for all your help so far...


Okay, I had to modify my entry point a bit.  As part of the guidlines, we have to start with a menu choice.

Your fgets does work now (Thank you),,

Now when I enter 1, and then the name, it runs through the routine, but it has a problem.  As you can see from the attached imagine, it runs through the routine again.

How do I make sure it doesn't do that?


char Buffer[100];
int main()
{
	while (1) 
		{
		iCounter++;
		if (iCounter == 1)
		{
			printf ("Hi!  Let's play the name game!!!\n\n");
			printf ( "Type 1 to play, followed by Return...\n" );
			printf ( "Type 2 to exit, followed by Return...\n" );
		}
		else
		{
			printf ("Would you like to play the name game again???\n\n");
			printf ( "Type 1 to play again, followed by Return...\n" );
			printf ( "Type 2 to exit, followed by Return...\n" );
		}
		    fgets (Buffer, 100, stdin);
			i = 0;
			sscanf (Buffer, "%d", &i);
		
			//if (i < 1 || i > 2)   // Sanity check and exit
			//break;
			if (i==1)
			{
				printf("Please type your name and then press Return...\n\n");
				scanf ("%s",screenName);
      			formatName();
			}
			else if (i==2)
			{
				break;
			}
			else
			{
			printf ("Uh, I didn't quite catch that, please try again...\n\n");
			}
		}	

		if ( i == 2 )
		{
		return 0;
		}
}

Open in new window

screenshot3.JPG
It's like i need to reinitialize Buffer (clear it).
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Okay, that seems reasonable, but can you give me an example when looking for strings instead of integers?
sscanf has the same parsing behavior as scanf. The only difference is that scanf reads from an input stream, and sscanf reads from a string.

        http://www.cplusplus.com/reference/clibrary/cstdio/scanf/
        http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/

So, you parse in the same way as you did with scanf.
I find this forum very frustrating.  Again, I don't know if there are differences between C and C++ with the methods you are suggesting.

In the experts-exchange VB.net forum, they are very helpful with examples relevant to my question.  Why is everyone so quick in this forum to point me to external sites (Kent, you do a good job helping me with specifics to my example)?

I have searched the internet for external sites and examples, but they don't help me with my specific example.

How can I phrase my question so that I get specific help with my examples?
Infinity,

I am so dang confused.  We were dealing with scanf's and you said to use fgets.  Now that I am asking about a fget example (with strings), you are referring me back to using scanf!?!?

what in the world?
Infinity,

Okay, I just threw this fget in there, and changed the sscanf to use string, and now the whole routine works just as I need.

I am not trying to be a jerk, but this method of learning was very frustrating.

Instead of pointing me to external sites, I would have appreciated the following:

fgets (Buffer, 100, stdin);
sscanf (Buffer, "%s", screenName);

How can I be more clear in how I ask for help?

Thanks

int main()
{
	while (1) 
		{
		iCounter++;
		if (iCounter == 1)
		{
			printf ("Hi!  Let's play the name game!!!\n\n");
			printf ( "Type 1 to play, followed by Return...\n" );
			printf ( "Type 2 to exit, followed by Return...\n" );
		}
		else
		{
			printf ("Would you like to play the name game again???\n\n");
			printf ( "Type 1 to play again, followed by Return...\n" );
			printf ( "Type 2 to exit, followed by Return...\n" );
		}
		    fgets (Buffer, 100, stdin);
			i = 0;
			sscanf (Buffer, "%d", &i);
		
			//if (i < 1 || i > 2)   // Sanity check and exit
			//break;
			if (i==1)
			{
				printf("Please type your name and then press Return...\n\n");
				;scanf ("%s",screenName);

				fgets (Buffer, 100, stdin);
				sscanf (Buffer, "%s", screenName);
      			formatName();
			}
			else if (i==2)
			{
				break;
			}
			else
			{
			printf ("Uh, I didn't quite catch that, please try again...\n\n");
			}
		}	

		if ( i == 2 )
		{
		return 0;
		}
}

Open in new window

>> Okay, I just threw this fget in there, and changed the sscanf to use string, and now the whole routine works just as I need.

Excellent.

>> I am not trying to be a jerk, but this method of learning was very frustrating.

I'm sorry for that. But I'm pretty sure that you have a good understanding of this technique now, since you managed to figure the specifics out for yourself. Correct ? If so, then that's a success, no ?

I realize that not everyone likes to learn in the same way, and that my way of teaching might not suit everyone. But I've had very good results with doing it this way, so that's what I keep doing :)

I can't please everyone heh :)

So, I guess, I'll leave things to the others then.
Infinity,

I've been programming for 7 years now (VB.net), and I understand logic for the most part, but I struggle with syntax of C.  

That's why I keep asking for syntax relative to my example specifically.

If I tell you upfront that's how I learn best, why try a method that is frustrating for me.  I understood what you were trying to do from a logic stand point (for the most part), but I need the syntax help.

How can I make it clear to experts when asking a question what I am looking for syntax help, relevant to my example, specifically?

Thanks for your help by the way.  I don't want to seem ungrateful.  :)
Hi Indy,

Sorry, but I had to be elsewhere for a while.  Still, you were in very capable hands.  Infinity08 is as good as we have here.  :)

Please don't let the slow pace frustrate you.  One of the things that Experts-Exchange is very big about is "academic integrity".  The seasoned experts are very mindful of it and we make every effort to groom the new experts in the same thinking.  We aren't in the business of doing people's homework and make every effort to determine whether we're helping with a professional question (that can be offered every possible benefit) or an academic one where we try to teach while we're getting to the correct answer.

This question is actually in a gray area.  We're helping you to learn C as part of your learning with a friend.  We have no control over how you present the answers to your friend nor do we know if your friend is taking a C class or simply wants to learn C.  We're taking it on good faith that the solutions that we present to you don't end up being turned in by your friend as homework.

Anyway, we're glad to help and glad that you came to EE for assistance.


Now, back to the problem at hand.  :)

I/O can be confusing and irritating, like a lot of things in C.  One of the oddities is that the console I/O (using scanf, printf(), etc.) goes "directly" to/from the keyboard and monitor without being buffered by the I/O system.  Certain drivers translate the characters so that things like font color, cursor positioning, etc. can be handled just by sending the right character string.

The standard input and output streams are called *stdin* and *stdout*.  They are often mapped to the keyboard and monitor, but are buffered by the system's input and output routines.  Characters that are read or written through these streams don't translate the characters through the same driver(s) used by the console input and output.

So that's why programs need to be consistent in using the console functions and/or the stream functions.  Weird things happen when you try to use both and it takes a seasoned C programmer to understand them.  And most seasoned C programmers don't try to use both to control the same input or output.


Kent
Kent,

I guess I understand your logic as to keeping this above the board for academic purposes; however, I am a seasoned professional (though obviously not at C :) ) trying to learn enough to tudor my young friend.

I am trying to complete the project, so that I can tutor him through the process, as he works it.  I do not intend to just give him my work, but it is hard to tudor someone if you don't have any basis from which to teach.  I can teach him the logic, but I desperately need syntax help.

I have been a member of experts-exchange for over 6 years and I would certainly not like others to inject their sense of moral code without fully understanding the situation.  I need help with syntax, and I thought that's what I asked for, but I'm not sure that is clear.  The purpose of this forum is partly to learn, but also it is about providing answers to problems.  

I am taking my personal time to work with this individual, because he desperately needs help.  I am trying to work through this as quickly as possible so that I can get on with living life with my family, and helping someone else learn, at the same time.  For someone else to try to lead me through the process is frustrating to say the least.

I would appreciate, as a long-standing member of experts-exchange, to be given direct answers to the questions asked here, and I don't think I'm being unprofessional in my request.

Am I being unreasonable?
Hi Indy,

I don't think that you're being unreasonable at all.  It's quite generous of you to dedicate time to your friend this way.  (By the way, the Experts here donate their time, too.  The only staff that EE maintains is the core group that owns the site, builds it and markets it.  That list includes only the delivery mechanism, not the experts.)

So let's recap.  After the last several exchanges I'm not sure exactly where we are.  Then I'll try to fill in all the blanks as quickly as possible.


Kent
Kent,

I'm good now, I'm going to award points based on both your's and Infinity suggestions.  I was just expressing frustration that it took so long to get to an answer.

Thank you for your help!  I wouldn't have learned programming if it wasn't for the EE community.

Best Regards,
Eric
>> Thank you for your help!  I wouldn't have learned programming if it wasn't for the EE community.

That is nice to hear, and I hope we can be of further assistance to you.

Programming is not an easy thing to master - especially not in a language like C - so it takes quite a bit of effort at first to get some confidence in it.

I remember the days I was first getting acquainted with C like it was yesterday, and it's tough, no matter which approach you take to learn it.

I have never believed in learning by example - at least not initially. There are too many bad examples floating around, and it is too easy to misinterpret an example, or to re-use it in the wrong context. If there is no complete understanding of why a certain construct is used in an example, and why it is preferable over other ways, examples tend to teach the wrong things in my experience.

That is why I prefer to try to provide a deeper understanding of things, from which endless examples can then be constructed. By no means do I claim to be perfect at this, but I can give it my best shot.

I respect that that might not be what everyone is looking for, but it is what my experience has taught me, and I rarely go against my experience :)

I hope this somehow makes sense to you, and will be available for any further questions you might have. And I would like to apologize for any frustration I might have caused.
Infinity,

I am not exactly a talented proogrammer, and I do very much learn by example.  You are like my friend (and ended up being the best man in my wedding) in that he can take something so small and expand upon it.  I'm amazed how people like you can do that.

Sorry I was so frustrated earlier.  I do get what you were trying to do, and I greatly appreciate your help.