473,406 Members | 2,371 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

Please comment on my integer to string code.

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 '06 #1
58 3358
ma*******@gmail.com 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?????
Mar 9 '06 #2

red floyd wrote:
ma*******@gmail.com 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 '06 #3
ma*******@gmail.com 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!!!
Mar 9 '06 #4

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 '06 #5
Phlip wrote:
ma*******@gmail.com 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
Mar 9 '06 #6
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!!!
Mar 9 '06 #7
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...
Mar 9 '06 #8
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.
Mar 9 '06 #9
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!!!
Mar 9 '06 #10
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.
Mar 9 '06 #11
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:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Mar 9 '06 #12
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!!!
Mar 9 '06 #13

ma*******@gmail.com wrote in message
<11**********************@p10g2000cwp.googlegroups .com>...
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::out_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
Mar 9 '06 #14
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!!!
Mar 9 '06 #15
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.
Mar 9 '06 #16
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.
Mar 9 '06 #17

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
Mar 9 '06 #18
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!!!
Mar 9 '06 #19
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.
Mar 9 '06 #20

Phlip,
Thanks for the info. I appreciate you taking the time.

I have a lot of fun with try-catch in my 'experiments'. Of course I would
never do such things in 'real' code. <G> (reserved for critical errors that
are hard to handle otherwise).

I'll have to do some more testing next time I'm over on a GNU(Debian)
partition in this box.

You ever pop in some screwy stuff like that to rattle your 'lead'? <G>

--
Bob R
POVrookie
Mar 10 '06 #21
red floyd wrote:
We're way OT here, but it turns them into catch(int)?
The purpose of topicality is to grow a healthy community whose members know
they can stretch the bounds now and then.
I could never figure out C0000005 errors (Win32 equivalent of SegV) turned
into. That's the main reason I had catch(...) in my code.


Google this verbiage:

"try-except-statement :
__try compound-statement
__except ( expression ) compound-statement

"The try-except statement is a Microsoft extension to the C and C++
languages that enables 32-bit target applications to gain control when
events that normally terminate program execution occur. Such events are
called exceptions, and the mechanism that deals with exceptions is called
structured exception handling."

Except it ain't catch, it's __except. That's why it's OT - because nobody
will crack down on me if I get the natty details wrong.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Mar 10 '06 #22

BobR wrote:
ma*******@gmail.com wrote in message
<11**********************@p10g2000cwp.googlegroups .com>... Style-wise, **IMHO**, (at this point) it stinks!! I'd put the 'using *'
inside the function/main if I couldn't type "std::". thanks.will keep in mind. 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 Thanks. i = -i; Will this really cause issue if i is smallest negetive int? }

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

Will this be ok?
if (str[0] == '-')
std::reverse(str.begin()+1,str.end());
// > 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::out_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?

I modified a C code for this.I havent used C++ much.Want to be sure
that,there is no stupid mistakes.
--
Bob R
POVrookie

Thanks Bob,
Regards,
manoj.

Mar 10 '06 #23
ma*******@gmail.com wrote:
ma*******@gmail.com wrote in message
i = -i;
Will this really cause issue if i is smallest negetive int?


Whatever you mean by "smallest negetive"...
[..]


If 'i' is INT_MIN (and on some systems it's -32768), then change
its sign and the result may not be representable in an int. What
happens after that is implementation-defined, most likely the 'i'
gets truncated, and you get 0. So, -INT_MIN is 0? That doesn't
seem right...

V
--
Please remove capital As from my address when replying by mail
Mar 10 '06 #24

Victor Bazarov wrote:
Whatever you mean by "smallest negetive"...
[..]


If 'i' is INT_MIN (and on some systems it's -32768), then change
its sign and the result may not be representable in an int. What
happens after that is implementation-defined, most likely the 'i'
gets truncated, and you get 0. So, -INT_MIN is 0? That doesn't
seem right..

Thanks for the info.
Regards,
manoj..

Mar 10 '06 #25
manoj1978 wrote:
Style-wise, **IMHO**, (at this point) it stinks!! I'd put the 'using *'
inside the function/main if I couldn't type "std::".
thanks.will keep in mind.
The ulterior principle here is "give everything the narrowest feasible
scope". For example, prefer this:

loop thing
{
int x ...
}

over this:

int x;
loop thing
{
....
}
// x not used here

If it's not used outside the loop, put it inside the loop block.
> i = -i; Will this really cause issue if i is smallest negetive int?


Write a test case (one of the assert() lines I pitched that puts in such an
input that you reach this line with the smallest int.
// > str += charTable[i % base];
str += charTable.at( i % base );
Note that someone bounced this suggestion. charTable is potentially
constant, so it has no need to be a full-fledged string object.

Write it like this:

char const charTable[] = "0123...Z";
// prints "-16 = 10-" for base==16

Will this be ok?
if (str[0] == '-')
std::reverse(str.begin()+1,str.end());


I don't know, but I trimmed out the excess stuff from the post, and put
blank lines around your question, to make it easier for others to spot and
answer.

You might also write a test case that forces that situation.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Mar 10 '06 #26

Phlip wrote:
manoj1978 wrote:
Style-wise, **IMHO**, (at this point) it stinks!! I'd put the 'using *'
inside the function/main if I couldn't type "std::".
thanks.will keep in mind.
The ulterior principle here is "give everything the narrowest feasible
scope". For example, prefer this:

loop thing
{
int x ...
}

over this:

int x;
loop thing
{
...
}
// x not used here

If it's not used outside the loop, put it inside the loop block.
i = -i;

Will this really cause issue if i is smallest negetive int?


Write a test case (one of the assert() lines I pitched that puts in such an
input that you reach this line with the smallest int.


On my system,it remains as it is.I modified the code to treat that
input as invalid.
// > str += charTable[i % base];
str += charTable.at( i % base );
Note that someone bounced this suggestion. charTable is potentially
constant, so it has no need to be a full-fledged string object.

Write it like this:

char const charTable[] = "0123...Z"; Ok. // prints "-16 = 10-" for base==16

Will this be ok?
if (str[0] == '-')
std::reverse(str.begin()+1,str.end());


I don't know, but I trimmed out the excess stuff from the post, and put
blank lines around your question, to make it easier for others to spot and
answer.

You might also write a test case that forces that situation.

I tried with that and it is working fine.want to be sure that it is
okay to use that in C++ or does it have any hidden problems.

Regards,
manoj.

Mar 10 '06 #27

Phlip wrote:
> i = -i;

Will this really cause issue if i is smallest negetive int?


Write a test case (one of the assert() lines I pitched that puts in such an
input that you reach this line with the smallest int.


Using C's INT_MIN is okay for C++ or does it have its own way of
representing smallest int?

Regards,
manoj.

Mar 10 '06 #28
manoj1978 wrote:
Using C's INT_MIN is okay for C++ or does it have its own way of
representing smallest int?
A language lawyer will know the exact difference between INT_MIN and the
"trait" that Dietmar suggested. In general, you may use the mostly harmless
C library things in C++, because C++'s ISO Standard includes the C Library
entirely, by reference, hence a compiler must agree on C's and C++'s size of
ints.
I tried with that and it is working fine.want to be sure that it is
okay to use that in C++ or does it have any hidden problems.


You are answering around my point.

Please write a batch of test cases, like this:

assert("16" == printBase(36+6));
assert("A6" == printBase(10*36+6));
assert("FOO" == printBase(15*36*36 + 25*36 + 36));
...

Run them all each time you make the tiniest change to your program. Put
another way, only make such tiny changes that all the tests pass after each
one. If they fail, use Undo to back out your changes.

That is what your professors should teach on the first day of school; it's
what your textbooks should cover right after "hello world". All programs
need many test cases for every feature. The alternative is always endless
debugging.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Mar 10 '06 #29

Phlip wrote:
manoj1978 wrote:
I tried with that and it is working fine.want to be sure that it is
okay to use that in C++ or does it have any hidden problems.
You are answering around my point.

Please write a batch of test cases, like this:

assert("16" == printBase(36+6));
assert("A6" == printBase(10*36+6));
assert("FOO" == printBase(15*36*36 + 25*36 + 36));
...

Run them all each time you make the tiniest change to your program. Put
another way, only make such tiny changes that all the tests pass after each
one. If they fail, use Undo to back out your changes.


I have to run it for all integers to make sure that in this code,it
will never cause problems.
But a person who know C++ well can immediately tell, if I reverse part
of a string like this,then it will cause issues or will work always.I
really want opinion on the language features I used more than the
algorithm,input or output.
That is what your professors should teach on the first day of school; it's
what your textbooks should cover right after "hello world". All programs
need many test cases for every feature. The alternative is always endless
debugging.


Regards,
manoj.

Mar 10 '06 #30
In article <1141970724.433887.106160
@i40g2000cwc.googlegroups.com>, ma*******@gmail.com
says...

[ ... ]
Using C's INT_MIN is okay for C++ or does it have its own way of
representing smallest int?


The C version continues to work fine, but you can also
use std::numeric_limits<int>::min(). This can be
particularly useful inside of a template where you don't
necessarily know what type you're dealing with ahead of
time.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Mar 10 '06 #31
Jerry Coffin wrote:
The C version continues to work fine, but you can also
use std::numeric_limits<int>::min(). This can be
particularly useful inside of a template where you don't
necessarily know what type you're dealing with ahead of
time.

MSVC 6 and gcc 2.95.3 complains on this.Devcpp (having gcc version
3.4.2 mingw) works fine with this.Is this a new feature?

Mar 10 '06 #32

ma*******@gmail.com wrote in message ...
Please write a batch of test cases, like this:

assert("16" == printBase(36+6));
assert("A6" == printBase(10*36+6));
assert("FOO" == printBase(15*36*36 + 25*36 + 36));
...
Run them all each time you make the tiniest change to your program. Put
another way, only make such tiny changes that all the tests pass after each one. If they fail, use Undo to back out your changes.


I have to run it for all integers to make sure that in this code,it
will never cause problems.
But a person who know C++ well can immediately tell, if I reverse part
of a string like this,then it will cause issues or will work always.I
really want opinion on the language features I used more than the
algorithm,input or output.
Regards,
manoj.

#include <iostream> // C++
#include <ostream> // std::endl
#include <string>
// ------------------------------------
class Manoj{
public: // ------------------------------ public
Manoj():
charTable("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
{} // Ctor
// ------------------------------------
void execute( int base, std::ostream &cout=std::cout){
cout<<"\n___[ base = "<<base<<" ]___"<<std::endl;
// ------------
for(int i(-55); i <= 55; ++i){
cout << i <<" = "<<CalcBase( i, base )<<std::endl;
} // for(i)
// ------------
cout<<"___[ Done ]___\n"<<std::endl;
} //execute(int,std::ostream&)
// ------------------------------------
private: // ------------------------------ private
std::string charTable;
// ------------------------------------
std::string CalcBase( int i, int base ){
using std::abs;
if((abs(base) <= 1) || (abs(base) > 36) || (i == 0)){
return "0";
}
std::string str("");
std::string negate("");
if((base > 0) && (i < 0)){
negate = "-";
i = -i;
}
do{
if(i % base >= 0){
str += charTable.at( i % base );
i = i / base;
}
else{
str += charTable.at( i % base - base );
i = i /base + 1;
}
} while(i);
std::reverse(str.begin(), str.end());
str = negate + str;
// Will this be ok? Try it
// if (str[0] == '-')
// std::reverse(str.begin()+1,str.end());
return str;
} //CalcBase(int,int)
// ------------------------------------
}; //class Manoj
// ------------------------------------

#include <fstream> // std::endl

int main(){
Manoj Man;
Man.execute( 10, std::cout);
Man.execute( 16 );

ofstream File("MyTest.txt");
if( !File ){
std::cerr<<"ofstream File FAILURE!!"<<std::endl;
return EXIT_FAILURE;
}
for(int i( -36 ); i <= 36; ++i){
Man.execute( i, File );
} // for(i)
return 0;
} // main()end
// ------------------------------------

--
Bob R
POVrookie
Mar 10 '06 #33

BobR wrote:

#include <iostream> // C++
#include <ostream> // std::endl
#include <string>
// ------------------------------------
class Manoj{
public: // ------------------------------ public
Manoj():
charTable("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
{} // Ctor
// ------------------------------------
void execute( int base, std::ostream &cout=std::cout){
cout<<"\n___[ base = "<<base<<" ]___"<<std::endl;
// ------------
for(int i(-55); i <= 55; ++i){
cout << i <<" = "<<CalcBase( i, base )<<std::endl;
} // for(i)
// ------------
cout<<"___[ Done ]___\n"<<std::endl;
} //execute(int,std::ostream&)
// ------------------------------------
private: // ------------------------------ private
std::string charTable;
// ------------------------------------
std::string CalcBase( int i, int base ){
using std::abs;
if((abs(base) <= 1) || (abs(base) > 36) || (i == 0)){
return "0";
}
std::string str("");
std::string negate("");
if((base > 0) && (i < 0)){
negate = "-";
i = -i;
}
do{
if(i % base >= 0){
str += charTable.at( i % base );
i = i / base;
}
else{
str += charTable.at( i % base - base );
i = i /base + 1;
}
} while(i);
std::reverse(str.begin(), str.end());
str = negate + str;
// Will this be ok? Try it
// if (str[0] == '-')
// std::reverse(str.begin()+1,str.end());
return str;
} //CalcBase(int,int)
// ------------------------------------
}; //class Manoj
// ------------------------------------

#include <fstream> // std::endl

int main(){
Manoj Man;
Man.execute( 10, std::cout);
Man.execute( 16 );

ofstream File("MyTest.txt");
if( !File ){
std::cerr<<"ofstream File FAILURE!!"<<std::endl;
return EXIT_FAILURE;
}
for(int i( -36 ); i <= 36; ++i){
Man.execute( i, File );
} // for(i)
return 0;
} // main()end
// ------------------------------------

--
Bob R
POVrookie


Hi Bob,
Thank you very much for the code.
I changed ofstream File("MyTest.txt"); to std::ofstream
File("MyTest.txt");
Changed charTable into character array and added step to handle
INT_MIN.
It works fine.Once again thanks.
Regards,
manoj.

Mar 10 '06 #34
ma*******@gmail.com wrote:
Jerry Coffin wrote:
The C version continues to work fine, but you can also
use std::numeric_limits<int>::min(). This can be
particularly useful inside of a template where you don't
necessarily know what type you're dealing with ahead of
time.

MSVC 6 and gcc 2.95.3 complains on this.Devcpp (having gcc version
3.4.2 mingw) works fine with this.Is this a new feature?


Both MSVC 6 and gcc 2.95* should be considered pre-standard compilers.
Many compilers where pretty late to support certain features provided
by the standard. Whether it is a "new" feature depends on your view:
the standard is now in place for something like seven years...
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Mar 10 '06 #35
Dietmar Kuehl wrote:
Both MSVC 6 and gcc 2.95* should be considered pre-standard compilers.
Many compilers where pretty late to support certain features provided
by the standard. Whether it is a "new" feature depends on your view:
the standard is now in place for something like seven years...


Unfortunately my office still uses these two for developement.
At home i have VC 2005 express and Devcpp.

Mar 10 '06 #36
ma*******@gmail.com wrote:
Phlip wrote:
manoj1978 wrote:
>> > i = -i;
> Will this really cause issue if i is smallest negetive int?

It will cause a problem on all platforms using two's complement to
represent the negative integers. Historically there had been machines
which used a different approach but I would suspect that all modern
systems actually use two's complement. The tricky part here is that
the range of values is asymmetric. If you are using n bits to
represent your integer, the range for signed integers is

-2^(n - 1) to 2^(n - 1) - 1

("x^y" in the above expression means "x to the power of y" not the
C++ meaning of XOR). Applying the usual approach to change the sign
of the number, nothing happens to the smallest negative number: it
just stays the same.
On my system,it remains as it is.I modified the code to treat that
input as invalid.


This is actually the wrong fix! You should treat the situations
somehow. One approach is to handle the least significant digit
specifically and only negate the resulting values afterwards. This
could be done by adding the base to negative values smaller than the
base itself before negating the negative value. I recently posted
code which did just that (although the transformation uses a fixed
base of 10).
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Mar 10 '06 #37

Dietmar Kuehl wrote:
On my system,it remains as it is.I modified the code to treat that
input as invalid.


This is actually the wrong fix! You should treat the situations
somehow. One approach is to handle the least significant digit
specifically and only negate the resulting values afterwards. This
could be done by adding the base to negative values smaller than the
base itself before negating the negative value. I recently posted
code which did just that (although the transformation uses a fixed
base of 10).


I knew that it is a wrong fix.But unfortunately not able to think of
any solution.
Will surely try your idea.

Thanks and Regards,
manoj.

Mar 10 '06 #38

Dietmar Kuehl wrote:
This is actually the wrong fix! You should treat the situations
somehow. One approach is to handle the least significant digit
specifically and only negate the resulting values afterwards. This
could be done by adding the base to negative values smaller than the
base itself before negating the negative value. I recently posted
code which did just that (although the transformation uses a fixed
base of 10).
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence


Could you please give a link of this posting?

Regards,
manoj.

Mar 10 '06 #39

manoj1...@gmail.com wrote:
Dietmar Kuehl wrote:
This is actually the wrong fix! You should treat the situations
somehow. One approach is to handle the least significant digit
specifically and only negate the resulting values afterwards. This
could be done by adding the base to negative values smaller than the
base itself before negating the negative value. I recently posted
code which did just that (although the transformation uses a fixed
base of 10).
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence


Could you please give a link of this posting?

Regards,
manoj.


I got it here
http://groups.google.co.in/group/com...4117e0eecabcc2

Sorry about that.

Regards,
manoj.

Mar 10 '06 #40

ma*******@gmail.com wrote:
Jerry Coffin wrote:
The C version continues to work fine, but you can also
use std::numeric_limits<int>::min(). This can be
particularly useful inside of a template where you don't
necessarily know what type you're dealing with ahead of
time.

MSVC 6 and gcc 2.95.3 complains on this.Devcpp (having gcc version
3.4.2 mingw) works fine with this.Is this a new feature?


I missed #include <limits> :-(

It works fine in MSVC 6 with that.

Regards,
manoj.

Mar 10 '06 #41

Dietmar Kuehl wrote:
ma*******@gmail.com wrote:
On my system,it remains as it is.I modified the code to treat that
input as invalid.


This is actually the wrong fix! You should treat the situations
somehow. One approach is to handle the least significant digit
specifically and only negate the resulting values afterwards. This
could be done by adding the base to negative values smaller than the
base itself before negating the negative value. I recently posted
code which did just that (although the transformation uses a fixed
base of 10).


I put the following into the code.

if ((base > 0) && (i < 0))
{
if (i < -base)
{
str += charTable[-(i % base)];
i /= base;
}
negate = "-";
i = -i;
}

and it works.

I am confused about adding the base part in your code though.
Could you please explain the reason?

Regards,
manoj.

Mar 10 '06 #42
ma*******@gmail.com wrote:
if (i < -base)
{
str += charTable[-(i % base)];
i /= base;
}
[...]
and it works.
For some definition of "it works" but clearly not mine: the result
of using the modulo operator with negative operands is implementation
defined in C++, i.e. it may work depending on the choice of the
implementation. Essentially, the sign of the result is not defined.
I am confused about adding the base part in your code though.
Could you please explain the reason?


By using something like this to figure out the last digit

-(i < -base? i + base: i) % base

(assuming a positive base) the code avoids any problems with the
implementation defined issues of the modulo operator: both operands
are positive and thus the remainder is clearly positive, too.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Mar 10 '06 #43

Dietmar Kuehl wrote:
ma*******@gmail.com wrote:
if (i < -base)
{
str += charTable[-(i % base)];
i /= base;
}
[...]
and it works.


For some definition of "it works" but clearly not mine: the result
of using the modulo operator with negative operands is implementation
defined in C++, i.e. it may work depending on the choice of the
implementation. Essentially, the sign of the result is not defined.


I have a doubt here. which among these causes undefined behavior?
Because i was relying on these :-((

negetive % negetive.
negetive % positive.
positive % negetive
I am confused about adding the base part in your code though.
Could you please explain the reason?


By using something like this to figure out the last digit

-(i < -base? i + base: i) % base

(assuming a positive base) the code avoids any problems with the
implementation defined issues of the modulo operator: both operands
are positive and thus the remainder is clearly positive, too.


Now I got it.Thanks.

Regards,
manoj.

Mar 10 '06 #44
In article <1141976111.078529.189330
@j52g2000cwj.googlegroups.com>, ma*******@gmail.com
says...
Jerry Coffin wrote:
The C version continues to work fine, but you can also
use std::numeric_limits<int>::min(). This can be
particularly useful inside of a template where you don't
necessarily know what type you're dealing with ahead of
time.

MSVC 6 and gcc 2.95.3 complains on this.Devcpp (having gcc version
3.4.2 mingw) works fine with this.Is this a new feature?


It's not particularly new. VC++ 6.0 and gcc 2.95.3 are
particularly old...

--
Later,
Jerry.

The universe is a figment of its own imagination.
Mar 10 '06 #45
ma*******@gmail.com wrote:
For some definition of "it works" but clearly not mine: the result
of using the modulo operator with negative operands is implementation
defined in C++, i.e. it may work depending on the choice of the
implementation. Essentially, the sign of the result is not defined.


I have a doubt here. which among these causes undefined behavior?
Because i was relying on these :-((

negetive % negetive.
negetive % positive.
positive % negetive


Well, they are not "undefined" but "implementation defined". There
is a subtle difference: for "undefined" the implementation does not
have to state what it does and actually may not even detect the
situation at all. For "implementation defined" the implementation
is supposed to tell somewhere how it handles the situation.

The relevant quote from the standard is this (5.6, expr.mul,
paragraph 4):

If the second operand of / or % is zero the behavior is undefined;
otherwise (a/b)*b + a%b is equal to a. If both operands are
nonnegative then the remainder is nonnegative; if not, the sign of
the remainder is implementation-defined.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
Mar 10 '06 #46

Dietmar Kuehl wrote:
The relevant quote from the standard is this (5.6, expr.mul,
paragraph 4):

If the second operand of / or % is zero the behavior is undefined;
otherwise (a/b)*b + a%b is equal to a. If both operands are
nonnegative then the remainder is nonnegative; if not, the sign of
the remainder is implementation-defined.

I posted my message before seeing this.Sorry.

Regards,
manoj.

Mar 10 '06 #47

ma*******@gmail.com wrote:
Dietmar Kuehl wrote:
For some definition of "it works" but clearly not mine: the result
of using the modulo operator with negative operands is implementation
defined in C++, i.e. it may work depending on the choice of the
implementation. Essentially, the sign of the result is not defined.


I have a doubt here. which among these causes undefined behavior?
Because i was relying on these :-((

negetive % negetive.
negetive % positive.
positive % negetive


I have the following assumption about % and /

When b != 0.

1. abs(a/b) == abs(a) / abs(b)
2. sign of a/b is positive if a and b have the same sign.negative
otherwise.
3. abs(a%b) == abs(a) % abs(b)
4. sign of a %b == sign of a.
5. (a/b) * b + a%b == a
From C Standard May 6,2005 draft Page 82


section 6.5.5 Mulplicative operators

5 The result of the / operator is the quotient from the division of the
first operand by the
second; the result of the % operator is the remainder. In both
operations, if the value of
the second operand is zero, the behavior is undefined.
6 When integers are divided, the result of the / operator is the
algebraic quotient with any
fractional part discarded(88) If the quotient a/b is representable, the
expression
(a/b)*b + a%b shall equal a.

foot note 88) This is often called ''truncation toward zero''.

How many of my assumptions are valid? Also what the C++ standard says
about this?

Mar 10 '06 #48

ma*******@gmail.com wrote:
Dietmar Kuehl wrote:
For some definition of "it works" but clearly not mine: the result
of using the modulo operator with negative operands is implementation
defined in C++, i.e. it may work depending on the choice of the
implementation. Essentially, the sign of the result is not defined.


I have a doubt here. which among these causes undefined behavior?
Because i was relying on these :-((

negetive % negetive.
negetive % positive.
positive % negetive


I have the following assumption about % and /

When b != 0.

1. abs(a/b) == abs(a) / abs(b)
2. sign of a/b is positive if a and b have the same sign.negative
otherwise.
3. abs(a%b) == abs(a) % abs(b)
4. sign of a %b == sign of a.
5. (a/b) * b + a%b == a
From C Standard May 6,2005 draft Page 82


section 6.5.5 Mulplicative operators

5 The result of the / operator is the quotient from the division of the
first operand by the
second; the result of the % operator is the remainder. In both
operations, if the value of
the second operand is zero, the behavior is undefined.
6 When integers are divided, the result of the / operator is the
algebraic quotient with any
fractional part discarded(88) If the quotient a/b is representable, the
expression
(a/b)*b + a%b shall equal a.

foot note 88) This is often called ''truncation toward zero''.

How many of my assumptions are valid? Also what the C++ standard says
about this?

Mar 10 '06 #49

Dietmar Kuehl wrote:
ma*******@gmail.com wrote:
For some definition of "it works" but clearly not mine: the result
of using the modulo operator with negative operands is implementation
defined in C++, i.e. it may work depending on the choice of the
implementation. Essentially, the sign of the result is not defined.


I have a doubt here. which among these causes undefined behavior?
Because i was relying on these :-((

negetive % negetive.
negetive % positive.
positive % negetive


Well, they are not "undefined" but "implementation defined". There
is a subtle difference: for "undefined" the implementation does not
have to state what it does and actually may not even detect the
situation at all. For "implementation defined" the implementation
is supposed to tell somewhere how it handles the situation.

The relevant quote from the standard is this (5.6, expr.mul,
paragraph 4):

If the second operand of / or % is zero the behavior is undefined;
otherwise (a/b)*b + a%b is equal to a. If both operands are
nonnegative then the remainder is nonnegative; if not, the sign of
the remainder is implementation-defined.


A quick search of comp.lang.c shows that what you say is true for C90
also.but differs in C99.
Regards,
manoj

Mar 10 '06 #50

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Sathyaish | last post by:
I am writing a program that will take a string that has a C source file and it would format all the multi-line comments like these: //Jingle bells, jingle bells, jingles all the way //O what...
2
by: John Regan | last post by:
Hello All I am trying to find the owner of a file or folder on our network (Windows 2000 Server) using VB.Net and/or API. so I can search for Folders that don't follow our company's specified...
1
by: Mark Hollander | last post by:
Hi All, Could you please help me convert this code so that it will run in VB.NET Thank You Mark Hollander Private Type USER_INFO Name As String
3
by: Joe | last post by:
Hello All, I am developing a webform which creates ArrayLists of people's names and addresses (the values are retrieved from an xml file) and dynamically drops a user control onto the webform...
7
by: manoj1978 | last post by:
Hi All, I wrote the following to convert an integer to its string representation from base -32 to 32(32 since strtoul takes 32). Used recursion so as not to crowd the logic. Please Comment on...
5
by: Registered User | last post by:
I'm a newbie and have attempted to create a program to convert a string containing the representation of a number in a specified base to a decimal integer. Here's the code: #include <stdio.h> ...
8
by: Greg Lyles | last post by:
Hi all, I'm trying to develop an ASP.NET 2.0 website and am running into some real problems with what I thought would be a relatively simple thing to do. In a nutshell, I'm stuck on trying to...
1
by: td0g03 | last post by:
Hello, I am new to C and I am new to English. I not sure what palindromes mean. I don't know exactly what my teacher wants me to do. If someone could explain it to me in a different way that would be...
2
by: BairnsRus | last post by:
Wonder if anyone can point me in the right direction? For part of my coursework I have been asked to create a BMI monitor which calculates height, weight and displays BMI for up to 5 records. So far...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.