• scruffy (unregistered) in reply to JimM
    JimM:
    Programmer:
    ... understand a piece of code any college freshman with a programming 101 should be able to grasp...
    While I'm happy to rely on people with a better grasp of C than me that this is not a WTF, it really irks me that so many people think not understanding this code indicates a lack of intelligence.

    To be blunt, if somebody can't understand this piece of code, they shouldn't be pretending to be a C coder. If they ARE pretending to be a C coder then that demonstrates a lack of self awareness, humility, and intelligence.

    JimM:
    Some of us took "programming 101" in the last five year, at colleges / universities that concentrated on modern OO languages (you know, the ones a lot of modern commercial software is written in),

    oooo! OO! OO does not remove the need for algorithmic coding. And that's all that this !WTF was. Which bleeding edge, commercial, OO language could you be proficient in without seeing for loops, mod and div? Sure you might not see the scope rules or pointer arithmetic in that language, but if you don't understand those you shouldn't be working in C.

    JimM:
    and have only a passing familiarity with C - I'm not a bad programmer, but having no knowledge of the language it'd take me a while (and possibly a textbook!) to figure out.

    And would you seriously criticise someone elses code in a language that you didn't understand?

  • Colin (unregistered)

    I think what the author meant to paste was:

    
    // CODING STANDARDS: NO MAGIC NUMBERS
    // http://en.wikipedia.org/wiki/The_Magic_Numbers
    #define THREE 3
    #define ONE   1
    #define NINETEEN 19
    #define ZERO 0
    #define ZERO_AS_CHARACTER '0'
    #define TEN (1 << 3) + (1 << 1)
    #define DECIMILIZER ','
    #define CONTINUE_LOOP superVariable1
    
    // This method determines if the given 'super' number is a 'winning'
    // number or not. If it is then the moduloproxybus needs to shift all
    // colours by 45.
    static char *win(long superVariable1)
    {
        goto start;
        
        loop:
        // This loop ensures that the buffer doesn't become greater than 7.
        do
        {
            *--superVariable5 = ZERO_AS_CHARACTER + (superVariable1 % TEN);
            superVariable1 /= TEN;
            if (--superVariable3 == ZERO)
            {
                superVariable3 = THREE;
                *--superVariable5 = DECIMILIZER;
            }
        }
        while (CONTINUE_LOOP);
        goto end;
        
        start:
        // TODO I don't think this is thread-safe. But its late and I'm tired
        // so I'm going to leave this. I'm quitting on Thursday anyway so it's not
        // my problem any more.
        // Also, Dave if you read this: LOLBUFFALOCHIPS!!!111
        int superVariable2 = ZERO, superVariable3 = THREE;
        int superVariable6 = 98;
        char *superVariable5 = prtbuf;
        int superVariable4 = sizeof(char) * NINETEEN + ONE;
    
        // Simple check to ensure that the variable isn't negative.
        // If it is then we need to consider whether it is prime or not.
        if (superVariable1 < ZERO)
        {
            superVariable2 = ONE;
            superVariable1 = -superVariable1;
        }
        superVariable5 += superVariable4;
        *--superVariable5 = '\0'; // The termination here ensures that the string isn't going to contain hacks from the internet.
    
        goto loop;
        
        switch (superVariable6) {
          case 98:
            prtbuf = "That's numberwang\n";
            break;
          default:
            // Don't do nothing.
            break;
        }
        
        goto loop;
        
        end:
        // Protect against buffer overflows by friggin' the pointer
        if (*superVariable5 == DECIMILIZER) ++superVariable5;
        if (superVariable2) *--superVariable5 = '-';
        return superVariable5;
    }
    
  • Dark (unregistered)

    jspenguin: Your tour the force is impressive, but by calling it _format_num (with leading underscore) you impinge on the reserved namespace. No banana!

  • (cs) in reply to scruffy
    scruffy:
    To be blunt, if somebody can't understand this piece of code, they shouldn't be pretending to be a C coder. If they ARE pretending to be a C coder then that demonstrates a lack of self awareness, humility, and intelligence.
    Couldn't agree more. I'm going to assume this is a general rant rather than aimed at me, since I never claimed to be a C coder.
    scruffy:
    JimM:
    ... at colleges / universities that concentrated on modern OO languages (you know, the ones a lot of modern commercial software is written in) ...
    OO does not remove the need for algorithmic coding. And that's all that this !WTF was. Which bleeding edge, commercial, OO language could you be proficient in without seeing for loops, mod and div?
    None, and I didn't say that either. I said that because I'd learned modern OOP I didn't immediately understand this code. If I was doing this in one of my preferred languages, the first thing I'd do is cast the number to a String, then manipulate that. Without knowledge of the language's structure and limitations, my first response to seeing this code was "What on earth is this meant to do?".
    scruffy:
    JimM:
    I'm not a bad programmer, but having no knowledge of the language it'd take me a while (and possibly a textbook!) to figure out.
    And would you seriously criticise someone elses code in a language that you didn't understand?
    No, I wouldn't. I believe I said that: I'm happy to rely on people with a better grasp of C than me that this is not a WTF see? Nowhere in my comment did I criticise the code in this article. I just dislike people who try to claim that because I don't understand this code instantly I'm dumb. That was my only point, and I think I made it perfectly clearly.

    The fact that you need to make such an aggressive response to it suggests that maybe I touched a nerve? Or are you just another whingy internet snot trying to prove that you're better than everyone else? Or do you actually think I'm dumb because I didn't understand the code instantly (in which case I will have to dislike you, obviously...)?

  • Comma Free Locale (unregistered) in reply to Goplat
    Goplat:
    James:
    sprintf(prtbuf, "%'ld", n);
    That function just writes 'ld for me. Believe it or not, not everyone uses Linux.
    Writing a nice_num() function yourself may make sense if the installed locales all have no thousands separator, and you don't have the authority to install additional locales. In that case, you can try futzing around with locales and format specifiers all you want, the ::sprintf() function will still steadfastly refuse to print any thousands separators. (And no, I don't use Linux either.)
    $ uname -s -r
    SunOS 5.10
    $ locale -a
    C
    POSIX
    iso_8859_1
    $ cat nice_num.c++
    #include <iostream>
    #include <stdio.h>      // for the ::sprintf() function
    #include <locale.h>     // for the ::setlocale() function
    
    int main(int argc, char** argv)
    {
            int num = 1048576;
            for(size_t i = 0;  i < 3;  ++i)
            {
                    static const char* locale = NULL;
                    switch(i)
                    {
                            case 0:         locale = "C";           break;
                            case 1:         locale = "iso_8859_1";  break;
                            case 2:         locale = "";            break;
                    }
                    std::cout << "For locale \"" << locale << '"' << std::endl;
                    if(!::setlocale(LC_NUMERIC, locale))
                            std::cerr << "warning:  could not set LC_NUMERIC to \"" << locale << '"' << std::endl;
                    const size_t bufsiz = 1024;
                    static char buf[bufsiz];
                    ::sprintf(buf, "%'d", num);
                    std::cout << "\twith %'d:\t" << buf << std::endl;
                    ::sprintf(buf, "%d", num);
                    std::cout << "\twith %d:\t" << buf << std::endl;
            }
            return(0);
    }
    $ c++ -o nice_num nice_num.c++
    $ ./nice_num
    For locale "C"
            with %'d:       1048576
            with %d:        1048576
    For locale "iso_8859_1"
    warning:  could not set LC_NUMERIC to "iso_8859_1"
            with %'d:       1048576
            with %d:        1048576
    For locale ""
            with %'d:       1048576
            with %d:        1048576
    $ 
  • Anonymous (unregistered)

    Cool thing about jspenguin's implementation is that now it takes longer to read for a C programmer but a non-C programmer may read the code... which is useful because?

  • Addison (unregistered) in reply to scruffy
    JimM:
    Some of us took "programming 101" in the last five year, at colleges / universities that concentrated on modern OO languages (you know, the ones a lot of modern commercial software is written in),

    Speak for yourself. I graduated just a few short months ago and I had no trouble reading this code. There is literally nothing in that code that I didn't learn in college. Including pointers.

  • (cs) in reply to Anonymous I18N Pseudo-Expert
    Anonymous I18N Pseudo-Expert:
    given that nobody (afaik) properly supports japanese number formatting (group every four digits), let alone the seriously wacky indian formatting (grouped by twos, except for the lowest order digits, which are a group of three) this is a fine start on an i18n number formatter--just make d an argument to support japan, and add another argument separating first and loop initializations of d to support india.

    http://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.numbergroupsizes.aspx

    BTW, Japanese uses the same format as English.

  • (cs) in reply to Addison
    Addison:
    JimM:
    Some of us took "programming 101" in the last five year, at colleges / universities that concentrated on modern OO languages (you know, the ones a lot of modern commercial software is written in),
    Speak for yourself. I graduated just a few short months ago and I had no trouble reading this code. There is literally nothing in that code that I didn't learn in college. Including pointers.
    I did speak for myself. Me and anyone else who was on my course, and anyone else who attended a similar course that only taught a modern high-level language (for my sins, mine was Java!). Nowhere did I say that no-one who did CS recently would understand this code. If I'd taken different modules in my Masters I might have learned C and therefore understood this perfectly.

    Why has this comment elicited so many aggressively defensive replies? What did I say that was so offensive?!?

  • illtiz (unregistered) in reply to neophrene
    neophrene:
    There is nothing wrong with this function. A good programmer understand it in far less than a minute. Of course it would be better to have a comment on top of it, but that's all. If your are not a good programmer (or if you are just a Java XML drone) you might of course want to fill it with storytelling comments.

    A good programmer also understand why it has been written like that.

    Indeed a good programmer already have written lots of functions like that.

    Please come back to us when you have enough programming experience, in various fields.

    Don't you mean "real programmer?" (http://www.pbm.com/~lindahl/real.programmers.html)

  • (cs) in reply to Anonymous
    Anonymous:
    Cool thing about jspenguin's implementation is that now it takes longer to read for a C programmer but a non-C programmer may read the code... which is useful because?
    The code could be part of a legacy system, and all the C programmers could have left the organisation (in disgust, perhaps?) when they migrated the majority of their apps to .NET / Java / PickaLang. Something's gone funky with the legacy app, and now a PickaLang developer has been assigned to try to work out what's going wrong, because as far as management are concerned it's all just code, and that's what programmers write, yeah?

    I've been asked more than once to stick my head in applications written in languages I have absolutely no knowledge of, and the occasional relief of a pertinent comment is like nectar, believe me ;^) (Ok, jspenguin's may be a little verbose on the comments, but in this situation I'd always prefer too many comments rather than too few!)

  • AllUrBase (unregistered)

    03 NICE-NUM PICTURE --,---,---,--9,ZZ.

  • illtiz (unregistered) in reply to Nazca

    Yes, I did bother to read your monster comment.

    Nazca:
    JPhi:
    You use sprintf to get the number into a string, and then you simply add a comma every 3 spaces in some kind of loop... It takes all the "math" out of the equation and turns the problem into a simple string manipulation.

    Yeah... sprintf to one buffer and loop the array assigning to a second buffer which is returned. So you have all the overhead of sprintf and then do a manip loop anyway, with the added bonus of having to pull the data from a buffer instead of compute it.

    Talk about cutting your nose off to spite your face lol.

    Hmm. From what I gather, that wasn't implied at all. You can sprintf the current value % 1000 just the way the single digits are written into the buffer in the original snippet. The readability would improve somewhat. I fail to see other possible advantages. I agree that the high speed (which was probably intended with this code) would suffer.

  • scruffy (unregistered) in reply to JimM
    JimM:
    Couldn't agree more. I'm going to assume this is a general rant rather than aimed at me, since I never claimed to be a C coder.

    Exactly, more to the point any such person who then passes themself off as such a good C programmer that they can deride other people's work deserves all the lambasting they get.

    JimM:
    None, and I didn't say that either. I said that because I'd learned modern OOP I didn't immediately understand this code. If I was doing this in one of my preferred languages, the first thing I'd do is cast the number to a String, then manipulate that.
    I.E. you'd use a type conversion. Type conversion isn't a necessary or sufficient feature of an OO language, pretty much any scripting language or shell will do that!
    JimM:
    scruffy:
    And would you seriously criticise someone elses code in a language that you didn't understand?
    No, I wouldn't. I believe I said that: I'm happy to rely on people with a better grasp of C than me that this is not a WTF see? Nowhere in my comment did I criticise the code in this article. I just dislike people who try to claim that because I don't understand this code instantly I'm dumb.
    Again it's a general rant, there are a lot of people who do criticise code in languages that they don't understand, and to be honest it looked like you were defending them!

    I don't understand PERL very well, if I have to maintain some then it'll take me a couple of hours to work out what's going on, but that's work against my own lack of knowledge, not work trying to overcome an obtuse predecessor.

    JimM:
    The fact that you need to make such an aggressive response to it suggests that maybe I touched a nerve?

    Actually it was necessitated by the implication that C is archaic, and that everyone here was some sort of biggot for expecting everyone to get what for loops do.

    JimM:
    Or are you just another whingy internet snot trying to prove that you're better than everyone else?

    Let me get this straight, you're posting to a site called "The Daily WTF", a forum set up specifically for people to giggle and sneer at stupid code written by stupid people, and you have a problem with "internet snot"s ?;-)

  • mattc (unregistered)

    Interesting to see so many people arguing over this method, I think it would be a nice feature on dailywtf to challenge people to re-write functions to see who can write the most optimal ;)

  • (cs) in reply to Dark
    Dark:
    jspenguin: Your tour the force is impressive, but by calling it _format_num (with leading underscore) you impinge on the reserved namespace. No banana!
    Incorrect. Reserved names are those that start with and underscore that is followed with another underscore or an uppercase letter. As a regex: /^_[_A-Z]/. So an underscore followed by a lower case letter is safe.
  • scruffy (unregistered) in reply to mattc
    mattc:
    Interesting to see so many people arguing over this method, I think it would be a nice feature on dailywtf to challenge people to re-write functions to see who can write the most optimal ;)

    That could be fun, it'd be nice to see who can think up the biggest WTF code too;-)

  • Son Of Thor (unregistered) in reply to scruffy

    This is standard C Stuff and it is almost beautiful bar the Global variable.

    I write in both C and C++ for a living (yes they are very different but in a subtle way) I usually choose straight C for small utility functions like this ( write it as a macro if possible) because if you write straight C code correctly it is the most portable code on the planet (it is basically warmed over pdp 11 asembley).

    Java people hate my java code because when I am sentenced to write java code I write it in C. As I say you can write C in any language you just have to find a way around not having pointers which is the only natural datatype there is that being on an unsigned integer value of the size that the operating system/CPU considers being a single work unit.

    I could go on about why I like to do my FOR loops backwards but you would just think I a strange or something like that.

  • (cs) in reply to scruffy
    scruffy:
    I.E. you'd use a type conversion. Type conversion isn't a necessary or sufficient feature of an OO language, pretty much any scripting language or shell will do that!
    Perhaps I've misunderstood what all the C programmers have said, but I'd gathered from other comments that C wouldn't let you type-cast then step through the string (or at least, that the available methods to do so are obnoxiously slow)? Hence the cunning use of the fact that if you add num % 10 to '0' you'll get the ascii point code from 0 - 9? And having to stack those directly into consecutive memory? Or have I got the wrong end of the stick?
    scruffy:
    ... there are a lot of people who do criticise code in languages that they don't understand, and to be honest it looked like you were defending them! ...

    ... Actually it was necessitated by the implication that C is archaic, and that everyone here was some sort of biggot for expecting everyone to get what for loops do. ...

    No, none of that was my intended meaning. Certainly not defending anyone else, certainly not calling C archaic (I did imply it was OLD, but I think that's fair given that it's older than me!), and I didn't mention any kind of loop in my comment (so I don't know where you've got that bit from...).

    I was simply frustrated at all the comments of the type "Anyone who can't understand this code in seconds is obviously dumb and pathetic". I'll give you that anyone criticising the code without understanding it is a fscktard, but criticising other people just because they don't understand a particular programming language is just as bad. I consider myself a decent coder so to be told that I'm dumb because I don't know C really riles me.

    Oh, and FYI I don't have a problem with internet snots in general, just whingy ones who think they're better than everyone else ;^)

  • Addison (unregistered) in reply to JimM
    JimM:
    I did speak for myself. Me and anyone else who was on my course, and anyone else who attended a similar course that only taught a modern high-level language (for my sins, mine was Java!). Nowhere did I say that no-one who did CS recently would understand this code. If I'd taken different modules in my Masters I might have learned C and therefore understood this perfectly.

    Why has this comment elicited so many aggressively defensive replies? What did I say that was so offensive?!?

    Mostly because it opens up a HUGE can of worms over the great divide between old school programming and new school. You said "I went to school recently (insert snide comment about the uselessness of C) so therefore I don't know how to read this code." Most people take offense to that because we know better then to assume someone CAN'T read code. Anyone who programs for a living and doesn't wind up on this site can read that code. It's just some people (like those that have learned OO languages exclusively) aren't willing to put 5 minutes of critical thinking to use. Not saying this is what you meant or even what you said, that's just how (imo) everyone took it.

  • (cs) in reply to Addison
    Addison:
    Mostly because it opens up a HUGE can of worms over the great divide between old school programming and new school. You said "I went to school recently (insert snide comment about the uselessness of C) so therefore I don't know how to read this code."
    Lets compare that to my original comment, shall we:
    JimM:
    Some of us took "programming 101" in the last five year, at colleges / universities that concentrated on modern OO languages (you know, the ones a lot of modern commercial software is written in), and have only a passing familiarity with C
    No, I see no snide comments about C - just that I didn't learn it.
    Addison:
    Most people take offense to that because we know better then to assume someone CAN'T read code. Anyone who programs for a living and doesn't wind up on this site can read that code. It's just some people (like those that have learned OO languages exclusively) aren't willing to put 5 minutes of critical thinking to use. Not saying this is what you meant or even what you said, that's just how (imo) everyone took it.
    So you think assuming someone can read code gives carte blanche to then insult them if they don't completely understand that code straight away? As I said, it'd take me a while and some reference material to figure out what the code did on my own. I didn't say I wouldn't be willing to do that.

    I was simply replying to Programmer (and, by association, a number of other people generally who said things like "anyone who doesn't understand what this code does is an idiot") when s/he said "any college freshman with a programming 101 should be able to grasp <this code>". The point is, I finished my Master's just over 2 years ago. I can read this code no problem, in the sense of following the flow of it. But, having no knowledge of C, I couldn't understand the code. So it's simply not true that anyone with a Programming 101 can understand it. Read it yes, follow the flow yes, but understand it? Not unless the course taught C.

    As it is, everyone has now lost sight of the fact that I was making a specific reply to a specific part of a comment, and I predict a long, drawn-out flame war before I get sick of it, amke myself another cup of coffee, and go back to doing some real work. Life? Don't talk to me about life...

  • (cs) in reply to Son Of Thor
    Son Of Thor:
    Java people hate my java code because when I am sentenced to write java code I write it in C.
    I can understand their point of view - after all, the whole concept of coding standards is to make sure everyone can read everyone's code ;^)

    On the other hand, I can also sympathise completely: when I went back to uni it took a term for the software workshop people to get me writing Java with standard namings, as I was coming from a Perl and self-taught Javascript background where all my naming conventions has _ in: so a method that in Java convention would be called getHorizontalPosition I would name get_horiz_pos. They actually started marking my assignments down after the second week because I wouldn't conform ;^(

  • scruffy (unregistered) in reply to JimM
    JimM:
    scruffy:
    I.E. you'd use a type conversion. Type conversion isn't a necessary or sufficient feature of an OO language, pretty much any scripting language or shell will do that!
    Perhaps I've misunderstood what all the C programmers have said, but I'd gathered from other comments that C wouldn't let you type-cast then step through the string (or at least, that the available methods to do so are obnoxiously slow)? Hence the cunning use of the fact that if you add num % 10 to '0' you'll get the ascii point code from 0 - 9? And having to stack those directly into consecutive memory? Or have I got the wrong end of the stick?

    Ah, I see where you're coming from now. C doesn't have a "String" data-type per-se. Instead we use arrays of 8bit numbers. (Each eight bit number storing a single ASCII encoded letter) C can widen and narrow data on recasts, but it won't perform algorithmic functions to do that. (C++ however does.) There are some common library functions for converting between raw binary (such as the algebraic functions use) and human-readable strings... but if you use them you have to include an entire library, which is a pain if you're working on an embedded task, or on an OS kernel.

    C describes very closely what the CPU actually does, which is why it's still popular in a lot of tasks that need direct access (like device drivers) low overheads (like OSs) and high performance (like multimedia codecs, game engines, etc).

    I do have to admit that a lot of C programmers have massive superiority complexes, and that's probably due to being acutely aware of what the CPU's doing, and most of them can't imagine leaving a language to do this kind of thing for them.

    With respect if you start off learning on a language which can inject a load of functionality on a "simple" operation, then this does wrong-foot you when you come to learn C, and then the old school C guys start circling like vultures (or like while(1);)

    JimM:
    Oh, and FYI I don't have a problem with internet snots in general, just whingy ones who think they're better than everyone else ;^)

    Ah you'll be okay here then, nobody thinks that they're better than everyone else, they all know that they're better than each other;->

  • (cs) in reply to JimM
    JimM:
    scruffy:
    I.E. you'd use a type conversion. Type conversion isn't a necessary or sufficient feature of an OO language, pretty much any scripting language or shell will do that!
    Perhaps I've misunderstood what all the C programmers have said, but I'd gathered from other comments that C wouldn't let you type-cast then step through the string (or at least, that the available methods to do so are obnoxiously slow)?
    I wouldn't call it a type-cast but a conversion. Of course C lets you do that (sprintf()), but why would you do something that complicated when there's a dead simple algorithm to do it in one go, and faster, too? That being said, the code has a few definite bad parts and a few potentially bad parts. The function should've been called format_number or similar, nice_num can be confused with a function concerning process priorities. It shouldn't use a global buffer but take the buffer as an argument. Hardcoding the thousands separator as ',', ignoring -MIN_LONG == MIN_LONG, possible buffer overflow if long is 64 bits and lack of thread safety are potentially bad, but may be justified here. Still, if setlocale(LC_NUMERIC,something with separators); sprintf("%'d",num); was an option, that would be preferable. And yes, all the "*--buf =" probably won't be obvious to someone not familiar with C, so it's okay if it takes them a couple of minutes to figure the code.
    Hence the cunning use of the fact that if you add num % 10 to '0' you'll get the ascii point code from 0 - 9? And having to stack those directly into consecutive memory?
    Cunning? I thought that was standard practice in every language where char is a numeric type (and the digits are consecutive in order, because of its simplicity I always am annoyed that the charcter after '9' isn't 'A' or 'a' in ASCII). You stack them directly into consecutive memory because it's simple to accomplish and what you finally want.
    I was simply frustrated at all the comments of the type "Anyone who can't understand this code in seconds is obviously dumb and pathetic".
    Understandable. Though I read them meaning "Any C programmer ..." which I could agree with.
  • Rambaldi (unregistered) in reply to scruffy
    scruffy:
    With respect if you start off learning on a language which can inject a load of functionality on a "simple" operation, then this does wrong-foot you when you come to learn C, and then the old school C guys start circling like vultures (or like while(1);)

    gah, for(;;); depending on system you are implementing it for and compiler optimization it removes the test for 1 being a true value.

  • (cs) in reply to JimM
    JimM:
    I just dislike people who try to claim that because I don't understand this code instantly I'm dumb.

    You don't have to understand it instantantly. But if you can't look at it for a few minutes and at least have an idea what it is trying to do, well, I won't say you are dumb, but maybe programming isn't the best career choice for you.

  • Scott (unregistered)

    A few minor WTFs, already covered. 1. Static buffer--result is overwritten on next call, not threadsafe. 2. If a standard library is available, you can use sprintf() with your own buffer. 3. No comments; at least "// Converts int to string representation with comma separators" would make a 30 second job of reading the code into a 15 second job. Otherwise, this a fair way to do it.

  • Bega (unregistered) in reply to JimM

    [quote user="JimM"][quote user="Addison"]Mostly because it opens up a HUGE can of worms over the great divide between old school programming and new school. You said "I went to school recently (insert snide comment about the uselessness of C) so therefore I don't know how to read this code." [/quote]Lets compare that to my original comment, shall we:[quote user="JimM"]Some of us took "programming 101" in the last five year, at colleges / universities that concentrated on modern OO languages (you know, the ones a lot of modern commercial software is written in), and have only a passing familiarity with C[/quote]No, I see no snide comments about C - just that I didn't learn it.[/quote] <snip> [/quote]

    You don't think people might have taken offence at the bold comment above?

    It reads quite arrogant (to me, and I suspect many others) and sounds very "What would you c people know, use a real language"..... I'm not interested in getting into an OO vs Other debate, but I noticed you were surprised your comments had caused such a ruckus...I would imagine it's comments like the above one that may have attracted all that attention (but hey, I could be wrong....)

  • m (unregistered) in reply to ML

    Nice try, but:

    Jäg har 96 386-CPUar.

    (Excuse me Swedish, I'm backporting from Danish here)

  • WOW I dont wanna see your code (unregistered) in reply to Goofy Modulus Math
    Goofy Modulus Math:
    Anyone (like me) whose primary environment is weakly-typed languages where converting numbers to strings is a simple matter of sticking '""+' in front, might take a while to understand what was going on.

    I'm just going to quote you, so hopefully others will see it too.

  • son of thor (unregistered) in reply to JimM
    JimM:
    I can understand their point of view - after all, the whole concept of coding standards is to make sure everyone can read everyone's code ;^)

    It is worse than that.

    I dont write Java that often and if I am going to do some string manipulation I am not going to know about the system.out.strings.stringbuffer object so would just roll my own.

    and I will start worrying about if something was allocated on the stack or in the heap and ague that it is the callers job to allocate the object not the called subroutine.

    And then a holy war breaks out it would properly be best to let someone with passion for java write the code.

    And dont get me started on what is in the language specification vs the class libirary.

  • Herby (unregistered)

    Not a bad function. Yes, it has a few "flaws" but nothing serious. The even more subtle WTF is that the routine won't work (at least in a 2's complement system) at the most negative number. That is because it has no positive equivalent. A word to the wise to those who want to use the program.

  • nazlfrag (unregistered)

    /* differences: goes forwards, directly modifies buffer at dest */

    nice_num_fwds(char* dest,long num) {

    long i; long j; long denom; long charcount;

    /* find number of digits in final string */

    i=num; /* i will be used as our number to convert / if(i<0) i=-i; / incorrect for maximum negative / charcount=0; / # of final digits / denom=1; / denom will equal 10 to the power of charcount-1 */

    while(i) { denom*=10; i/=10; charcount++; } denom/=10; /* adjust to charcount-1 */

    /* convert the number */

    i=num; if(i<0) i=-i; /* again incorrect for maximum negative */

    /* and the rest explains itself :) */

    if (num<0) *dest++='-';

    while(charcount) { j=i/denom; *dest++='0'+j; charcount--; if(charcount%3==0) dest++=','; i-=(jdenom); denom/=10; } *dest='/0'; return; }

    Untested and dodgy (ie. zero fails) but just did it as a concept of how much more complex the logic gets going forwards. As it turns out, it's not as painful as I thought, but still clearly less efficient. Oh, and the article is not a WTF, but you already knew that.

  • (cs) in reply to scruffy
    scruffy:
    JimM:
    Oh, and FYI I don't have a problem with internet snots in general, just whingy ones who think they're better than everyone else ;^)
    Ah you'll be okay here then, nobody thinks that they're better than everyone else, they all know that they're better than each other;->
    Oh, absolutely; I am clearly far superior to you - except my knowledge of C, that is ;^)

    Thanks for the info: always nice to broaden my horizons into new languages. Not that my current work has much call for C (fricking web apps - I hate that I have a designers eye... everyone wants web apps! GAH!) but I'm sure it'll come in later (when I refuse to build any more web apps!)...

  • Woteva (unregistered)

    Why would you want to divide by 1,000 when you're converting to a string digit by digit?

  • Tom (unregistered) in reply to JPhi

    I assumed the WTF was the potential for overspill. Otherwise, pretty much everything I've ever seen written in C or C-like C++ is a WTF. Although And C isn't any more about getting stuff done than anything else. C is about getting close to the actual computer behaviour. In many ways, that's counter to accomplishing a goal.

  • (cs) in reply to Bob

    FIST!

  • Clank75 (unregistered) in reply to jspenguin

    Yow. I have to agree with the gallery - absolutely no WTF here. Perfectly good code.

    jspenguin's heart is in the right place, but commenting to that level actually hurts readability, it doesn't help it. The original is compact, simple to understand to anyone with a passing familiarity with the language, and critically the entire function fits on the screen and is visible without scrolling.

    Adding masses of comments so you can't scan/take in the function in its entirity is not an aid to understanding.

    About the only changes I'd make would be - A slightly more descriptive name. Use #defines for the separator character and buffer length A single comment at the beginning along the lines of:

    /**************************
     * nice_num
     * 
     * Formats a long to a string representation, with separator characters between thousands.
     * e.g. n = 123456789 is formatted to 123,456,789
     *
     * SIDE EFFECTS: Dirties the /prtbuf/ global buffer.
     * RETURNS: A pointer into /prtbuf/.  Caller must copy/use before calling any other function which dirties /prtbuf/.
     */
  • John Muller (unregistered) in reply to Gieron
    Gieron:
    Paolo G:
    bitpirate:
    The real WTF is assuming that all locales use "," for their thousands separator. "1.000.000" is common for a million in Europe.
    Yes, dot is the standard in continental Europe (which uses a comma instead of a decimal point), but the comma is used in the UK.
    In Sweden we use spaces: 1 000 000

    If that's true, I have code to fix.

  • Slicerwizard (unregistered)

    I may have missed it, but I don't think anyone has yet posted an elegant method of handling MIN_LONG. This is my 30 year old signed integer to string code (designed for 16 bit processors):

    // converts a 32 bit integer to its string representation
    
    void ltoa(INT_32 number, STRING target)
    {
       INT_32 n;
       STRING ep;
       BYTE buf[12];
    
       if (number < 0L)
          *(target++) = '-';
       else
          number = -number;
    
       *(ep = buf + 10) = EOS;
    
       do
          {
          n = number / 10;
          *--ep = (INT_16) (n * 10 - number) + '0';
          number = n;
          }
       while (number);
    
       strcpy(target, ep);
    }
    

    I wrote a custom version of sprintf to handle separator character requirements; doing it in a modified ltoa function just gets ugly.

  • illtiz (unregistered) in reply to Slicerwizard
    Slicerwizard:
    I may have missed it, but I don't think anyone has yet posted an elegant method of handling MIN_LONG. This is my 30 year old signed integer to string code (designed for 16 bit processors):
    // converts a 32 bit integer to its string representation
    
    <snip code>
    
    

    I wrote a custom version of sprintf to handle separator character requirements; doing it in a modified ltoa function just gets ugly.

    Is it me or is this actually a bit harder to comprehend than the original snippet? What really made me spin for a bit was that you don't use modulo math (which isn't goofy). But I like how you elegantly solved the ~0 issue.

  • Rambaldi (unregistered) in reply to illtiz
    illtiz:
    Slicerwizard:
    I may have missed it, but I don't think anyone has yet posted an elegant method of handling MIN_LONG. This is my 30 year old signed integer to string code (designed for 16 bit processors):
    // converts a 32 bit integer to its string representation
    
    <snip code>
    
    

    I wrote a custom version of sprintf to handle separator character requirements; doing it in a modified ltoa function just gets ugly.

    Is it me or is this actually a bit harder to comprehend than the original snippet? What really made me spin for a bit was that you don't use modulo math (which isn't goofy). But I like how you elegantly solved the ~0 issue.

    looking at it, i think it would have been slightly faster if done with a modulo operator but then not all architectures have that instruction.

  • Goran (unregistered) in reply to JimM
    Perhaps I've misunderstood what all the C programmers have said, but I'd gathered from other comments that C wouldn't let you type-cast then step through the string (or at least, that the available methods to do so are obnoxiously slow)? Hence the cunning use of the fact that if you add num % 10 to '0' you'll get the ascii point code from 0 - 9? And having to stack those directly into consecutive memory? Or have I got the wrong end of the stick?
    What on EARTH is it with the posters here? How do you imagine built-in funcs, operators etc in any language "typecast" a binary number to a string? They do the **cunning** remainder 10 and add to '0' 'trick'. It's the plain obvious simple mathematical way to do it. If a builtin, for some reason, isn't convenient, write it out yourself. But for heaven's sake don't go 'typecasting to string' and think something magic has happened and imagine you are avoiding doing the mathematics necessary to convert binary to decimal. And no, this isn't telling you you are dumb for not knowing a given language, this is the really basic mathematics that any programmer should know.
  • Slicerwizard (unregistered) in reply to Rambaldi
    illtiz:
    Is it me or is this actually a bit harder to comprehend than the original snippet? What really made me spin for a bit was that you don't use modulo math (which isn't goofy). But I like how you elegantly solved the ~0 issue.
    Unusual solutions generally need more comments, and this code is no exception. However, they were never added way back then and since it's only a three line loop, I decided to let y'all work it out.
    Rambaldi:
    looking at it, i think it would have been slightly faster if done with a modulo operator but then not all architectures have that instruction.
    Modulo is just remainder after division. The original code has two divides per digit:

    *--buffer = '0' + (n % 10); n /= 10;

    Mine has one:

    n = number / 10; *--ep = (INT_16) (n * 10 - number) + '0';

    Divides on older hardware were very slow (~150 clock cycles on 808x) while multiplication was a bit faster, so one divide was used.

  • airdrummer (unregistered) in reply to Robajob

    ...using apostrophes for plural's;-)

  • (cs) in reply to Slicerwizard
    Slicerwizard:
    Rambaldi:
    looking at it, i think it would have been slightly faster if done with a modulo operator but then not all architectures have that instruction.
    Modulo is just remainder after division. The original code has two divides per digit:

    *--buffer = '0' + (n % 10); n /= 10;

    Mine has one:

    n = number / 10; *--ep = (INT_16) (n * 10 - number) + '0';

    Divides on older hardware were very slow (~150 clock cycles on 808x) while multiplication was a bit faster, so one divide was used.

    I think what Rambaldi meant was that using n%10 and n/= 10, a good compiler figures out that only one division is needed, because it gives you the quotient in one register and the remainder in another (if the hardware has that instruction, which I believe most modern do). I tried it, and on my box indeed it is faster to use division and modulo than one division and one multiplication, though only marginally so (~ 0.9%), with optimisation turned on. With optimisation tuned off, one division + one multiplication is significanty faster (~ 20%).
  • Slicerwizard (unregistered)

    Gotcha. All our old compilers did for us was throw in redundant x86 register reloads all over the generated code. :(

  • foo (unregistered)

    The code is pretty obvious actually. An it doesn't divide by 1000 because a 3-digit decimal number wouldn't be directly convertible to single digit's ASCII code... But yes, the name is silly and an explanatory comment would have been in order.

  • argh (unregistered)

    I agree with everyone: nice_num() was a very poor choice of name for this function. Something like xtoa() would be much more readable.

  • romkyns (unregistered)

    I looked through it briefly. It made sense. I looked through it carefully, looking for WTFs. I couldn't find any. I thought "WTF is this code doing on this site?!?!"

    And then it dawned upon me. See that WTF thought in there? That's it! Good job! :)

Leave a comment on “nice_num, mean_programmer”

Log In or post as a guest

Replying to comment #232248:

« Return to Article