c-program questiontype: echoing stdin to stdout

Re: c-program questiontype: echoing stdin to stdout

de Richard Lobb -
Número de respuestas: 2
Yep, it would be nice if there was a better solution. Maybe someone will post something back to this thread in the future.
En respuesta a Richard Lobb

Re: c-program questiontype: echoing stdin to stdout

de Michael Fairbank -

Hi Richard, 

I have a potential solution to this now.  A possible template that seems to work reasonably well for a c_program_w_input question type would be this one:

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

/* Improved scanf replacement with echo */
int scanf2(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);

    int assigned = 0;
    int c;

    while (*fmt) {

        /* Handle format specifier */
        if (*fmt == '%') {
            fmt++;

            /* Read first non-space character */
            do {
                c = getchar();
                if (c != EOF) putchar(c);
            } while (isspace(c));

            if (*fmt == 'd') {
                int *ip = va_arg(args, int*);
                int sign = 1;
                int value = 0;

                if (c == '-') {
                    sign = -1;
                    c = getchar();
                    putchar(c);
                }

                while (isdigit(c)) {
                    value = value * 10 + (c - '0');
                    c = getchar();
                    if (c != EOF) putchar(c);
                }

                if (c != EOF)
                    ungetc(c, stdin);

                *ip = sign * value;
                assigned++;
            }

            else if (*fmt == 's') {
                char *sp = va_arg(args, char*);
                int i = 0;

                while (c != EOF && !isspace(c)) {
                    sp[i++] = c;
                    c = getchar();
                    if (c != EOF) putchar(c);
                }

                if (c != EOF)
                    ungetc(c, stdin);

                sp[i] = '\0';
                assigned++;
            }
        }

        /* Handle literal characters in format string */
        else {
            putchar(*fmt);
        }

        fmt++;
    }

    va_end(args);
    return assigned;
}

/* Replace scanf globally */
#define scanf scanf2

/* Student code */
{{ STUDENT_ANSWER }}

Does that seem valid to you?  It seems to meet the goal I want. It defines a new scanf2 function, which approximates the original scanf function, but echos input text to the terminal too.  And then it uses the final #define instruction to replace the built-in scanf by the new scanf2 function.   (Note that the scanf2 implementation is not as flexible and powerful as the built-in scanf function.  For example, it can only handle one instance of %d or %s in the string given.  So you can't do an input for "%d %d" say. But I can't see we'd ever need double input like that in a beginner C course.  And it can't handle "%f" for floating point input.)  P.S. Disclaimer- I built the above scanf2 function using AI.

Thanks.  

Michael


En respuesta a Michael Fairbank

Re: c-program questiontype: echoing stdin to stdout

de Richard Lobb -
Hi Michael

Thanks for posting. That approach looks fine, provided students don't attempt to use unimplemented features. I no longer teach C myself but I'll pass it on to a guy in our department who does.

I vaguely recall another user solving the same problem using OS-level operations - perhaps a pseudo-terminal? - but I don't remember the details. For a simple introductory course with students reading only a single integer or a single string, your approach is probably simpler.

Thanks

Richard