Quoth hahahahacker2009 <[email protected]>:
> I'm writing a program that use uvlong on 9legacy raspberry pi.
> uvlong n;
> scanf("%lld", &n);
> print("%lld", n);
> But after compiling the program and input a small number (8), it print 0. I 
> modified it and compile with pcc, but it print a very big number then.
> unsigned long works. What's the problem with uvlong?

the problem is with scanf; it doesn't handle that case:

        static int icvt_n(FILE *f, va_list *args, int store, int width, int 
type){
                if(store){
                        --ncvt; /* this assignment doesn't count! */
                        switch(type){
                        case 'h': *va_arg(*args, short *)=nread; break;
                        case 'n': *va_arg(*args, int *)=nread; break;
                        case 'l':
                        case 'L': *va_arg(*args, long *)=nread; break;
                        }
                }
                return 1;
        }

A patch to fix this would be welcome, but Plan 9 code doesn't
tend to use scanf; Unix code is also best off avoiding scanf,
it's an API that feels convienient but has a number of pitfalls.
Specifically, if there's a format mismatch, the remainder of the
input remains buffered, and you need fiddly error handling code
to consume it.

Here's probably how I'd write it:

        char *e;
        uvlong n;

        ln = Brdstr(bfd, '\n', 1);
        n = strtoull(ln, &e, 0);
        if(*e != '\0')
                print("trailing junk\n");
        printf("%llud\n", n);
        free(ln);

it's a little more code, but it keeps working as the code gets
more functional.

If I want to handle more complex input, I'd tend to reach for
tokenize(2) -- which loosely the format a lot of programs use.
For example:

        char *e, *sp[4];
        uvlong n1, n2;
        int n;

        ln = Brdstr(bfd, '\n', 1);
        n = tokenize(ln, sp, nelem(sp));
        switch(n){
        case 1:
                if(strcmp(sp[0], "greet") != 0)
                        sysfatal("unknown command");
                print("hello world\n");
                break;
        case 3:
                if(strcmp(sp[0], "sum") != 0)
                        sysfatal("unknown command");
                n1 = strtoull(sp[1], &e, 0);
                if(*e != 0)
                        sysfatal("invalid number\n");
                n2 = strtoull(sp[2], &e, 0);
                if(*e != 0)
                        sysfatal("invalid number\n");
                print("2*arg: %lld\n", n1+n2);
                break;
        default:
                sysfatal("invalid line");
                break;
        }
        free(ln);

(Subtle point: I have n+1 entries in sp[] to detect that
too many fields were passed).


------------------------------------------
9fans: 9fans
Permalink: 
https://9fans.topicbox.com/groups/9fans/T3df06e15ad1bc104-Mae15e97615432098d31bdbbd
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription

Reply via email to