Exercise 7.4 - private version of scanf

Question

Write a private version of scanf analogous to minprintf from the previous section.

/* minscanf: minimalistic scanf function */
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>

void minscanf(char *fmt, ...);

int main(void) {

    int i;
    minscanf("%d", &i);
    printf("minscanf input: %d\n", i);

    char *a = malloc(100); // Allocate 100 bytes, enough for "test char"
    minscanf("%s", a);
    printf("minscanf input: %s\n", a);
    free(a); // free the allocated memory

    float f;
    minscanf("%f", &f);
    printf("minscanf input: %f\n", f);

    int o;
    minscanf("%o", &o);
    printf("minscanf input in octal %o, in decimal %d\n", o, o);

    int x;
    minscanf("%x", &x);
    printf("minscanf input in hex %x, in decimal %d\n", x, x);
    return 0;
}

void minscanf(char *fmt, ...) {
    va_list ap; /* points to each unnamed arg in turn */
    char *p, *sval;
    int *ival;
    float *dval;

    va_start(ap, fmt); /* make ap point to 1st unnamed arg */

    for (p = fmt; *p; p++) {
        if (*p != '%') {
            continue;
        }

        switch (*++p) {
            case 'd':
                ival = va_arg(ap, int *);
                char *d = "44";
                sscanf(d, "%d", ival);
                break;
            case 'f':
                dval = va_arg(ap, float *);
                char *f = "5.33";
                sscanf(f, "%f", dval);
                break;
            case 's':
                sval = va_arg(ap, char *);
                sscanf("test char", "%s", sval);
                break;
            case 'o':
                ival = va_arg(ap, int *);
                char *o = "011";
                sscanf(o, "%o", ival);
                break;
            case 'x':
                ival = va_arg(ap, int *);
                char *x = "1a";
                sscanf(x, "%x", ival);
                break;
            default:
                putchar(*p);
                break;
        }
    }
    va_end(ap); /* clean up when done */
}

Explanation

The Headers

#include <stdarg.h>

This header provides functionality for functions with variable arguments (variadic functions) It defines va_list, va_start, va_arg, and va_end macros which are used to handle variable arguments Essential for implementing functions like scanf/printf that can take varying numbers of arguments

#include <stdio.h>

This is the standard input/output header Provides functions like printf, sscanf, putchar used in the program Necessary for basic input/output operations

This program implements a functionality similar to scanf, by taking a variable number of args and prints them to output.

#include <stdlib.h> for the malloc macro.

The key components are

va_list ap;  // Declares a variable to hold the argument list
va_start(ap, fmt);  // Initializes ap to point to first unnamed argument
va_arg(ap, type);   // Returns next argument of specified type
va_end(ap);         // Cleanup of argument list

Visualize