Solved

infinite loops and flushall()

Posted on 2008-10-11
22
527 Views
Last Modified: 2010-04-21
if I remove flushall() then enter a letter instead of 1 or 2 the program goes into an infinite loop.
My thought here was to isolate the choices...<=0...>=3 then by using flushall() eliminate the garbage that causes infinite loops.  Is this close to what is happening?  I did look into fgets & fscanf...that option looked rather complicated to me.
#include <stdio.h>

#include <conio.h>

# include <ctype.h>
 

#define TRUE 1

#define FALSE !TRUE
 

char stay_open,c;

int menu;
 

int main(void)

{

	stay_open = TRUE;

	while (stay_open)

	{

		do

		{

			flushall();

			printf("\nEnter 1. for Option 1  ");

			printf("\nEnter 2. for Option 2  \n\n");

			scanf("%i",&menu);
 

			if ( (menu >= 3) || (menu <= 0) )

			printf("\nNot an option, try again!\n");

		}

		while ( (menu >= 3) || (menu <=0) );
 

			switch (menu)

			{

				case 1:

					printf("\nOK Option 1");

					printf("\n\nPress any key to continue.");

					c=toupper(getch());

					break;

				case 2:

					printf("\nOK Option 2");

					printf("\n\nPress any key to continue.");

					c=toupper(getch());

					break;

			}
 

		printf("\n\nStay Open? Any key for YES, N for NO.\n");

		c=toupper(getch());

		if(c == 'N')

		{

			stay_open=!TRUE;

			printf("\nAdios");

		}

	}

		return 0;

}

Open in new window

0
Comment
Question by:FrawgLips
  • 5
  • 5
  • 3
  • +3
22 Comments
 
LVL 45

Expert Comment

by:sunnycoder
Comment Utility
fflush on stdin is undefined.

fgets() followed by parsing is your best bet.
0
 

Author Comment

by:FrawgLips
Comment Utility
Infinity08 I saw your post after I closed the last question...So, you see, I have kept my original code and did indeed look into your suggestion....cheers
0
 
LVL 45

Expert Comment

by:sunnycoder
Comment Utility
here is a sample

                        printf("\nEnter 1. for Option 1  ");
                        printf("\nEnter 2. for Option 2  \n\n");
                        scanf("%i",&menu);
can be written as




#define MAX_LINE_BUFFER 128

char buffer[MAX_LINE_BUFFER];

...

printf ("\nEnter 1. for Option 1  ");

printf ("\nEnter 2. for Option 2  \n\n");

fgets (buffer, MAX_LINE_BUFFER, stdin); //return value check omitted for brevity

menu = atoi (buffer); 

//as you get more comfortable move from atoi to strtol - something that would let you validate your input

Open in new window

0
 
LVL 10

Expert Comment

by:peetm
Comment Utility
flushall() - um, don't recognise it.

0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
>> Infinity08 I saw your post after I closed the last question...So, you see, I have kept my original code and did indeed look into your suggestion....cheers

No problem. But I think you misunderstood my advice. Flushing the input is not the way to go ... My suggestion was to use fgets to read input one line at a time, and then get the actual values from the line string that was read. That's a lot more robust, and avoids leaving garbage on the stream (no need to flush either ;) )
0
 

Author Comment

by:FrawgLips
Comment Utility
sunnycoder....
OK, I'm confused....if fflush is undefined, why, by using it, does it stop the looping?
And, if fgets is a better option could you tell me why?
Your suggestion performs fine after including stdlib....
Thanks

0
 
LVL 23

Expert Comment

by:Mysidia
Comment Utility

calling fflush() or flushall()  does not consume any input;  the same character is still waiting.

scanf("%i",&menu);

doesn't consume any input either, if there's an error.

Here's what I suggest:

if (  scanf("%i",&menu)  < 1 ) {
         (void)getchar();
}

This will  consume 1  character of input and throw it away  if scanf fails,
thus preventing the loop from being endless.


fgets()  is a better option for real programs,  because it is more efficient,
and the input that will satisfy it is more precise:  some text followed by a newline.
scanf()  involves parsing.
for example
scanf("%d %d", &a, &b);
will wait for 2 numbers to be received on input before returning,  even if they are on different lines.

If you expect a number on its own line,  scanf() is wasteful.

fgets() is also necessary if you need detailed control of input:
for example, giving the user an option to type either 1 number or 2 numbers
on the same line.

Calling  fgets()  gives you more detailed control of how the input will be processed.



fgets()  will always fill the buffer with one's line input,  and atoi() will
convert exactly one item.

This is a more consistent result  for interacting with a user.



0
 
LVL 23

Accepted Solution

by:
Mysidia earned 125 total points
Comment Utility
To clarify.. if you use
scanf("%i", &menu);

 and the user types
"3 4"  as input.

the scanf only consumes the 3.

If you had another scanf later i.e.
scanf("%i" &b);

The second scanf will consume the '4'  and fill in b=4;

Despite the fact the user answered only the first prompt,
and did not type anything at the second prompt.


0
 
LVL 45

Assisted Solution

by:sunnycoder
sunnycoder earned 125 total points
Comment Utility
>if fflush is undefined, why, by using it, does it stop the looping?
You have been lucky. It is not guaranteed to work the same on all platforms. In fact different versions of the same platform can give you different results.
http://www.cprogramming.com/faq/cgi-bin/smartfaq.cgi?answer=1052863818&id=1043284351

>And, if fgets is a better option could you tell me why?
Mysidia has already answered that in detail :)
0
 
LVL 10

Expert Comment

by:peetm
Comment Utility
Try:

void flush_stdin(void)
{
    int c;

    while((c = getchar()) != '\n' && c != EOF)
        ;
}
0
 

Author Comment

by:FrawgLips
Comment Utility
OK, Teachers....thank you...your input  is greatly appreciated.  If only I could "fgets" this in my head.  just kidding... infinity08, sunnycoder,  mysidia and peetm...I redid the code...using fgets  and sunnycoders snippet....infinity08,  I was probably wrong to give points for my last post as I ended up using part of your suggestion.....Mysidia..very good.........peetm..haven't tested your suggestion..but I did see something similar a while back..... at any rate I believe I need to allocate more points and split them up amongst you 4 .....what is acceptable to each?  
thanks again,
FL

0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 10

Assisted Solution

by:peetm
peetm earned 125 total points
Comment Utility
No worries about the points.
0
 
LVL 53

Assisted Solution

by:Infinity08
Infinity08 earned 125 total points
Comment Utility
>> infinity08,  I was probably wrong to give points for my last post as I ended up using part of your suggestion.....

Don't worry about that ... I'm just happy I could help.


If you want, you can post the code you have now, so that we can have a look over it.
0
 

Author Closing Comment

by:FrawgLips
Comment Utility
In my "self help" books I do not recall seeing any function other
than scanf.... (I am temporarily not where all my books are.)  
Looking in Borland's help I find  a lot of information..."scanf might
stop scanning a particular field before it reaches the normal
end-of-field(whitespace)character, or it might terminate entirely."  It
goes on to tell many reasons for this.....Then...."Warning: scanf
often leads to unexpected results if you diverge from an expected
pattern.  You must provide information that tells scanf how to
synchronize at the end of a line."  No mention what this "expected
pattern" is or what the "info" is or where to put it......
(#define scanf  a shaky function for the unwary....)

I was having problems with the program I was writing....the one I
posted was for info and illustration only....I will close this Q then
open another with the actual intended one...thanks all.
I find a problem with the points here at EE.....I wish not to slight anyone one but at the same time I would like to give more points to those who gave more detail....a catch22...hopefully it will work out in the long run....
0
 

Author Comment

by:FrawgLips
Comment Utility
lot of work grading...lol   thanks all
0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
>> No mention what this "expected pattern" is or what the "info" is or where to put it......

The "expected pattern" is what you expect the input to be. However, what you expect is not necessarily what you'll get as input - especially if that input is entered by a user.
The "info" is providing a format that includes end-of-line synchronization. But as I said, it's a lot easier and a lot more robust to simply read a line into a string, and then process that string.
0
 
LVL 23

Expert Comment

by:Mysidia
Comment Utility
The only real pitfall with  fgets()  is to be wary  about what happens when the maximum buffer length is exceeded.

The next call to  fgets()  will read  the rest of the line.
You can detect this   by  checking if  the buffer contains a newline character:
strchr(buffer, '\n');

For simple test programs,  just  use a large enough size that a single line will never exceed it,  i.e.  512 bytes    is usually fairly safe for user input.
Either that or treat is as an error,  and call  fgets()  more times
behind the scenes until  strchr(buffer, '\n')   returns true.


There are a few errors that can cause fgets() to fail;  not as many as scanf;  primarily:  system running out of memory,  end of file..  fgets() will return NULL when these happen,  whereas it normally returns  a pointer to the string



Something to keep in mind with fgets()  is that using it doesn't stop you from also using format-based parsing of a single line if you want

For example, you can store a line in a string buffer, and then use

if ( sscanf(buffer, "%i %d:%d", &x, &y, &z) < 3 ) {
    /*  Error handling code here */
}

Which will only scan 'buffer'.  for a string like   "3 4:5".
scanf  returns the number of   values that were successfully parsed.
and fills in  x=3,   y=4,   z=5


This allows you to have some of the conveniences of scanf() in well
defined cases without
the disadvantage of giving formatted reading functions  control
of how you read the lines in the file,  like scanf  does.

sscanf()  with fgets() is  (IMO)  much more useful than scanf(),   since it is easier to keep control over what it does.

Plus you can parse the integers with  sscanf(),   and then
examine the buffer to find the string that follows them,  instead of using
sscanf     with   %[^]   to match  a multi-word string



The above sscanf() is more convenient than   writing your own lexer or using something like

char *token;
int *temporaryArray[] = { &x, &y, &z };
for(  int i = 0;  (token = strsep(&tempbuffer, " "))  != NULL ; i++  )
{    
   *(temporaryArray[i]) =   atoi(token);
}

Or...

char *temp;

 temp = buffer;
 while(isspace(*temp))  { temp++ ; }

 x =  strtod(temp, &temp, 10);
 if (temp != NULL && temp != buffer) {
       y = strtod(temp, &temp, 10);
       while(isspace(*temp))  { temp++ ; }

       if (temp != NULL && temp != buffer) {
            z = strtod(temp, &temp, 10);
            while(isspace(*temp))  { temp++ ; }
      }
 }


0
 
LVL 16

Expert Comment

by:t0t0
Comment Utility
Frawglips...

How are you progressing with your menu - in particular, the user input section?

During my short absence, I have designed a function which gets a valid input from a user.
0
 
LVL 16

Expert Comment

by:t0t0
Comment Utility
Frawglips

Just reading through this thread, I couldn't help but notice your comment regarding the points awarded in your previous thread.

I disagree with your comment. Your previous post suggested you required assistance with the design of your loops - in particular, your concerns regarded infinite loops.

I submitted code which demonstrated simplicity, clarity, logic and structure - basically, everything that lacked in your program.

I feel I have provided you with a fully workable solution to your previous problem and therefore I feel I deserved to receive the points I was awarded. You may have taken infinity08's suggestion to 'learn from your own mistakes' by apparently tinkering with your code but I fear you are little or no wiser than you were when you posted your prevoius question.

This current thread focuses on how C processes input from the keyboard. I suspect you still have problems with your loops and this is most likely due to logic errors and a lack of understanding of C's input functions.

I was going to suggest you start a new thread entitled "How Do I Write My Own Input Function" so that I could post you a full working solution to your problem would of included a complete custom written reusable input routine which does not rely on fgets() nor scanf() - these are buffered input streams - my solution captures unbuffered characters typed in at the keyboard. But my fear is you would regret awarding me the points.

By all means, post your code as suggested by infinity08.... and if you end up rewriting it to incorporate fragments of code designed by others then I think you will have proved my point that one does not always learn from their own mistakes.

Instead of reinventing the whole wheel, would you not be just as happy inventing a better spoke thus leaving you more time to spend on the carriage?
0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
t0t0, whether or not you agree with my approach is not relevant, but please do not misrepresent it. I did not suggest to "tinker" with his code on his own, but rather suggested to use his current code as a starting point (because it was rather good already) and modify it with our guidance and suggestions.

You may not think that he'd learn a lot more that way, but I do. By modifying his own code based on our suggestions, he sees what was wrong with his own code (and thus learns how not to do it), and learns how to fix it and do it correctly. That'll always be better than simply copying a piece of code and throwing all your previous efforts out of the window.

Let me ask you this question : how did you learn about I/O in C ? Did you make mistakes, and then had someone point out the mistakes to you, and helped you fix them ? Or did you rely on someone giving you a different piece of code whenever there was an issue with yours ?

Problem solving is a very important part of being a programmer, but for that you need to understand how everything works first, and if you get everything handed on a golden plate, you won't.

To me, these different approaches to learning result in two different types of coders :

1) a copy-paste coder who learned everything by example, and when writing an application, simply refers to different existing fragments of code, and then tries to piece them together.

2) a coder who learned the ins and outs of programming, as well as the pitfalls (by falling in them, and climbing out of them (often with assistance from others)) one might encounter. When writing an application, he applies this knowledge of how to (not) do things.

Of course this is a black-and-white view, but that's not the point. The point is that one will remember not to stick his hand in the fire a lot better by doing it once and getting burned, than by only being told not to.



Apologies for hijacking your question, FrawgLips. I'll end this post with something for you : the questions you ask are your questions, and you decide which posts are most helpful to you. So, don't worry :)
0
 
LVL 16

Expert Comment

by:t0t0
Comment Utility
infintiy08

Firstly, my humble apologies. In no way do I criticising your efforts nor the time you have invested in frawglips' problems. I didn't make this clear in my earlier post - this was probably due to me nodding off at the keyboard until finally dropping onto my bed sometime after 4am.

Permit me to respond to your comment above.

>> "You may have taken infinity08's suggestion to 'learn from your own mistakes' by apparently tinkering with your code".

Your suggestion to 'learn from your own mistakes' is not the focus of my criticism here - although, after reading my own post again I can quite understand how easy it is to misinterpret what I wrote.

Sure, one can learns from his own mistakes but only if one understands the nature of the problem and then understands how and why one arrived at a resolve however, this is reliant on the familiarity of the 'tools' at hand (in this case C's functions) and an understanding of how to use those tools (the ability to design and code programs).

I feet frawglips knows what it is he wants to achieve but given his lack of familiarity with some of C's functions and how to implement them means he is unable to solve his problem.

In some cases, one learns better by example - to which I have no objection whatsoever. This implies one knows it works but not necessarily why or how - so in this case, one is already assured there lies a solution. If there is clarity and methodology in the solution, then the curve of learning increases because it's easier to see why a particular solution solves a problem. This then leaves the 'how' and this is where I feel frawglips needs to focus - by experimenting with different functions so that he is familiar with their application and subsequent behaviour.

This is why I posted a working solution loosely based on frawglips' original design. I refer to the main function here, the other functions were offered as a way of removing the clutter from the problem at hand (and besides, I personally loathe seeing more than 12 or so lines of code in any one single function unless it is really unavoidable - but that's beside the point).

So, in stating the above, I was drawing reference to frawglips 'tinkering' with his code until he accidentally stumbles on a solution without fully knowing why or how, rather than approach the problem methodically and with a greater understanding of C.

In no way do I infer you suggested frawglips should 'tinker' with his code and I agree that modifying his own code while receiving guidance and suggestions from others can be an effective method of learning to solve a problem.

To answer your question, I learned to program on a remote mainframe by punching cards. I quickly embraced BASIC on a ZX81 with open arms and then 6502 and 68000 assembly. I migrated to BBC BASIC, embedded assembly, 8086, Fortran, Pascal, ADA, COBOL, C, C++, VB. Over the years, I have forgotten far more than I remember having probably the worst memory in the world....

Sorry, what was I saying?....

Oh, yeah, How I learned C.... I bought loads and loads of books and spent almost every waking moment thinking in terms of '1's, '0's and hex until it ruined my marriage and left me bringing up a 3-year old child on my own - which is why I dropped out of the scene some 7 years ago. Call it an obsession, a hobby, an art, whatever. I do profess to becoming a little over-sensitive when I feel someone is knocking that which I have lived with alll my life.

Really though, have you heard the phrase 'RTFM'? Sometimes I feel there is no greater meaning to the phrase than what it spells out however, I have learned to bite my bottom lip nevertheless, perhaps there is room on frawglips' bookshelf for one more book.

But I take your point, we all have to learn somewhere.... and one of my favourite books was written by Nabajyoti Barkakati entitled The Waite Group's Turbo C++ Bible printed by SAMS. I saw one on Amazon recently for as little as 5 quid!! Wow! knowledge doesn't come much cheaper than that!

I hope we don't fall out over this, I just want to earn a few points. Surely you don't begrudge me that do you?

In the meantime I have total respect for you all.

Frawglips, it's me who's apologising now for hijacking your question.... So without further ado, can we please move forward and start cracking some really tough eggs....
0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
>> Sure, one can learns from his own mistakes but only if one understands the nature of the problem and then understands how and why one arrived at a resolve

Agreed. I just like to understand something first before coming up with the solution, rather than doing it the other way around ... but you're right, I shouldn't expect everybody else to think the same way :)


>> Really though, have you heard the phrase 'RTFM'?

Oh yes ... and I've read my share lol (still reading every day). It is often the correct response to a question (not with the same words which imo scare people off more than help them, heh).


>> I hope we don't fall out over this

Certainly not !!! Just getting to know each other, as I'm sure we'll see a lot more of each other in the coming months and hopefully years ;)


>> In the meantime I have total respect for you all.

And you ... As I said earlier : it's always good to have some new insights and ideas. Without that, we would be standing still, and this place (the world) would quickly become boring lol.
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
NotAlone Challenge 20 70
Line meaning 9 74
wordappend challenge 8 82
Unable to start eclipse ? 17 80
Having just graduated from college and entered the workforce, I don’t find myself always using the tools and programs I grew accustomed to over the past four years. However, there is one program I continually find myself reverting back to…R.   So …
Whether you’re a college noob or a soon-to-be pro, these tips are sure to help you in your journey to becoming a programming ninja and stand out from the crowd.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now