This week's book giveaway is in the OO, Patterns, UML and Refactoring forum.
We're giving away four copies of Five Lines of Code and have Christian Clausen on-line!
See this thread for details.
Win a copy of Five Lines of Code this week in the OO, Patterns, UML and Refactoring forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Bear Bibeault
  • Ron McLeod
  • Jeanne Boyarsky
  • Paul Clapham
Sheriffs:
  • Tim Cooke
  • Liutauras Vilda
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • fred rosenberger
  • salvin francis
Bartenders:
  • Piet Souris
  • Frits Walraven
  • Carey Brown

How to quit when string is quit, Quit, or q?

 
Ranch Hand
Posts: 124
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So im having trouble with my do while loop to where its an endless loop. The loop should end when userStr is quit, Quit, or q but it seems that im doing something wrong. Can someone explain to me what the problem could be?

 
Ranch Hand
Posts: 191
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Hanna - from fgets() man page https://linux.die.net/man/3/fgets:

fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer.

 
Marshal
Posts: 69789
277
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Which loop? The outer one?

Don't write for (...; i > 0; ...) ... Since fgets() never returns a zero‑length char *, nor one with a negative length (), you will be testing whether i is not 0. Since C uses numbers or pointers instead of Boolean expressions as Java® does, you would write for (...; i; ...) ... and terminate when i turns into 0.
Similarly:- ...while(strcmp(userStr,"quit") && strcmp(userStr,"Quit") && strcmp(userStr,"q"));
I suggest you put some debugging into that loop, rather like print("Next: \u201c%s\u201d backwards is ", userStr);
The Unicode numbers 201c/d are posh quote marks.
 
John Matthews
Ranch Hand
Posts: 191
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Since fgets() never returns a zero‑length char *


Quite easy to get fgets() to return a zero length string, if you mean no characters followed by the terminating \0 ie. strlen() == 0.

Since C uses numbers or pointers instead of Boolean expressions as Java® does, you would write for (...; i; ...) ...


You could, but I think it's better to not use numbers as Boolean expressions unless there's a good reason to - it's obfuscating the code.

The Unicode numbers 201c/d are posh quote marks.

Now you're just showing off
 
Campbell Ritchie
Marshal
Posts: 69789
277
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

John Matthews wrote:. . . Now you're just showing off

I know at least two other Unicode numbers off by heart.
 
Hanna Roberts
Ranch Hand
Posts: 124
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm not understanding what you mean by that, also the link above didn't work
 
Saloon Keeper
Posts: 22259
151
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:

John Matthews wrote:. . . Now you're just showing off

I know at least two other Unicode numbers off by heart.



I know 10: \u0030-\u0039 And this one: \u0020.

In ancient days where resources were scarce, the way to look for a "quit" in a program was to simply test that the first character of the input was tolower(input[0]) == 'q'. A more discerning match wasn't worth the memory or effort.

Unix, of course, generally simply took an end-of-data (Ctrl-D), and many systems took Ctrl-C, but of course non-technical people wouldn't know to do that.

In less ancient but still olden days, it was common to have a command parsing library that you could use to detect variations on the (possibly abbreviated) word "quit". Some of them are still popular even today.

 
Campbell Ritchie
Marshal
Posts: 69789
277
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's eleven.
Shall we get back to the official point of this thread, and find out whether HR has got her program to read “quit”.
 
Hanna Roberts
Ranch Hand
Posts: 124
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So would adding for example, "q\n" to all of them fix it?
 
John Matthews
Ranch Hand
Posts: 191
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just adding "\n" would be one solution, yes (I assume the additional 'q' in your post was a typo).

Or a slightly neater option (although it actually requires more typing) - instead of adding the newline to the 3 strings you are testing for, you could remove it from the one string that has been input. Something like:
You could also then use len in your for() loop.

Another suggestion - at the moment you are doing an fgets() before the while() loop as well as inside it. There should only be the one, inside the loop - why not just do the fgets() before the for()?
 
Hanna Roberts
Ranch Hand
Posts: 124
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I tried submitting the program with the \n after each of the options and it still said it was incorrect. Do you know why that could be? but so I would just type those lines in before the end of the loop? and yes that's true I could just have it in the loop, I didn't think about that
 
John Matthews
Ranch Hand
Posts: 191
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you post the updated code? (Just about to go to bed now, will look tomorrow.)
 
Hanna Roberts
Ranch Hand
Posts: 124
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Heres how it looks now.


 
John Matthews
Ranch Hand
Posts: 191
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well it works for me - enter something other than one the 3 'quit' strings and they are output in reverse, and it quits if one of the strings is entered. Good work

But I don't know why it's not working for you; please could you try changing your print loop to the following, re-run, and show the output when you enter one of the quit strings?
 
Hanna Roberts
Ranch Hand
Posts: 124
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I did that and it still was an endless loop, the output looks like this but keeps going
Screen-Shot-2020-07-01-at-5.13.01-PM.png
[Thumbnail for Screen-Shot-2020-07-01-at-5.13.01-PM.png]
 
John Matthews
Ranch Hand
Posts: 191
4
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Those messages 'Program generated too much output' etc. are interesting; what environment are you running in? I wonder if that's something to do with it. Is it generating input for you or something weird like that?

The output you've posted shows that the program received inputs of 'Hello there' and 'Hey', with each one terminated by a \n (=10). Did you enter those? There should be some output somewhere corresponding to the 'quit' you (presumably) entered.

The fact that the count in the output keeps going back to 0 implies the code is looping around the outer 'while' loop, not just the print 'for' loop, and it must be calling fgets() each time. Ttrying changing the fgets() call to this:
But the output looks like 'real' input, as if it's just reading a file. Odd.

Sorry - please can you re-post your code again, just so we can double-check it?
 
John Matthews
Ranch Hand
Posts: 191
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In fact you could print out the input as lines rather than individual characters, as that's what appears to be coming in. That is, instead of the for() loop, just do
(You don't need to add a \n here because it's been added by fgets() to the end of the string in userStr.)

Then instead of the output you posted above I would expect to see:
Might give more of a clue as to where it's coming from. Something to read anyway
 
Campbell Ritchie
Marshal
Posts: 69789
277
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

John Matthews wrote:. . . . . .

Beware: tangent. How old is the fgets function? I see it has output parameters (the first parameter) and returns something. I see from man fgets that it is the same as the first parameter, or NULL if reading fails. So it is one of those things you test with the bang operator !. When I go back to the Java® fora, where I spend most of my time, I get suspicious when I see output parameters; at least in Java® you can only apply bang to a boolean.
 
John Matthews
Ranch Hand
Posts: 191
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hey, fgets() is one of the good guys

You usually see it being recommended as the function to use instead of bad-boy gets(). To quote the linux gets() man(ual) entry:

Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.


fegts() takes an argument telling it how big the buffer is where it will store the input, and it won't attempt to store more than will fit in the buffer. gets() has no such argument - given a big enough input it will happily write all over your memory for you.

The ! thing is a separate issue - fgets() returns a pointer pointing to where the input has been stored (which as you say is where you told fgets() to put it), or NULL on error/end of input. It is just the fact that it is a pointer that allows it to be used with !, because NULL is 0, and 0 is false (obviously ).

Interesting (I use the word loosely) note, just in case you hadn''t heard it before - the fact that number 0 is the NULL pointer in a pointer context *doesn't* necessarily mean that your computer's internal representation of NULL is the number 0
http://c-faq.com/null/varieties.html
 
Campbell Ritchie
Marshal
Posts: 69789
277
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, I never knew that NULL might be implemented as different from 0. Thank you
 
Hanna Roberts
Ranch Hand
Posts: 124
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

John Matthews wrote:Those messages 'Program generated too much output' etc. are interesting; what environment are you running in? I wonder if that's something to do with it. Is it generating input for you or something weird like that?

The output you've posted shows that the program received inputs of 'Hello there' and 'Hey', with each one terminated by a \n (=10). Did you enter those? There should be some output somewhere corresponding to the 'quit' you (presumably) entered.

The fact that the count in the output keeps going back to 0 implies the code is looping around the outer 'while' loop, not just the print 'for' loop, and it must be calling fgets() each time. Ttrying changing the fgets() call to this:
But the output looks like 'real' input, as if it's just reading a file. Odd.

Sorry - please can you re-post your code again, just so we can double-check it?




The place im running it on is a homework site called zybooks. Its often very picky with the format. So you want me to try this code in the place of the middle as well?
 
John Matthews
Ranch Hand
Posts: 191
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not sure if I understand the question, but I think so - to clarify, this:
When I compile and run it:
You can see my input being echoed by the printf(), and it exits when I enter 'quit'. So I'm pretty sure it works; if it doesn't in zybooks then there's something we don't understand about the way zybooks is set up to handle input.
 
John Matthews
Ranch Hand
Posts: 191
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
(In case you're unfamiliar with a linux command line environment, the '$' is the linux prompt, and the './a.out' is what I entered to run the compiled program which is in file a.out (default for executables built by the gcc compiler).)
 
Hanna Roberts
Ranch Hand
Posts: 124
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I run it like that and the output seems to match. Also you mentioned the command "$", what is the point of having it at the beginning? I was only taught to type ./a.out
 
John Matthews
Ranch Hand
Posts: 191
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The '$' is the linux console command prompt; I mentioned it in my previous post. I didn't enter it.
 
Hanna Roberts
Ranch Hand
Posts: 124
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
oh ok, I was confused, I thought you said you did enter it lol.
 
You’ll find me in my office. I’ll probably be drinking. And reading this tiny ad.
Thread Boost feature
https://coderanch.com/t/674455/Thread-Boost-feature
    Bookmark Topic Watch Topic
  • New Topic