Please comment on my integer to string code.

Discussion in 'C++' started by manoj1978@gmail.com, Mar 9, 2006.

  1. Guest

    Hi All,
    I wrote the following to print an integer in its string
    representation for base -36 to 36.
    Please comment on this code.

    #include <iostream>
    #include <string>

    using std::abs;
    using std::cout;
    using std::endl;
    using std::reverse;
    using std::string;

    char charTable[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    void printBase(int i, int base)
    {
    if ((abs(base) <= 1) || (abs(base) > 36) || (i == 0))
    {
    cout << "0" << endl;
    return;
    }

    string str = "";
    if ((base > 0) && (i < 0))
    {
    str += "-";
    i = -i;
    }

    do {
    if (i % base >= 0)
    {
    str += charTable[i % base];
    i = i / base;
    } else {
    str += charTable[i % base - base];
    i = i /base + 1;
    }
    } while(i);
    reverse(str.begin(), str.end());
    cout << str << endl;
    }

    int main()
    {
    for(int i = -55; i <= 55; i++)
    {
    cout << i << " = ";
    printBase(i,-10);
    }
    }

    Thanks and Regards,
    manoj.
     
    , Mar 9, 2006
    #1
    1. Advertising

  2. red floyd Guest

    wrote:
    > Hi All,
    > I wrote the following to print an integer in its string
    > representation for base -36 to 36.
    >
    > [code redacted]


    How do you display numbers in a *negative* base?????
     
    red floyd, Mar 9, 2006
    #2
    1. Advertising

  3. Guest

    red floyd wrote:

    > wrote:
    > > Hi All,
    > > I wrote the following to print an integer in its string
    > > representation for base -36 to 36.
    > >
    > > [code redacted]

    >
    > How do you display numbers in a *negative* base?????


    Consider negadecimal.

    27 will be 187

    since 187 = 1 * -10 * -10 + 8 * -10 + 7 = 27.
     
    , Mar 9, 2006
    #3
  4. Phlip Guest

    wrote:

    > int main()
    > {
    > for(int i = -55; i <= 55; i++)
    > {
    > cout << i << " = ";
    > printBase(i,-10);
    > }
    > }


    Unit tests are the most important aspect of programming. Your printBase
    should return a string, so you can test it, and so it won't "couple" with
    its environment. Here you have some cout outside printBase, and some
    inside. Move all outside, then write unit tests like these:

    assert("whatever" == printBase(-55);
    assert("whatever" == printBase(-55);
    assert("whatever" == printBase(-55);
    assert("whatever" == printBase(-55);

    Now each time you change the program, run those tests. If you make certain
    kinds of mistakes (but not any mistake) the test will catch you, and you
    can use Undo to get rid of the mistake. Undo is much more efficient than
    debugging.

    --
    Phlip
    http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
     
    Phlip, Mar 9, 2006
    #4
  5. Guest

    Phlip wrote:

    > Unit tests are the most important aspect of programming. Your printBase
    > should return a string, so you can test it, and so it won't "couple" with
    > its environment. Here you have some cout outside printBase, and some
    > inside. Move all outside, then write unit tests like these:
    >
    > assert("whatever" == printBase(-55);
    > assert("whatever" == printBase(-55);
    > assert("whatever" == printBase(-55);
    > assert("whatever" == printBase(-55);
    >
    > Now each time you change the program, run those tests. If you make certain
    > kinds of mistakes (but not any mistake) the test will catch you, and you
    > can use Undo to get rid of the mistake. Undo is much more efficient than
    > debugging.
    >
    > --
    > Phlip
    > http://www.greencheese.org/ZeekLand <-- NOT a blog!!!

    Hi Philip,
    Thanks.I will surely keep this in mind.
    This time I had the expected results in a file.
    I was redirecting the output and doing file compare.
    Regards,
    manoj.
     
    , Mar 9, 2006
    #5
  6. Phlip wrote:
    > wrote:
    >
    >
    >>int main()
    >>{
    >> for(int i = -55; i <= 55; i++)
    >> {
    >> cout << i << " = ";
    >> printBase(i,-10);
    >> }
    >>}

    >
    >
    > Unit tests are the most important aspect of programming. Your printBase
    > should return a string, so you can test it, and so it won't "couple" with
    > its environment. Here you have some cout outside printBase, and some
    > inside. Move all outside, then write unit tests like these:
    >
    > assert("whatever" == printBase(-55);
    > assert("whatever" == printBase(-55);
    > assert("whatever" == printBase(-55);
    > assert("whatever" == printBase(-55);


    Why four of them in a row? Are there side effects expected that affect
    the behaviour of the function?

    > Now each time you change the program, run those tests. If you make certain
    > kinds of mistakes (but not any mistake) the test will catch you, and you
    > can use Undo to get rid of the mistake. Undo is much more efficient than
    > debugging.


    V
    --
    Please remove capital As from my address when replying by mail
     
    Victor Bazarov, Mar 9, 2006
    #6
  7. Phlip Guest

    Victor Bazarov wrote:

    >>assert("whatever" == printBase(-55);
    >>assert("whatever" == printBase(-55);
    >>assert("whatever" == printBase(-55);
    >>assert("whatever" == printBase(-55);

    >
    > Why four of them in a row?  Are there side effects expected that affect
    > the behaviour of the function?


    I forgot to edit:

    assert("whatever" == printBase(-55));
    assert("whatever" == printBase(-54));
    assert("whatever" == printBase( -1));
    assert("whatever" == printBase( 0));
    ...

    The next, more complex topic is: How to make sure the tests use enough
    inputs to exercise all the branches in the code. Don't go there. ;-)

    --
    Phlip
    http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
     
    Phlip, Mar 9, 2006
    #7
  8. Ben Pope Guest

    Phlip wrote:
    >
    > The next, more complex topic is: How to make sure the tests use enough
    > inputs to exercise all the branches in the code. Don't go there. ;-)


    Classification trees and code coverage tests. Don't know of any free
    software to do that.

    Ben Pope
    --
    I'm not just a number. To many, I'm known as a string...
     
    Ben Pope, Mar 9, 2006
    #8
  9. Pete Becker Guest

    Phlip wrote:

    >
    > The next, more complex topic is: How to make sure the tests use enough
    > inputs to exercise all the branches in the code. Don't go there. ;-)
    >


    Especially since branch testing is known to be inadequate. <g>

    --

    Pete Becker
    Roundhouse Consulting, Ltd.
     
    Pete Becker, Mar 9, 2006
    #9
  10. Phlip Guest

    Pete Becker wrote:

    > Especially since branch testing is known to be inadequate. <g>


    Inadequate for converting an integer to a string???

    <vbgd&rc>

    --
    Phlip
    http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
     
    Phlip, Mar 9, 2006
    #10
  11. Pete Becker Guest

    Phlip wrote:

    > Pete Becker wrote:
    >
    >
    >>Especially since branch testing is known to be inadequate. <g>

    >
    >
    > Inadequate for converting an integer to a string???
    >


    Certainly inadequate as a testing discipline in general, and almost
    certainly inadequate for testing a function that converts an integer to
    a string. Whether it gives you adequate coverage in any particular case
    depends on the case. Applied to the original code it is inadequate.

    For example, branch analysis could be satisfied with test cases that
    only exercise the do loop exactly twice: once to branch back to the head
    of the loop and once to branch out of it. That doesn't test what happens
    when you need exactly one digit or three or more digits to represent the
    value. Of course, doing that one thoroughly requires path testing, which
    is known to be prohibitively expensive <g>, although perhaps workable
    for this example.

    For another example, if the charTable had some incorrect values, a test
    suite based only on branch testing wouldn't necessarily find them.

    --

    Pete Becker
    Roundhouse Consulting, Ltd.
     
    Pete Becker, Mar 9, 2006
    #11
  12. Phlip wrote:
    > Inadequate for converting an integer to a string???


    At least insufficient. For example, branch testing would not detect
    the error which is in the original code when passing
    'std::numeric_limits<int>::min()': the value range for integers is
    [normally] asymmetric and "i = -i" is the identity operation for
    the two values '0' and 'std::numeric_limits<int>::min()' (well, for
    the latter value the behavior may actually be undefined or
    implementation defined). That is, in addition to branch testing you
    need to perform at least some testing for corner cases.
    --
    <mailto:> <http://www.dietmar-kuehl.de/>
    <http://www.eai-systems.com> - Efficient Artificial Intelligence
     
    Dietmar Kuehl, Mar 9, 2006
    #12
  13. Phlip Guest

    Dietmar Kuehl wrote:

    > That is, in addition to branch testing you
    > need to perform at least some testing for corner cases.


    Tiny little voice: Then add, uh, branches inside the code to handle or throw
    the corner cases...

    But thanks guys - I put both yours and Pete's answers on a Wiki page
    BranchTesting. For some strange reason no page by that name was there
    yet. ;-)

    --
    Phlip
    http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
     
    Phlip, Mar 9, 2006
    #13
  14. BobR Guest

    wrote in message
    <>...
    >Hi All,
    > I wrote the following to print an integer in its string
    >representation for base -36 to 36.
    > Please comment on this code.
    >
    >#include <iostream>
    >#include <string>
    >

    // >using std::abs;
    >using std::cout;
    >using std::endl;

    // >using std::reverse;
    >using std::string;


    Style-wise, **IMHO**, (at this point) it stinks!! I'd put the 'using *'
    inside the function/main if I couldn't type "std::".
    My suggestions inline below.

    >

    // >char charTable[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    std::string charTable( "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" );

    >

    // >void printBase(int i, int base){
    std::string CalcBase(int i, int base){
    using std::abs; // etc.

    > if ((abs(base) <= 1) || (abs(base) > 36) || (i == 0)){

    // > cout << "0" << endl;
    // > return;
    return "0";
    > }
    >
    > string str = "";
    > if ((base > 0) && (i < 0)){
    > str += "-"; // prints "-16 = 10-" for base==16
    > i = -i;
    > }
    >
    > do {
    > if (i % base >= 0){

    // > str += charTable[i % base];
    str += charTable.at( i % base );

    > i = i / base;
    > } else {

    // > str += charTable[i % base - base];
    str += charTable.at( i % base - base );

    > i = i /base + 1;
    > }
    > } while(i);

    // > reverse(str.begin(), str.end());
    std::reverse(str.begin(), str.end());

    // prints "-16 = 10-" for base==16

    // > cout << str << endl;
    return str;
    > } // CalcBase(int,int)
    >
    >int main(){


    try{
    for(int i(-55); i <= 55; ++i){
    // > cout << i << " = ";
    // > printBase( i, -10 );
    std::cout << i <<" = "<<CalcBase( i, -10 )<<std::endl;

    > } // for(i)

    } // try
    catch(std::eek:ut_of_range &Oor){
    std::cerr<<"caught "<<Oor.what()<<std::endl;
    return EXIT_FAILURE;
    }
    catch(...){
    std::cerr<<"caught ... something"<<std::endl;
    return EXIT_FAILURE;
    }
    return 0;

    > } // main()end
    >
    >Thanks and Regards,
    >manoj.


    // - output - (base==-10)
    -55 = 65
    -54 = 66
    [snip]
    -11 = 29
    -10 = 10
    -9 = 11
    -8 = 12
    [snip]
    -2 = 18
    -1 = 19
    0 = 0
    1 = 1
    [snip]
    8 = 8
    9 = 9
    10 = 190
    11 = 191
    [snip]
    54 = 154
    55 = 155


    And your C++ problem is?

    --
    Bob R
    POVrookie
     
    BobR, Mar 9, 2006
    #14
  15. Phlip Guest

    BobR wrote:

    > catch(...){
    > std::cerr<<"caught ... something"<<std::endl;
    > return EXIT_FAILURE;
    > }


    I know a certain lead programmer driven to distraction by code that relied
    on catch(...). The advice is let the program halt; use a debugger to fix
    all root causes, and stress-test applications to force out these risks.

    And catch(...) only catches hardware crashes on Win32 as a compiler-specific
    extension. Other platforms just dump core, meaning they cannot use that
    trick to maintain their work loops and keep running.

    --
    Phlip
    http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
     
    Phlip, Mar 9, 2006
    #15
  16. Pete Becker Guest

    BobR wrote:

    >
    > // > str += charTable[i % base];
    > str += charTable.at( i % base );
    >


    The data has already been validated. This check adds nothing. The
    original version, with the char array and direct access, had far less
    overhead and was just as robust.

    --

    Pete Becker
    Roundhouse Consulting, Ltd.
     
    Pete Becker, Mar 9, 2006
    #16
  17. Pete Becker Guest

    Phlip wrote:

    >
    >>catch(...){
    >>std::cerr<<"caught ... something"<<std::endl;
    >>return EXIT_FAILURE;
    >>}

    >
    >
    > I know a certain lead programmer driven to distraction by code that relied
    > on catch(...). The advice is let the program halt; use a debugger to fix
    > all root causes, and stress-test applications to force out these risks.
    >


    But it's okay here, since the code will never throw an exception. The
    checking in calls to at() is redundant.

    --

    Pete Becker
    Roundhouse Consulting, Ltd.
     
    Pete Becker, Mar 9, 2006
    #17
  18. BobR Guest

    Phlip wrote in message ...
    >BobR wrote:


    >> catch(...){
    >> std::cerr<<"caught ... something"<<std::endl;
    >> return EXIT_FAILURE;
    >> }

    >
    >I know a certain lead programmer driven to distraction by code that relied
    >on catch(...). The advice is let the program halt; use a debugger to fix
    >all root causes, and stress-test applications to force out these risks.
    >
    >And catch(...) only catches hardware crashes on Win32 as a compiler-specific
    >extension. Other platforms just dump core, meaning they cannot use that
    >trick to maintain their work loops and keep running.
    >
    >--
    > Phlip


    Good advice.
    But for 'toy' code, it's nice to see *something* output when testing a chunk
    of new code.
    In my experiments with try-catch, I've caught things other than 'hardware'
    (MinGW, win98).

    // ------------------------------------
    class MyError : public std::runtime_error { public:
    MyError(std::string const &msg = "") : std::runtime_error(msg){}
    };
    // ------------------------------------
    void f() throw(MyError){
    throw MyError( "blah-blah" );
    return;
    }
    // ------------------------------------
    // ------------ in main()
    try{ f();}
    // catch(MyError const &x){
    // std::cout<<"MyError test: "<<x.what()<<std::endl;
    // }
    // catch(std::runtime_error const &error){
    // std::cout<<"std::runtime_error "<<error.what()<<std::endl;
    // }
    catch(...){
    std::cout<<"something TERRIBLE happened,"
    " but, I don't know what!!"<<std::endl;
    }
    // ------------
    // - output -
    something TERRIBLE happened, but, I don't know what!!


    Are you saying I can't do that in GNU/Linux, winXP?

    --
    Bob R
    POVrookie
     
    BobR, Mar 9, 2006
    #18
  19. Phlip Guest

    BobR wrote:

    > Are you saying I can't do that in GNU/Linux, winXP?


    Windows has an extra feature that turns general protection faults (you know;
    crashies. Bad things.) into exceptions that you can catch with catch(int).
    So catch(...) will also catch them.

    Other systems may have similar features. Programmers should develop slowly
    and incrementally enough to discover and write code to catch all "real"
    exceptions, and should treat catch(...) like a failing assert() statement.
    Time to dissect the code looking for a programmer error.

    So, either way, never rely on 'catch(...)' within delivered code.

    --
    Phlip
    http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
     
    Phlip, Mar 9, 2006
    #19
  20. red floyd Guest

    Phlip wrote:
    > BobR wrote:
    >
    >> Are you saying I can't do that in GNU/Linux, winXP?

    >
    > Windows has an extra feature that turns general protection faults (you know;
    > crashies. Bad things.) into exceptions that you can catch with catch(int).
    > So catch(...) will also catch them.


    We're way OT here, but it turns them into catch(int)? I could never
    figure out C0000005 errors (Win32 equivalent of SegV) turned into.
    That's the main reason I had catch(...) in my code.
     
    red floyd, Mar 9, 2006
    #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. Analog_Guy
    Replies:
    6
    Views:
    565
    Andy Peters
    Jun 1, 2005
  2. Alec S.
    Replies:
    10
    Views:
    10,194
    Alec S.
    Apr 16, 2005
  3. Replies:
    7
    Views:
    331
  4. Replies:
    102
    Views:
    1,746
    Ben Bacarisse
    Jul 23, 2008
  5. Randy Kramer
    Replies:
    12
    Views:
    377
    Robert Klemme
    Oct 25, 2007
Loading...

Share This Page