Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #102755

Re: Recursion: getting input from the user

From David Brown <david.brown@hesbynett.no>
Newsgroups comp.lang.c
Subject Re: Recursion: getting input from the user
Date 2017-01-30 14:35 +0100
Organization A noiseless patient Spider
Message-ID <o6nfc9$3u0$1@dont-email.me> (permalink)
References <a1baac5a-a7a9-41e6-baaf-5190d075c3ab@googlegroups.com> <87efzkpx2f.fsf@bsb.me.uk> <7d912eeb-0bd5-41ea-84fb-eb9364a9c847@googlegroups.com>

Show all headers | View raw


On 30/01/17 13:46, Alla _ wrote:
> On Monday, January 30, 2017 at 3:11:11 PM UTC+3, Ben Bacarisse wrote:
>> Alla _ <modelling.data@gmail.com> writes:
>>
>>> I am trying to write a function that gets an input from the user.
>>> If the user has not provided a correct input, then the function
>>> should start all over again, prompting the user for another input.
>>> I wonder why it doesn't perform the recursion. If I enter only new
>>> line and then press ctrl D to indicate EOF, I get back the printf
>>> message for the second time and the program stops.
>>
>> Here's what's happening...
>>
>> The "top" call reads lines (rather short ones!) until EOF (or an error,
>> but let's forget about those).  You typed \nCtrl-D so fgets is called
>> twice.  The first time it puts \n\0 in the buffer, the second time it
>> puts nothing there (leaving \n\0 there).  buf[0] != '\n' is false so the
>> top call recurses and returns industry_rate().
>>
>> This second call sets up a new buffer full of nulls and tries to read a
>> line.  That fails (the input is at EOF) but this time buf[0] != '\n' is
>> true (buf[0] is 0) so strtod is called.  No number is seen and
>> not_converted will be left pointing at the first null in the buffer.
>> Thus the test *not_converted == '\n' || *not_converted == '\t' ||
>> *not_converted == '\0' is also true and rate will be returned.
>>
>> When I run this code I get a different effect because my Linux system
>> breaks C's rules for interactive input: once EOF has been seen, further
>> input is possible, but you really should no rely on that possibility
>> (and it seems your system does not do that).
>>
>> It's a little odd to read all the input and then look to see if the last
>> line had a number on it (which seems to be the plan).  It's usually
>> better to read until you get some acceptable data or you find that the
>> stream as ended.
>>
>>> When I enter a number, it correctly stores the number.
>>
>> Only in some situations.  If you type \n\n100\n\nCtrl-D you won't get
>> 100 returned.  I'm not saying that's a problem, but you should give some
>> thought to what you will accept as input and you won't.
>>
>>> Here is how the function is called:
>>> av.industry_rate = industry_rate();
>>>
>>> The function:
>>> double industry_rate()
>>> {
>>>     printf("Please, enter the projected industry growth rate beyond 5 year horizon; maximum 3 numbers after the decimal point\n");
>>>     char buf[7] = {0};
>>
>> That's a little small.  If someone inputs a few spaces before the number
>> it could get truncated.
>>
>>>     while(fgets(buf, sizeof(buf), stdin) != NULL);
>>>     
>>>     if(buf[0] != '\n')
>>>     {
>>>         char *not_converted = NULL;
>>>         double rate = strtod(buf, &not_converted);
>>>         
>>>         if(*not_converted == '\n' || *not_converted == '\t'
>>>            || *not_converted == '\0')
>>>         return rate;
>>
>> Odd indentation!
>>
>>>     }
>>>     return industry_rate();
> I see. Thank you very much.
> Solved by rewriting like this:
> double industry_rate()
> {
>     printf("Please, enter the projected industry growth rate beyond 5 year horizon in decimal notation; max 3 numbers after decimal point\n");
>     char buf[7] = {0};
>     char c;
>     int i = 0;
>     
>     while( (c = getchar()) != EOF && (c != '\n' && c != '\t'))
>         buf[i++] = c;
>     if (c == '\n')
>         buf[i] = '\0';
>     
>     if(buf[0])
>     {
>         char *not_converted = NULL;
>         double rate = strtod(buf, &not_converted);
>         
>         if(*not_converted == '\n' || *not_converted == '\t'
>                                                 || *not_converted == '\0')
>         return rate;
>     }
>     return industry_rate();
> }
> What indentation will be a correct one? Is the one above
> better?
> 

There is no "correct" indentation - there are merely many ways to have
/bad/ indentation!

You had the "if" and the "return" at the same level:

    if(*not_converted == '\n' || *not_converted == '\t'
        || *not_converted == '\0')
    return rate;

This is definitely /bad/ - not merely "odd".

If you have a line continuation, it is common to use more than one
tab-stop (or space equivalent) for the indentation, to make it clear
that the second line is a continuation, not statement controlled by the
conditional  - as you did in your second version.  But the "return"
statement /must/ be indented:

    if(*not_converted == '\n' || *not_converted == '\t'
                              || *not_converted == '\0')
        return rate;

However, I would strongly recommend you look up the "one true brace
style", and make a lot more use of braces.  It makes it much harder to
get indentation wrong or confusing, especially when changing code, or
for anyone to make a mistake when reading the code.

    if (*not_converted == '\n' || *not_converted == '\t'
                              || *not_converted == '\0') {
        return rate;
    }


/You/ decide your indentation style for your own code, but if you are
making mistakes with your current style, it is a good indication that
you should consider changing.


Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Recursion: getting input from the user Alla _ <modelling.data@gmail.com> - 2017-01-30 02:06 -0800
  Re: Recursion: getting input from the user Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-30 12:11 +0000
    Re: Recursion: getting input from the user Alla _ <modelling.data@gmail.com> - 2017-01-30 04:46 -0800
      Re: Recursion: getting input from the user David Brown <david.brown@hesbynett.no> - 2017-01-30 14:35 +0100
        Re: Recursion: getting input from the user Alla _ <modelling.data@gmail.com> - 2017-01-30 05:55 -0800
      Re: Recursion: getting input from the user Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-30 17:16 +0000
  Re: Recursion: getting input from the user Barry Schwarz <schwarzb@dqel.com> - 2017-01-30 10:07 -0800
    Re: Recursion: getting input from the user Alla _ <modelling.data@gmail.com> - 2017-01-30 11:13 -0800
    Re: Recursion: getting input from the user "James R. Kuyper" <jameskuyper@verizon.net> - 2017-01-30 15:07 -0500
    Re: Recursion: getting input from the user Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-30 20:16 +0000
    Re: Recursion: getting input from the user Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-02 01:47 -0800
    Re: Recursion: getting input from the user supercat@casperkitty.com - 2017-02-02 12:38 -0800

csiph-web