fgets question

This is a discussion on fgets question within the C Programming forums, part of the General Programming Boards category; I've been working on the code below for a little whlie, and I've almost got it done good, but there ...

fgets question

I've been working on the code below for a little whlie, and I've almost got it done good, but there is still one thing nagging me. As the code stands now, if the user
hits a number > 3 or a letter, it works fine. But if they just hit "enter", they have to hit it twice in order for the corresponding error message to display. It's not a big deal,
but I'd like to know why that is and if there is any way to fix that. My theory is that since you have to hit enter to terminate fgets, if you just hit enter, it reads in \n,
and requires another enter to terminate, that's the only thing I can think of....

Just a note:

You're doing a lot of printing of "\n" to format the screen. You could save a lot of spaces by using ANSI cursor addressing. You can home the cursor with "\x1b[H" (that moves it to the top-left corner of the screen.) You can move the cursor to any position on the screen by using <esc>[<row>;<column>H, where <esc> is the escape character, <row> is the row number represented as a string of ASCII decimal digits, and <column> is the column number, represented (again) as ASCII decimal digits.

I don't have the time to wade through all your screen formatting stuff to offer much assistance at the moment, but I will note that mixing getchar() with fgets() is not a good idea; I'd go as far to say that it's a bad idea to mix them. fgets() takes a file pointer, getchar() always works on stdin. If you want fgets() without the f, use gets(), which gets a string from stdin. Note that gets() does not leave the newline ('\n') in the buffer the way that fgets() does, nor does it limit the number of characters read to fit in the buffer, so it's not as safe.

I hope this helps a little.

Last edited by filker0; 01-09-2006 at 03:48 PM.
Reason: Remove reference to scanf(), as it was due to a misreading of the posting.

I don't have the time to wade through all your screen formatting stuff to offer much assistance at the moment, but I will note that mixing getchar() with fgets() is not a good idea; I'd go as far to say that it's a bad idea to mix them. fgets() takes a file pointer, getchar() always works on stdin. If you want fgets() without the f, use gets(), which gets a string from stdin. Note that gets() does not leave the newline ('\n') in the buffer the way that fgets() does, nor does it limit the number of characters read to fit in the buffer, so it's not as safe.

I hope this helps a little.

Here's a quick little tip for you: If anyone suggests you use gets, it's safe to ignore everything they post.

Also, rather than just say: "Use fgetc instead of getchar, so you can make sure you're working on the same stream." They instead tell you to simply not use getchar, and then go on to suggest the use of gets as a replacement.

You're doing a lot of printing of "\n" to format the screen. You could save a lot of spaces by using ANSI cursor addressing. You can home the cursor with "\x1b[H" (that moves it to the top-left corner of the screen.) You can move the cursor to any position on the screen by using <esc>[<row>;<column>H, where <esc> is the escape character, <row> is the row number represented as a string of ASCII decimal digits, and <column> is the column number, represented (again) as ASCII decimal digits.

Do a Google search on "ANSI Control Sequences VT100" to find a reference listing lots of common ANSI screen control sequences.

BTW, those sequences only work under Windows, and then only if you have ANSI.SYS installed (which I don't).

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell

It depends on your library implementation. MS used to get it wrong, so calls to fgets() mixed with getchar() would not always update file pointers as you might expect, especially when using redirection. I'm sure they fixed it, but it was a rule that was pounded into me back in the late 1980s through the 1990s when dealing with various environments. Restated, if you use the f forms of the functions, don't mix them (on the same channel) with the stdout specific ones.

Here's a quick little tip for you: If anyone suggests you use gets, it's safe to ignore everything they post.

If you read the post, I point out that gets() is unsafe. I never use it myself. Perhaps I could have been a bit clearer.

quzah's advice to ignore everything I write is annoying. He doesn't think I know what I'm talking about, but then again, he seems to think that nobody knows what they're talking about other than him, so I don't feel singled out.

BTW, those sequences only work under Windows, and then only if you have ANSI.SYS installed (which I don't).

It is true that they only work for ANSI displays, most of which are modeled on the VT100 and other DEC display terminals. If you're not dealing with ANSI consoles, the "<esc>[2J" that was in the original posting is also useless, so I assume that Ash1981 was working within an ANSI display environment. If I am wrong, I'm sorry.

If you read the post, I point out that gets() is unsafe. I never use it myself. Perhaps I could have been a bit clearer.

quzah's advice to ignore everything I write is annoying. He doesn't think I know what I'm talking about, but then again, he seems to think that nobody knows what they're talking about other than him, so I don't feel singled out.

Let's examine your post, shall we?

Originally Posted by filker0

I don't have the time to wade through all your screen formatting stuff to offer much assistance at the moment, but I will note that mixing getchar() with fgets() is not a good idea; I'd go as far to say that it's a bad idea to mix them.

Ok, you decide it's a bad idea. Yet, you give no reason for it. First off, getchar is the equivalent to "getc(stdin)". Couple this with their use of fgets ... fgets(ui,2,stdin) ... there is no reason there should ever be a problem on a compiler conforming to the standard. Now you again gave no reason whatsoever. So again, why should they see this as wrong? The fact of the matter is, it's not wrong. It's also not "a bad idea". It's you using a broken implementation. Not them, and definately not the language. It's you and your case, of which you fail to mention anything at all when saying it's "a bad idea".

Originally Posted by filker0

fgets() takes a file pointer, getchar() always works on stdin.

This little gem is completley meaningless to this thread. See, the file pointer they're using is stdin, so it doesn't matter at all. This is a completely pointless statement. It doesn't matter that one function always works on a specific file pointer, because the only file pointer they're using is the one specific one that function just happens to be using.

Originally Posted by filker0

If you want fgets() without the f, use gets(), which gets a string from stdin. Note that gets() does not leave the newline ('\n') in the buffer the way that fgets() does, nor does it limit the number of characters read to fit in the buffer, so it's not as safe.

So here you pretty much tell us that you're only posting to see yourself type. Your whole post is "that's a bad idea, so here's another bad idea you should use instead". You go from one "bad idea", that isn't a bad idea at all, it's simply your broken implementation of the standard, to a "here, this is really stupid, but it's better!" mindset.

Yet somehow, you can't get past the fact that I don't like your idea. No, it's a damn stupid idea. You post no reason at all why they shouldn't do what they're doing, yet tell them that if they are too lazy to remove the newline from their fgets call, that they should instead use gets, even though it's dangerous.

Why? Why suggest it at all? Again, you provide no reason why they shouldn't do what they are doing, but suggest using gets even though you say it's dangerous. You're telling them "Hey, your idea is bad; it's even worse than using gets, though I'm not going to even hint at why. Just take my word for it. Oh, and I can't stand it when that one guy says I'm wrong."

Let's not. You are ignoring the context in which I made my statements. You only want to show me up as incompetant -- I post to help the person (in this case, Ash1981) asking the questions. I don't post to get points in some imagined game.