Impossible question?

Discussion in 'C Programming' started by shane, Oct 5, 2010.

  1. shane

    shane Guest

    Hi/

    Been given this question, doesn't seem to make sense as it requires
    function overloading:

    Write a utility module that contains the following functions:
    a) int getint(char *prompt)
    Prompts the user then reads in an integer and returns the value
    through the return value of the function (Copy the function from <foo>)
    b) int getint(char *prompt, int max, int min, int *num)
    as for the previous function, except it must check whether the
    integer is in the given range (inclusive).

    Obviously this requires function overloading, which is not supported in
    C (C++ does apparently). And I get this output:

    ************************************
    util.h:12: conflicting types for `getint'
    util.h:11: previous declaration of `getint'
    util.c:16: conflicting types for `getint'
    util.h:12: previous declaration of `getint'
    util.c:25: conflicting types for `getint'
    util.c:16: previous declaration of `getint'
    ************************************

    Am I missing something, or has my lecturer set an impossible question?
    Can there be a VarArgs solution, only thing I can think of?
    shane, Oct 5, 2010
    #1
    1. Advertising

  2. shane

    Ian Collins Guest

    On 10/ 5/10 12:11 PM, shane wrote:
    > Hi/
    >
    > Been given this question, doesn't seem to make sense as it requires
    > function overloading:
    >
    > Write a utility module that contains the following functions:
    > a) int getint(char *prompt)
    > Prompts the user then reads in an integer and returns the value
    > through the return value of the function (Copy the function from<foo>)
    > b) int getint(char *prompt, int max, int min, int *num)
    > as for the previous function, except it must check whether the
    > integer is in the given range (inclusive).
    >
    > Obviously this requires function overloading, which is not supported in
    > C (C++ does apparently). And I get this output:
    >

    <snip>
    >
    > Am I missing something, or has my lecturer set an impossible question?
    > Can there be a VarArgs solution, only thing I can think of?


    Are you being asked to include both in the same executable, or can you
    provide two programmes?

    --
    Ian Collins
    Ian Collins, Oct 5, 2010
    #2
    1. Advertising

  3. shane

    Seebs Guest

    On 2010-10-04, shane <> wrote:
    > Been given this question, doesn't seem to make sense as it requires
    > function overloading:


    Yup. Your lecturer is a twit and doesn't know that C and C++ are
    different languages.

    Although! You can actually do it, sort of:

    > Write a utility module that contains the following functions:

    #ifndef FANCY_GETINT
    > a) int getint(char *prompt)

    #else
    > b) int getint(char *prompt, int max, int min, int *num)

    #endif

    > Am I missing something, or has my lecturer set an impossible question?
    > Can there be a VarArgs solution, only thing I can think of?


    No, because there's nothing about prompt to tell you whether there are
    additional arguments incoming.

    Your lecturer is not aware that his "C" compiler is actually compiling
    C++. Get ready for an exciting ride of trying to figure out what mistaken
    assumptions are hidden in each assignment.

    There is a plus side to this: You will be well prepared for the exciting
    world of specifications written by marketing.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 5, 2010
    #3
  4. shane

    Lew Pitcher Guest

    On October 4, 2010 19:11, in comp.lang.c, wrote:

    > Hi/
    >
    > Been given this question, doesn't seem to make sense as it requires
    > function overloading:


    Not really. It /can/ be done without function overloading, in C, with a
    minor change to the function prototype. Perhaps your instructor wasn't
    providing multiple prototypes for the function (implying function
    overloading), but instead was giving examples of the variety of calls that
    the hypothetical function would accept.

    Think of how printf() can be called as
    a) int printf(char *string);
    or
    b) int printf(char *string, int value);

    Does this imply function overloading for printf() to work?

    > Write a utility module that contains the following functions:
    > a) int getint(char *prompt)
    > Prompts the user then reads in an integer and returns the value
    > through the return value of the function (Copy the function from <foo>)
    > b) int getint(char *prompt, int max, int min, int *num)
    > as for the previous function, except it must check whether the
    > integer is in the given range (inclusive).
    >
    > Obviously this requires function overloading, which is not supported in
    > C (C++ does apparently). And I get this output:

    [snip]
    > Am I missing something, or has my lecturer set an impossible question?
    > Can there be a VarArgs solution, only thing I can think of?


    Assume the function prototype of...

    int getint(char *prompt, ...);

    Then, with suitable cues in the prompt string, the implementation of
    getint() could discern whether or not additional arguments (int max, int
    min, int *num) were to be utilized or not.

    Of course, this would require the use of varargs within the implementation
    of getint(), and the instructor's instructions would have to be interpreted
    as /examples of use/ rather than as function prototypes, but it /could/ be
    done with standard C.

    --
    Lew Pitcher
    Master Codewright & JOAT-in-training | Registered Linux User #112576
    Me: http://pitcher.digitalfreehold.ca/ | Just Linux: http://justlinux.ca/
    ---------- Slackware - Because I know what I'm doing. ------
    Lew Pitcher, Oct 5, 2010
    #4
  5. Lew Pitcher <> writes:
    > On October 4, 2010 19:11, in comp.lang.c, wrote:
    >> Been given this question, doesn't seem to make sense as it requires
    >> function overloading:

    >
    > Not really. It /can/ be done without function overloading, in C, with a
    > minor change to the function prototype. Perhaps your instructor wasn't
    > providing multiple prototypes for the function (implying function
    > overloading), but instead was giving examples of the variety of calls that
    > the hypothetical function would accept.
    >
    > Think of how printf() can be called as
    > a) int printf(char *string);
    > or
    > b) int printf(char *string, int value);
    >
    > Does this imply function overloading for printf() to work?


    No. And strictly speaking, those are declarations, not calls,
    and both of them are incompatible with the actual printf().
    I guess the point is that one call could be consistent with the
    first declaration, and another with the second; both are compatible
    with the actual declaration of printf().

    >> Write a utility module that contains the following functions:
    >> a) int getint(char *prompt)
    >> Prompts the user then reads in an integer and returns the value
    >> through the return value of the function (Copy the function from <foo>)
    >> b) int getint(char *prompt, int max, int min, int *num)
    >> as for the previous function, except it must check whether the
    >> integer is in the given range (inclusive).
    >>
    >> Obviously this requires function overloading, which is not supported in
    >> C (C++ does apparently). And I get this output:

    > [snip]
    >> Am I missing something, or has my lecturer set an impossible question?
    >> Can there be a VarArgs solution, only thing I can think of?

    >
    > Assume the function prototype of...
    >
    > int getint(char *prompt, ...);
    >
    > Then, with suitable cues in the prompt string, the implementation of
    > getint() could discern whether or not additional arguments (int max, int
    > min, int *num) were to be utilized or not.


    But I don't think the problem description permits using the value of
    ``prompt'' to control whether it looks for other arguments.

    The most likely explanation is that the instructor is overlooking the
    difference between C and C++, or was just sloppy with the names.

    > Of course, this would require the use of varargs within the implementation
    > of getint(), and the instructor's instructions would have to be interpreted
    > as /examples of use/ rather than as function prototypes, but it /could/ be
    > done with standard C.


    Given an assignment to write a function "int getint(char *prompt)",
    I don't think it's reasonable to assume that that's anything other
    than the declaration of the function. And if you're free to change
    the declaration, you might as well change the name.

    Incidentally, <varargs.h> is an obsolete header used in pre-ANSI C
    to implement variadic functions. The modern (since 1989) version
    is <stdarg.h>. I know you said "varargs", not "varargs.h", but it
    doesn't hurt to clarify.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Oct 5, 2010
    #5
  6. shane

    shane Guest

    Lew Pitcher writes:
    >> Write a utility module that contains the following functions:
    >> a) int getint(char *prompt)
    >> Prompts the user then reads in an integer and returns the value
    >> through the return value of the function (Copy the function from <foo>)
    >> b) int getint(char *prompt, int max, int min, int *num)
    >> as for the previous function, except it must check whether the
    >> integer is in the given range (inclusive).
    >>
    >> Obviously this requires function overloading, which is not supported in
    >> C (C++ does apparently). And I get this output:

    > [snip]
    >> Am I missing something, or has my lecturer set an impossible question?
    >> Can there be a VarArgs solution, only thing I can think of?

    >
    > Assume the function prototype of...
    >
    > int getint(char *prompt, ...);
    >
    > Then, with suitable cues in the prompt string, the implementation of
    > getint() could discern whether or not additional arguments (int max, int
    > min, int *num) were to be utilized or not.


    Got it, I can put information about the form to use after the NULL
    terminator in the prompt!

    Here is my full solution.

    #include "stdio.h"
    #include "strings.h"
    #include "stdarg.h"

    int getint(char *prompt,...)
    {
    int i=strlen(prompt),j;
    va_list k;
    char s[20];
    printf(prompt);
    gets(s);
    j=atoi(s);
    switch(*(prompt+ ++i)) {
    case 0:
    return j;
    default:
    va_start(k,prompt);
    if(j<=va_arg(k,int) && j>=va_arg(k,int)) return *(va_arg(k,int*))=j;
    printf("out-of-range error aborting");
    abort();
    }
    }

    int main()
    {
    int i;
    char p1[]="enter a number::",p2[]="enter a number in 1 to 10::";
    p1[15]=p1[16]=p2[26]=0;p2[27]=1;
    printf("you entered %d\n",getint(p1));
    getint(p2,10,1,&i);
    printf("you entered %d\n",i);
    }
    shane, Oct 5, 2010
    #6
  7. shane <> writes:
    > Lew Pitcher writes:
    >>> Write a utility module that contains the following functions:
    >>> a) int getint(char *prompt)
    >>> Prompts the user then reads in an integer and returns the value
    >>> through the return value of the function (Copy the function from <foo>)
    >>> b) int getint(char *prompt, int max, int min, int *num)
    >>> as for the previous function, except it must check whether the
    >>> integer is in the given range (inclusive).
    >>>
    >>> Obviously this requires function overloading, which is not supported in
    >>> C (C++ does apparently). And I get this output:

    >> [snip]
    >>> Am I missing something, or has my lecturer set an impossible question?
    >>> Can there be a VarArgs solution, only thing I can think of?

    >>
    >> Assume the function prototype of...
    >>
    >> int getint(char *prompt, ...);
    >>
    >> Then, with suitable cues in the prompt string, the implementation of
    >> getint() could discern whether or not additional arguments (int max, int
    >> min, int *num) were to be utilized or not.

    >
    > Got it, I can put information about the form to use after the NULL
    > terminator in the prompt!


    NULL is a null pointer constant, not a null character. You mean "null
    terminator", or perhaps "NUL terminator", or even "'\0' terminator".

    But it seems vanishingly unlikely that your instructor really had this
    kind of trick in mind.

    > Here is my full solution.
    >
    > #include "stdio.h"
    > #include "strings.h"
    > #include "stdarg.h"


    Use angle brackets, not quotation marks, for standard headers:

    #include <stdio.h>
    #include <strings.h>
    #include <stdarg.h>

    > int getint(char *prompt,...)
    > {
    > int i=strlen(prompt),j;
    > va_list k;
    > char s[20];
    > printf(prompt);
    > gets(s);


    Never use gets(). It cannot be used safely.

    [...]

    > char p1[]="enter a number::",p2[]="enter a number in 1 to 10::";
    > p1[15]=p1[16]=p2[26]=0;p2[27]=1;


    Trying for the IOCCC?

    [...]

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Oct 5, 2010
    #7
  8. shane <> writes:
    <snip>
    > Got it, I can put information about the form to use after the NULL
    > terminator in the prompt!


    That's too horrid an interface to used in practise but I suppose you've
    decided to take the instructions literally. BTW, is it possible there's
    been some miss-interpretation on your part?

    If I had to do it this way, I'd encode the information in the visible
    part of the string -- maybe by requiring that the range be signalled by,
    say, %R in the prompt. The function would then print a prompt where the
    %R was replaced by required range making it simple to inform the user of
    the required input range. Whilst still far from perfect this would at
    least get some benefit from the convoluted interface (and the prompt can
    be a literal string).

    > Here is my full solution.
    >
    > #include "stdio.h"
    > #include "strings.h"
    > #include "stdarg.h"


    Using <>s for standard headers is much safer.

    > int getint(char *prompt,...)
    > {
    > int i=strlen(prompt),j;
    > va_list k;
    > char s[20];
    > printf(prompt);


    What happens if the prompt has a % in it? What happens if it has
    (accidentally or deliberately) %s in it?

    > gets(s);


    Eek! Use fgets and stay safe. Alternatively use scanf("%d", &j) though
    that does not behave in exactly the same way.

    > j=atoi(s);


    The strtol functions is better in that atoi does not handle errors at
    all well. Since one form of this function can report errors, it seems a
    shame not to include input format errors in that.

    > switch(*(prompt+ ++i)) {


    Surely prompt[i + 1] is clearer here? While on the subject, i, j and k
    and not particularly helpful names.

    > case 0:
    > return j;
    > default:
    > va_start(k,prompt);
    > if(j<=va_arg(k,int) && j>=va_arg(k,int)) return *(va_arg(k,int*))=j;
    > printf("out-of-range error aborting");
    > abort();


    Every va_start much have a matching va_end call in the same function.
    Also, isn't abort() rather too drastic an action for an input utility
    function to take when the input is not in the desired range? For one
    thing, the error message may not even appear. Adding a \n at the end
    will help some but is not really enough (you have flush and streams you
    really want flushed when calling abort). Finally, errors are
    traditionally sent to stderr rather that stdout.

    > }
    > }
    >
    > int main()
    > {
    > int i;
    > char p1[]="enter a number::",p2[]="enter a number in 1 to 10::";
    > p1[15]=p1[16]=p2[26]=0;p2[27]=1;
    > printf("you entered %d\n",getint(p1));
    > getint(p2,10,1,&i);
    > printf("you entered %d\n",i);
    > }


    What happened to all the spaces!

    --
    Ben.
    Ben Bacarisse, Oct 5, 2010
    #8
  9. shane

    Lew Pitcher Guest

    On October 5, 2010 13:15, in comp.lang.c, wrote:

    > Lew Pitcher <> writes:
    >> On October 4, 2010 19:11, in comp.lang.c, wrote:
    >>> Been given this question, doesn't seem to make sense as it requires
    >>> function overloading:

    >>
    >> Not really. It /can/ be done without function overloading, in C, with a
    >> minor change to the function prototype. Perhaps your instructor wasn't
    >> providing multiple prototypes for the function (implying function
    >> overloading), but instead was giving examples of the variety of calls
    >> that the hypothetical function would accept.

    [snip]
    > The most likely explanation is that the instructor is overlooking the
    > difference between C and C++, or was just sloppy with the names.


    Could be.

    My post was coloured by my experience as a developer. If someone came to me
    at work and asked for a function that accepted one or five arguments as the
    caller preferred, I would have answered "varargs" :)

    >> Of course, this would require the use of varargs within the
    >> implementation of getint(), and the instructor's instructions would have
    >> to be interpreted as /examples of use/ rather than as function
    >> prototypes, but it /could/ be done with standard C.

    >
    > Given an assignment to write a function "int getint(char *prompt)",
    > I don't think it's reasonable to assume that that's anything other
    > than the declaration of the function. And if you're free to change
    > the declaration, you might as well change the name.


    Again, I approached this as I would have approached a problem at work.
    Perhaps the OP's instructor "misspoke" and wanted a C++ solution, or
    perhaps the OP "misunderstood" the requirements. We won't really know.

    If the OP wanted a C++ overloaded function, then the OP's question shouldn't
    have been asked here in comp.lang.c. And /any/ C solution we lead the OP to
    will be wrong.

    ISTM that we don't have sufficient information to correctly determine the
    instructor's purpose and/or target solution to this problem. In that case,
    IMHO, it is just as correct to suggest that the problem statement is poorly
    presented, and that (with suitable interpretation of the problem
    statement), a C "varargs" solution exists as it is to suggest that the
    problem statement is poorly written, and that (with suitable interpretation
    of the problem statement), a C++ "function overloading" solution exists.

    But, that's just my opinion. :)

    > Incidentally, <varargs.h> is an obsolete header used in pre-ANSI C
    > to implement variadic functions. The modern (since 1989) version
    > is <stdarg.h>. I know you said "varargs", not "varargs.h", but it
    > doesn't hurt to clarify.


    True.

    I was referring to the concept, not the implementation. I should have been
    clearer.


    As for the OP's later posting of a "varargs" C solution, I'll just respond
    with my own attempt. Note that the code is far from robust (the problem
    statement doesn't give enough info to include some features that I'd like,
    and, as a demo program, I've left out features that I'd want in a "live"
    program), but it works.

    ====================== start of program code =============================
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    #include <limits.h>

    #define SENTINAL ':'

    int getint(char *prompt, ...)
    {
    int val, /* input value */
    items, /* scanf() result */
    max = INT_MAX, /* maximum value (defaulted) */
    min = INT_MIN, /* minimum value (defaulted) */
    *num= NULL; /* save result here (defaulted) */

    if (*prompt == SENTINAL) /* getint(char *, int, int, int *) */
    {
    va_list ap;

    /* get additional arguments */
    va_start(ap, prompt);
    max = va_arg(ap, int);
    min = va_arg(ap, int);
    num = va_arg(ap, int *);
    va_end(ap);

    ++prompt; /* skip the sentinal - remainder is true prompt */
    }

    /* now, show the prompt and get the input */
    do
    {
    printf("\n%s :",prompt); fflush(stdout);
    if ((items = scanf("%d",&val)) == 0)
    scanf("%*s"); /* discard bad input */
    } while ((items == 0) || (val < min) || (val > max));

    if (num) *num = val;
    return val;
    }

    int main(void)
    {
    int value, othervalue;

    value = getint("Please input a number");
    printf("\n\ngetint() returned %d\n",value);

    value = getint(":please input a number", 50, 5, &othervalue);
    printf("\n\ngetint() returned %d, got %d\n",value, othervalue);

    return EXIT_SUCCESS;
    }

    ======================= end of program code ==============================

    --
    Lew Pitcher
    Master Codewright & JOAT-in-training | Registered Linux User #112576
    Me: http://pitcher.digitalfreehold.ca/ | Just Linux: http://justlinux.ca/
    ---------- Slackware - Because I know what I'm doing. ------
    Lew Pitcher, Oct 6, 2010
    #9
  10. shane

    James Waldby Guest

    On Tue, 05 Oct 2010 19:27:38 -0400, Lew Pitcher wrote:
    [snipalot]
    ....
    > #define SENTINAL ':'

    ....
    > if (*prompt == SENTINAL) /* getint(char *, int, int, int *) */

    ....
    > ++prompt; /* skip the sentinal - remainder is true prompt */
    > }

    ....

    Perhaps you mean "sentinel"?

    --
    jiw
    James Waldby, Oct 6, 2010
    #10
  11. shane

    Lew Pitcher Guest

    On Oct 5, 11:49 pm, James Waldby <> wrote:
    > On Tue, 05 Oct 2010 19:27:38 -0400, Lew Pitcher wrote:
    >
    > [snipalot]
    > ...> #define SENTINAL        ':'
    > ...
    > >   if (*prompt == SENTINAL) /* getint(char *, int, int, int *) */

    > ...
    > >     ++prompt; /* skip the sentinal - remainder is true prompt */
    > >   }

    >
    > ...
    >
    > Perhaps you mean "sentinel"?


    At least I'm consistent.

    :)
    Lew Pitcher, Oct 6, 2010
    #11
  12. shane

    shane Guest

    Keith Thompson writes:
    > Use angle brackets, not quotation marks, for standard headers:
    >
    > #include <stdio.h>
    > #include <strings.h>
    > #include <stdarg.h>


    OK but if you also have local headers then using "" for both is more
    consistent IMO.

    >> int getint(char *prompt,...)
    >> {
    >> int i=strlen(prompt),j;
    >> va_list k;
    >> char s[20];
    >> printf(prompt);
    >> gets(s);

    >
    > Never use gets(). It cannot be used safely.


    Note than any int can be represented in 20 characters!

    > [...]
    >
    >> char p1[]="enter a number::",p2[]="enter a number in 1 to 10::";
    >> p1[15]=p1[16]=p2[26]=0;p2[27]=1;

    >
    > Trying for the IOCCC?


    Sorry if the code isn't clear. Basically the second : in each string is a
    dummy character. It gets replaced by the 0 character which functions as a
    NULL terminator for that string. Then after that 0 character I insert a
    flag which the getint() function reads to determine whether or not there
    are extra options. Note that p1 and p2 also get a NULL terminator when
    they are first assigned and that is what gets overwritten by this flag.
    If you draw a picture of the arrays with a box for each character you may
    find it easier to see what's going on.

    HTH.
    shane, Oct 6, 2010
    #12
  13. shane

    Lew Pitcher Guest

    On October 6, 2010 14:24, in comp.lang.c, wrote:

    > Keith Thompson writes:
    >> Use angle brackets, not quotation marks, for standard headers:
    >>
    >> #include <stdio.h>
    >> #include <strings.h>
    >> #include <stdarg.h>

    >
    > OK but if you also have local headers then using "" for both is more
    > consistent IMO.
    >
    >>> int getint(char *prompt,...)
    >>> {
    >>> int i=strlen(prompt),j;
    >>> va_list k;
    >>> char s[20];
    >>> printf(prompt);
    >>> gets(s);

    >>
    >> Never use gets(). It cannot be used safely.

    >
    > Note than any int can be represented in 20 characters!


    Yes, but your user might not enter an integer in the way you /expect/ them
    to enter it, or might not even enter an integer at all. Your code would
    fail if
    - the user's cat sat on the keyboard,
    entering "dasdfagetrgidusoiasusefadpopuadfpguodfopgdfugpasf[gu[adfugdf"
    - the user entered "twenty seven thousand two hundred fourty seven"
    - the user entered "000000000000000000000000000001"
    - the user entered "9999999999999999999999999999999"
    and so on.


    >> [...]
    >>
    >>> char p1[]="enter a number::",p2[]="enter a number in 1 to 10::";
    >>> p1[15]=p1[16]=p2[26]=0;p2[27]=1;

    >>
    >> Trying for the IOCCC?

    >
    > Sorry if the code isn't clear.

    [snip]
    > If you draw a picture of the arrays with a box for each character you may
    > find it easier to see what's going on.


    I doubt that Keith needs instruction to "draw a picture". He's likely a lot
    more knowledgable about C and programming than you give him credit for. In
    fact, he probably understood your code on sight, and recognized that it is
    pretty unmaintainable and confusing.

    Keith's hint is that your code is unnecessarily complicated for the task at
    hand, and could be both simpler and clearer.

    HTH
    --
    Lew Pitcher
    Master Codewright & JOAT-in-training | Registered Linux User #112576
    Me: http://pitcher.digitalfreehold.ca/ | Just Linux: http://justlinux.ca/
    ---------- Slackware - Because I know what I'm doing. ------
    Lew Pitcher, Oct 6, 2010
    #13
  14. shane <> writes:
    > Keith Thompson writes:
    >> Use angle brackets, not quotation marks, for standard headers:
    >>
    >> #include <stdio.h>
    >> #include <strings.h>
    >> #include <stdarg.h>

    >
    > OK but if you also have local headers then using "" for both is more
    > consistent IMO.


    No, it really isn't. The language has two different syntaxes for a
    reason.

    #include <stdio.h> performs a system-specified search for the header.
    #include "stdio.h" first searches in an additional set of places *and
    then* falls back to the search done for the <> form. If you happen to
    have a file named "stdio.h" in the wrong place, then the "" form will
    pick up that file rather than the standard one.

    Really, you should always use the <> form for standard headers (and you
    should usually the "" form for your own headers).

    >>> int getint(char *prompt,...)
    >>> {
    >>> int i=strlen(prompt),j;
    >>> va_list k;
    >>> char s[20];
    >>> printf(prompt);
    >>> gets(s);

    >>
    >> Never use gets(). It cannot be used safely.

    >
    > Note than any int can be represented in 20 characters!


    Nothing prevents the user from typing more than 20 characters. If that
    happens, your program's behavior is undefined (if you're very lucky, it
    will crash; if not, you'll just quietly corrupt memory with
    unpredictable results.)

    Never use gets().

    >> [...]
    >>
    >>> char p1[]="enter a number::",p2[]="enter a number in 1 to 10::";
    >>> p1[15]=p1[16]=p2[26]=0;p2[27]=1;

    >>
    >> Trying for the IOCCC?

    >
    > Sorry if the code isn't clear. Basically the second : in each string is a
    > dummy character. It gets replaced by the 0 character which functions as a
    > NULL terminator for that string. Then after that 0 character I insert a
    > flag which the getint() function reads to determine whether or not there
    > are extra options. Note that p1 and p2 also get a NULL terminator when
    > they are first assigned and that is what gets overwritten by this flag.
    > If you draw a picture of the arrays with a box for each character you may
    > find it easier to see what's going on.


    "null terminator", not "NULL terminator". "NULL" is specifically a null
    pointer constant.

    If I have to draw pictures to understand the code, I suggest that the
    code is too complex. The lack of whitespace and the use of magic
    numbers also make it difficult to read. I guess that the values
    15, 16, 26, and 27 come from the lengths of the prompts, which means
    that any changes are going to be extremely error-prone.

    If you want control characters in your strings, you can just put them
    there:

    char p1[] = "enter a number:\0";
    char p2[] = "enter a number in 1 to 10:\0\x01";

    The compiler will append an additional '\0' to each string.

    Note that if your function looks past the '\0' for additional data, it
    could blow up if it's passed (the address of) an ordinary string.

    And this is almost certainly not what the instructor had in mind anyway.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Oct 6, 2010
    #14
  15. shane <> writes:
    > Keith Thompson writes:

    [...]
    >>> int getint(char *prompt,...)
    >>> {
    >>> int i=strlen(prompt),j;
    >>> va_list k;
    >>> char s[20];
    >>> printf(prompt);
    >>> gets(s);

    >>
    >> Never use gets(). It cannot be used safely.

    >
    > Note than any int can be represented in 20 characters!

    [...]

    In addition to my other comments, how do you know that any int can be
    represented in 20 characters? It probably can on your system, int
    can have different ranges on different implementations.

    Do you know how big int has to be for a decimal representation without
    leading zeros to exceed 20 charaters? (Don't forget about the sign for
    negative values.)

    Even if no existing implementation has an int that big, you're
    still making an assumption, one that you should at least document.

    And never use gets(). It's so unsafe, it's being removed from the next
    version of the C standard.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Oct 6, 2010
    #15
  16. shane

    Seebs Guest

    On 2010-10-06, shane <> wrote:
    > Note than any int can be represented in 20 characters!


    Sure, but nothing compels the user to stop typing there...

    >>> char p1[]="enter a number::",p2[]="enter a number in 1 to 10::";
    >>> p1[15]=p1[16]=p2[26]=0;p2[27]=1;

    >>
    >> Trying for the IOCCC?


    > Sorry if the code isn't clear. Basically the second : in each string is a
    > dummy character. It gets replaced by the 0 character which functions as a
    > NULL terminator for that string. Then after that 0 character I insert a
    > flag which the getint() function reads to determine whether or not there
    > are extra options. Note that p1 and p2 also get a NULL terminator when
    > they are first assigned and that is what gets overwritten by this flag.
    > If you draw a picture of the arrays with a box for each character you may
    > find it easier to see what's going on.


    Yeah, but the hard-coded offsets are Unfriendly.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 6, 2010
    #16
  17. shane

    Seebs Guest

    On 2010-10-06, shane <> wrote:
    > OK but if you also have local headers then using "" for both is more
    > consistent IMO.


    No, no it really isn't. They're different things.

    Here's the thing. Consistency is good when you make *similar* things look
    *similar*. When you make *different* things look *similar*, you're violating
    the whole point of what makes consistency useful.

    What's good about consistency is it lets you easily recognize what things
    are without having to think about them. What you should be going for is
    "inclusion of standard headers stays the same everywhere".

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
    Seebs, Oct 6, 2010
    #17
  18. Kenneth Brody <> writes:
    > On 10/6/2010 2:24 PM, shane wrote:
    >> Keith Thompson writes:

    > [...]
    >>>> char s[20];
    >>>> printf(prompt);
    >>>> gets(s);
    >>>
    >>> Never use gets(). It cannot be used safely.

    >>
    >> Note than any int can be represented in 20 characters!

    >
    > Hmm... "-9223372036854775807" takes 21 characters, including the '\0'.
    >
    > But that still assumes you don't have ints larger than 64 bits, and that the
    > user doesn't type in something other than a "valid" integer.
    >
    > [...]


    0000000000000000000000000000001 is a valid integer. And as far as
    atoi() is concerned, so is
    " 1 ".

    For that matter, atoi("non-numeric-string") returns 0, and of course the
    string the user entered can be arbitrarily long.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Oct 7, 2010
    #18
  19. On 6 Oct, 00:27, Lew Pitcher <> wrote:
    > On October 5, 2010 13:15, in comp.lang.c, wrote:
    > > Lew Pitcher <> writes:
    > >> On October 4, 2010 19:11, in comp.lang.c, wrote:



    > >>> Been given this question, doesn't seem to make sense as it requires
    > >>> function overloading:

    >
    > >> Not really. It /can/ be done without function overloading, in C, with a
    > >> minor change to the function prototype. Perhaps your instructor wasn't
    > >> providing multiple prototypes for the function (implying function
    > >> overloading), but instead was giving examples of the variety of calls
    > >> that the hypothetical function would accept.


    not as written. Unless "prompt" had some extra information encoded in
    it to tell you how many arguments to expect.

    > > The most likely explanation is that the instructor is overlooking the
    > > difference between C and C++, or was just sloppy with the names.

    >
    > Could be.


    I think so

    > My post was coloured by my experience as a developer. If someone came to me
    > at work and asked for a function that accepted one or five arguments as the
    > caller preferred, I would have answered "varargs" :)


    *my* experience as a developer would be say "why 1 and 5?". Sounds
    like two different functions to me. Perhaps the short one is
    implemented in terms of the long one

    int default_getint (const char *prompt)
    {
    int n;
    return getint (prompt, DEFAULT_MAX, DEFAULT_MIN, &n);
    }

    I think he's suffering from poor interface design.

    > >> Of course, this would require the use of varargs within the
    > >> implementation of getint(), and the instructor's instructions would have
    > >> to be interpreted as /examples of use/ rather than as function
    > >> prototypes, but it /could/ be done with standard C.

    >
    > > Given an assignment to write a function "int getint(char *prompt)",
    > > I don't think it's reasonable to assume that that's anything other
    > > than the declaration of the function.  And if you're free to change
    > > the declaration, you might as well change the name.

    >
    > Again, I approached this as I would have approached a problem at work.
    > Perhaps the OP's instructor "misspoke" and wanted a C++ solution, or
    > perhaps the OP "misunderstood" the requirements. We won't really know.
    >
    > If the OP wanted a C++ overloaded function, then the OP's question shouldn't
    > have been asked here in comp.lang.c. And /any/ C solution we lead the OP to
    > will be wrong.
    >
    > ISTM that we don't have sufficient information to correctly determine the
    > instructor's purpose and/or target solution to this problem. In that case,
    > IMHO, it is just as correct to suggest that the problem statement is poorly
    > presented, and that (with suitable interpretation of the problem
    > statement), a C "varargs" solution exists as it is to suggest that the
    > problem statement is poorly written, and that (with suitable interpretation
    > of the problem statement), a C++ "function overloading" solution exists.
    >
    > But, that's just my opinion. :)


    <snip>

    what C really needs is lambda...
    Nick Keighley, Oct 8, 2010
    #19
  20. shane

    shane Guest

    Seebs writes:
    >> Sorry if the code isn't clear. Basically the second : in each string is
    >> a dummy character. It gets replaced by the 0 character which functions
    >> as a NULL terminator for that string. Then after that 0 character I
    >> insert a flag which the getint() function reads to determine whether or
    >> not there are extra options. Note that p1 and p2 also get a NULL
    >> terminator when they are first assigned and that is what gets
    >> overwritten by this flag. If you draw a picture of the arrays with a
    >> box for each character you may find it easier to see what's going on.

    >
    > Yeah, but the hard-coded offsets are Unfriendly.


    Your right, I have now implemented some cool macros to improve the
    interface. I also enlarged the gets buffer to address people's concerns
    that 20 wasn't long enough on 64-bit ints. Other invalid input - well
    garbage in garbage out...

    For the other suggestion, I think abort is a good way of exiting, it lets
    users debug what went wrong from the core dump.

    #include "stdio.h"
    #include "string.h"
    #include "stdarg.h"

    #define str_to_prompt_nocheck(s) do{char* t=malloc(strlen(s)+2);strncpy
    (t,s,strlen(s)+2);s=t;}while(0);
    #define str_to_prompt_check(s) do{char* t=malloc(strlen(s)+2);strncpy
    (t,s,strlen(s)+2);(*(++t+strlen(s)))++;s=t;}while(0);

    int getint(char *prompt,...)
    {
    int i=strlen(prompt),j;
    va_list k;
    char s[40];
    printf(prompt);
    gets(s);
    j=atoi(s);
    switch(*(prompt+ ++i)) {
    case 0:
    return j;
    default:
    va_start(k,prompt);
    if(j<=va_arg(k,int) && j>=va_arg(k,int)) return *(va_arg(k,int*))=j;
    printf("out-of-range error aborting");
    abort();
    }
    }

    main()
    {
    int i;
    char p1[]="enter a number:",p2[]="enter a number in 1 to 10:";
    char *s1=p1,*s2=p2;
    str_to_prompt_nocheck(s1);
    str_to_prompt_check(s2);

    printf("you entered %d\n",getint(s1));
    getint(s2,10,1,&i);
    printf("you entered %d\n",i);
    }
    shane, Oct 8, 2010
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rick Spiewak
    Replies:
    1
    Views:
    422
    Rick Spiewak
    Jul 22, 2003
  2. Brian Birtle
    Replies:
    3
    Views:
    2,424
  3. =?Utf-8?B?VVJHRU5ULi5QbGVhc2U=?=

    IMPOSSIBLE QUESTION

    =?Utf-8?B?VVJHRU5ULi5QbGVhc2U=?=, Sep 4, 2004, in forum: ASP .Net
    Replies:
    4
    Views:
    599
    Greg Burns
    Sep 4, 2004
  4. Replies:
    5
    Views:
    258
    Michele Dondi
    Jun 30, 2006
  5. Mel
    Replies:
    3
    Views:
    94
    Ian Skinner
    Jun 22, 2006
Loading...

Share This Page