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. | | | | re: Please comment on my integer to string code. manoj1978@gmail.com wrote:[color=blue]
> Hi All,
> I wrote the following to print an integer in its string
> representation for base -36 to 36.
>
> [code redacted][/color]
How do you display numbers in a *negative* base????? | | | | re: Please comment on my integer to string code.
red floyd wrote:
[color=blue]
> manoj1978@gmail.com wrote:[color=green]
> > Hi All,
> > I wrote the following to print an integer in its string
> > representation for base -36 to 36.
> >
> > [code redacted][/color]
>
> How do you display numbers in a *negative* base?????[/color]
Consider negadecimal.
27 will be 187
since 187 = 1 * -10 * -10 + 8 * -10 + 7 = 27. | | | | re: Please comment on my integer to string code. manoj1978@gmail.com wrote:
[color=blue]
> int main()
> {
> for(int i = -55; i <= 55; i++)
> {
> cout << i << " = ";
> printBase(i,-10);
> }
> }[/color]
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!!! | | | | re: Please comment on my integer to string code.
Phlip wrote:
[color=blue]
> 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!!![/color]
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. | | | | re: Please comment on my integer to string code.
Phlip wrote:[color=blue]
> manoj1978@gmail.com wrote:
>
>[color=green]
>>int main()
>>{
>> for(int i = -55; i <= 55; i++)
>> {
>> cout << i << " = ";
>> printBase(i,-10);
>> }
>>}[/color]
>
>
> 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);[/color]
Why four of them in a row? Are there side effects expected that affect
the behaviour of the function?
[color=blue]
> 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.[/color]
V
--
Please remove capital As from my address when replying by mail | | | | re: Please comment on my integer to string code.
Victor Bazarov wrote:
[color=blue][color=green]
>>assert("whatever"Â*==Â*printBase(-55);
>>assert("whatever"Â*==Â*printBase(-55);
>>assert("whatever"Â*==Â*printBase(-55);
>>assert("whatever"Â*==Â*printBase(-55);[/color]
>
> Why four of them in a row?Â*Â*AreÂ*thereÂ*sideÂ*effectsÂ*expectedÂ*that *affect
> the behaviour of the function?[/color]
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!!! | | | | re: Please comment on my integer to string code.
Phlip wrote:[color=blue]
>
> 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. ;-)[/color]
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... | | | | re: Please comment on my integer to string code.
Phlip wrote:
[color=blue]
>
> 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. ;-)
>[/color]
Especially since branch testing is known to be inadequate. <g>
--
Pete Becker
Roundhouse Consulting, Ltd. | | | | re: Please comment on my integer to string code.
Pete Becker wrote:
[color=blue]
> Especially since branch testing is known to be inadequate. <g>[/color]
Inadequate for converting an integer to a string???
<vbgd&rc>
--
Phlip http://www.greencheese.org/ZeekLand <-- NOT a blog!!! | | | | re: Please comment on my integer to string code.
Phlip wrote:
[color=blue]
> Pete Becker wrote:
>
>[color=green]
>>Especially since branch testing is known to be inadequate. <g>[/color]
>
>
> Inadequate for converting an integer to a string???
>[/color]
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. | | | | re: Please comment on my integer to string code.
Phlip wrote:[color=blue]
> Inadequate for converting an integer to a string???[/color]
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:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence | | | | re: Please comment on my integer to string code.
Dietmar Kuehl wrote:
[color=blue]
> That is, in addition to branch testing you
> need to perform at least some testing for corner cases.[/color]
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!!! | | | | re: Please comment on my integer to string code. manoj1978@gmail.com wrote in message
<1141916757.291734.248560@p10g2000cwp.googlegroups .com>...[color=blue]
>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>
>[/color]
// >using std::abs;[color=blue]
>using std::cout;
>using std::endl;[/color]
// >using std::reverse;[color=blue]
>using std::string;[/color]
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.
[color=blue]
>[/color]
// >char charTable[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::string charTable( "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
[color=blue]
>[/color]
// >void printBase(int i, int base){
std::string CalcBase(int i, int base){
using std::abs; // etc.
[color=blue]
> if ((abs(base) <= 1) || (abs(base) > 36) || (i == 0)){[/color]
// > cout << "0" << endl;
// > return;
return "0";[color=blue]
> }
>
> string str = "";
> if ((base > 0) && (i < 0)){
> str += "-"; // prints "-16 = 10-" for base==16
> i = -i;
> }
>
> do {
> if (i % base >= 0){[/color]
// > str += charTable[i % base];
str += charTable.at( i % base );
[color=blue]
> i = i / base;
> } else {[/color]
// > str += charTable[i % base - base];
str += charTable.at( i % base - base );
[color=blue]
> i = i /base + 1;
> }
> } while(i);[/color]
// > reverse(str.begin(), str.end());
std::reverse(str.begin(), str.end());
// prints "-16 = 10-" for base==16
// > cout << str << endl;
return str;[color=blue]
> } // CalcBase(int,int)
>
>int main(){[/color]
try{
for(int i(-55); i <= 55; ++i){
// > cout << i << " = ";
// > printBase( i, -10 );
std::cout << i <<" = "<<CalcBase( i, -10 )<<std::endl;
[color=blue]
> } // for(i)[/color]
} // 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;
[color=blue]
> } // main()end
>
>Thanks and Regards,
>manoj.[/color]
// - 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 | | | | re: Please comment on my integer to string code.
BobR wrote:
[color=blue]
> catch(...){
> std::cerr<<"caughtÂ*...Â*something"<<std::endl;
> returnÂ*EXIT_FAILURE;
> }[/color]
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!!! | | | | re: Please comment on my integer to string code.
BobR wrote:
[color=blue]
>
> // > str += charTable[i % base];
> str += charTable.at( i % base );
>[/color]
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. | | | | re: Please comment on my integer to string code.
Phlip wrote:
[color=blue]
>[color=green]
>>catch(...){
>>std::cerr<<"caught ... something"<<std::endl;
>>return EXIT_FAILURE;
>>}[/color]
>
>
> 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.
>[/color]
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. | | | | re: Please comment on my integer to string code.
Phlip wrote in message ...[color=blue]
>BobR wrote:[/color]
[color=blue][color=green]
>> catch(...){
>> std::cerr<<"caught ... something"<<std::endl;
>> return EXIT_FAILURE;
>> }[/color]
>
>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[/color]
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 | | | | re: Please comment on my integer to string code.
BobR wrote:
[color=blue]
> Are you saying I can't do that in GNU/Linux, winXP?[/color]
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!!! | | | | re: Please comment on my integer to string code.
Phlip wrote:[color=blue]
> BobR wrote:
>[color=green]
>> Are you saying I can't do that in GNU/Linux, winXP?[/color]
>
> 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.[/color]
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. | | | | re: Please comment on my integer to string code.
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 | | | | re: Please comment on my integer to string code.
red floyd wrote:
[color=blue]
> We're way OT here, but it turns them into catch(int)?[/color]
The purpose of topicality is to grow a healthy community whose members know
they can stretch the bounds now and then.
[color=blue]
> I could never figure out C0000005 errors (Win32 equivalent of SegV) turned
> into. That's the main reason I had catch(...) in my code.[/color]
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!!! | | | | re: Please comment on my integer to string code.
BobR wrote:[color=blue]
> manoj1978@gmail.com wrote in message
> <1141916757.291734.248560@p10g2000cwp.googlegroups .com>...[/color]
[color=blue]
> Style-wise, **IMHO**, (at this point) it stinks!! I'd put the 'using *'
> inside the function/main if I couldn't type "std::".[/color]
thanks.will keep in mind.[color=blue]
> My suggestions inline below.
>[color=green]
> >[/color]
> // >char charTable[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
>
> std::string charTable( "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
>[color=green]
> >[/color]
> // >void printBase(int i, int base){
> std::string CalcBase(int i, int base){
> using std::abs; // etc.
>[color=green]
> > if ((abs(base) <= 1) || (abs(base) > 36) || (i == 0)){[/color]
> // > cout << "0" << endl;
> // > return;
> return "0";[color=green]
> > }
> >
> > string str = "";
> > if ((base > 0) && (i < 0)){
> > str += "-"; // prints "-16 = 10-" for base==16[/color][/color]
Thanks.[color=blue][color=green]
> > i = -i;[/color][/color]
Will this really cause issue if i is smallest negetive int?[color=blue][color=green]
> > }
> >
> > do {
> > if (i % base >= 0){[/color]
> // > str += charTable[i % base];
> str += charTable.at( i % base );
>[color=green]
> > i = i / base;
> > } else {[/color]
> // > str += charTable[i % base - base];
> str += charTable.at( i % base - base );
>[color=green]
> > i = i /base + 1;
> > }
> > } while(i);[/color]
> // > reverse(str.begin(), str.end());
> std::reverse(str.begin(), str.end());
>
> // prints "-16 = 10-" for base==16[/color]
Will this be ok?
if (str[0] == '-')
std::reverse(str.begin()+1,str.end());[color=blue]
>
> // > cout << str << endl;
> return str;[color=green]
> > } // CalcBase(int,int)
> >
> >int main(){[/color]
>
> try{
> for(int i(-55); i <= 55; ++i){
> // > cout << i << " = ";
> // > printBase( i, -10 );
> std::cout << i <<" = "<<CalcBase( i, -10 )<<std::endl;
>[color=green]
> > } // for(i)[/color]
> } // 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;
>[color=green]
> > } // main()end
> >
> >Thanks and Regards,
> >manoj.[/color]
>
> // - 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?[/color]
I modified a C code for this.I havent used C++ much.Want to be sure
that,there is no stupid mistakes.[color=blue]
>
> --
> Bob R
> POVrookie[/color]
Thanks Bob,
Regards,
manoj. | | | | re: Please comment on my integer to string code. manoj1978@gmail.com wrote:[color=blue][color=green]
>> manoj1978@gmail.com wrote in message[color=darkred]
>>> i = -i;[/color][/color]
> Will this really cause issue if i is smallest negetive int?[/color]
Whatever you mean by "smallest negetive"...
[color=blue]
>[..][/color]
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 | | | | re: Please comment on my integer to string code.
Victor Bazarov wrote:
[color=blue]
> Whatever you mean by "smallest negetive"...
>[color=green]
> >[..][/color]
>
> 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..[/color]
Thanks for the info.
Regards,
manoj.. | | | | re: Please comment on my integer to string code.
manoj1978 wrote:
[color=blue][color=green]
>> Style-wise, **IMHO**, (at this point) it stinks!! I'd put the 'using *'
>> inside the function/main if I couldn't type "std::".[/color][/color]
[color=blue]
> thanks.will keep in mind.[/color]
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.
[color=blue][color=green][color=darkred]
>> > i = -i;[/color][/color]
> Will this really cause issue if i is smallest negetive int?[/color]
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.
[color=blue][color=green]
>> // > str += charTable[i % base];
>> str += charTable.at( i % base );[/color][/color]
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";
[color=blue][color=green]
>> // prints "-16 = 10-" for base==16[/color][/color]
[color=blue]
> Will this be ok?
> if (str[0] == '-')
> std::reverse(str.begin()+1,str.end());[/color]
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!!! | | | | re: Please comment on my integer to string code.
Phlip wrote:
[color=blue]
> manoj1978 wrote:
>[color=green][color=darkred]
> >> Style-wise, **IMHO**, (at this point) it stinks!! I'd put the 'using *'
> >> inside the function/main if I couldn't type "std::".[/color][/color]
>[color=green]
> > thanks.will keep in mind.[/color]
>
> 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.
>[color=green][color=darkred]
> >> > i = -i;[/color]
> > Will this really cause issue if i is smallest negetive int?[/color]
>
> 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.[/color]
On my system,it remains as it is.I modified the code to treat that
input as invalid.
[color=blue]
>[color=green][color=darkred]
> >> // > str += charTable[i % base];
> >> str += charTable.at( i % base );[/color][/color]
>
> 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";[/color]
Ok.[color=blue]
>[color=green][color=darkred]
> >> // prints "-16 = 10-" for base==16[/color][/color]
>[color=green]
> > Will this be ok?
> > if (str[0] == '-')
> > std::reverse(str.begin()+1,str.end());[/color]
>
> 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.[/color]
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. | | | | re: Please comment on my integer to string code.
Phlip wrote:
[color=blue][color=green][color=darkred]
> >> > i = -i;[/color]
> > Will this really cause issue if i is smallest negetive int?[/color]
>
> 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.[/color]
Using C's INT_MIN is okay for C++ or does it have its own way of
representing smallest int?
Regards,
manoj. | | | | re: Please comment on my integer to string code.
manoj1978 wrote:
[color=blue]
> Using C's INT_MIN is okay for C++ or does it have its own way of
> representing smallest int?[/color]
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.
[color=blue]
> 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.[/color]
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!!! | | | | re: Please comment on my integer to string code.
Phlip wrote:
[color=blue]
> manoj1978 wrote:[color=green]
> > 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.[/color]
>
> 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.[/color]
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.[color=blue]
>
> 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.[/color]
Regards,
manoj. | | | | re: Please comment on my integer to string code.
In article <1141970724.433887.106160
@i40g2000cwc.googlegroups.com>, manoj1978@gmail.com
says...
[ ... ]
[color=blue]
> Using C's INT_MIN is okay for C++ or does it have its own way of
> representing smallest int?[/color]
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. | | | | re: Please comment on my integer to string code.
Jerry Coffin wrote:
[color=blue]
> 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.[/color]
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? | | | | re: Please comment on my integer to string code. manoj1978@gmail.com wrote in message ...[color=blue]
>[color=green]
>> 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[/color][/color]
each[color=blue][color=green]
>> one. If they fail, use Undo to back out your changes.[/color]
>
>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.[/color]
#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 | | | | re: Please comment on my integer to string code.
BobR wrote:
[color=blue]
> #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[/color]
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. | | | | re: Please comment on my integer to string code. manoj1978@gmail.com wrote:
[color=blue]
> Jerry Coffin wrote:[color=green]
>> 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.[/color]
> 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?[/color]
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:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence | | | | re: Please comment on my integer to string code.
Dietmar Kuehl wrote:
[color=blue]
> 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...[/color]
Unfortunately my office still uses these two for developement.
At home i have VC 2005 express and Devcpp. | | | | re: Please comment on my integer to string code. manoj1978@gmail.com wrote:[color=blue]
> Phlip wrote:[color=green]
>> manoj1978 wrote:[color=darkred]
>> >> > i = -i;
>> > Will this really cause issue if i is smallest negetive int?[/color][/color][/color]
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.
[color=blue]
> On my system,it remains as it is.I modified the code to treat that
> input as invalid.[/color]
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:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence | | | | re: Please comment on my integer to string code.
Dietmar Kuehl wrote:
[color=blue][color=green]
> > On my system,it remains as it is.I modified the code to treat that
> > input as invalid.[/color]
>
> 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).[/color]
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. | | | | re: Please comment on my integer to string code.
Dietmar Kuehl wrote:[color=blue]
> 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:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
> <http://www.eai-systems.com> - Efficient Artificial Intelligence[/color]
Could you please give a link of this posting?
Regards,
manoj. | | | | re: Please comment on my integer to string code.
manoj1...@gmail.com wrote:
[color=blue]
> Dietmar Kuehl wrote:[color=green]
> > 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:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
> > <http://www.eai-systems.com> - Efficient Artificial Intelligence[/color]
>
> Could you please give a link of this posting?
>
> Regards,
> manoj.[/color]
I got it here http://groups.google.co.in/group/com...4117e0eecabcc2
Sorry about that.
Regards,
manoj. | | | | re: Please comment on my integer to string code. manoj1978@gmail.com wrote:
[color=blue]
> Jerry Coffin wrote:
>[color=green]
> > 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.[/color]
> 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?[/color]
I missed #include <limits> :-(
It works fine in MSVC 6 with that.
Regards,
manoj. | | | | re: Please comment on my integer to string code.
Dietmar Kuehl wrote:
[color=blue]
> manoj1978@gmail.com wrote:[color=green]
> > On my system,it remains as it is.I modified the code to treat that
> > input as invalid.[/color]
>
> 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).[/color]
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. | | | | re: Please comment on my integer to string code. manoj1978@gmail.com wrote:[color=blue]
> if (i < -base)
> {
> str += charTable[-(i % base)];
> i /= base;
> }[/color]
[...]
[color=blue]
> and it works.[/color]
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.
[color=blue]
> I am confused about adding the base part in your code though.
> Could you please explain the reason?[/color]
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:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence | | | | re: Please comment on my integer to string code.
Dietmar Kuehl wrote:
[color=blue]
> manoj1978@gmail.com wrote:[color=green]
> > if (i < -base)
> > {
> > str += charTable[-(i % base)];
> > i /= base;
> > }[/color]
>
> [...]
>[color=green]
> > and it works.[/color]
>
> 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.[/color]
I have a doubt here. which among these causes undefined behavior?
Because i was relying on these :-((
negetive % negetive.
negetive % positive.
positive % negetive
[color=blue]
>[color=green]
> > I am confused about adding the base part in your code though.
> > Could you please explain the reason?[/color]
>
> 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.[/color]
Now I got it.Thanks.
Regards,
manoj. | | | | re: Please comment on my integer to string code.
In article <1141976111.078529.189330
@j52g2000cwj.googlegroups.com>, manoj1978@gmail.com
says...[color=blue]
> Jerry Coffin wrote:
>[color=green]
> > 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.[/color]
> 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?[/color]
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. | | | | re: Please comment on my integer to string code. manoj1978@gmail.com wrote:[color=blue][color=green]
>> 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.[/color]
>
> I have a doubt here. which among these causes undefined behavior?
> Because i was relying on these :-((
>
> negetive % negetive.
> negetive % positive.
> positive % negetive[/color]
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:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence | | | | re: Please comment on my integer to string code.
Dietmar Kuehl wrote:[color=blue]
> 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.
>[/color]
I posted my message before seeing this.Sorry.
Regards,
manoj. | | | | re: Please comment on my integer to string code. manoj1978@gmail.com wrote:[color=blue]
> Dietmar Kuehl wrote:[/color]
[color=blue][color=green]
> > 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.[/color]
>
> I have a doubt here. which among these causes undefined behavior?
> Because i was relying on these :-((
>
> negetive % negetive.
> negetive % positive.
> positive % negetive[/color]
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
[color=blue]
>From C Standard May 6,2005 draft Page 82[/color]
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? | | | | re: Please comment on my integer to string code. manoj1978@gmail.com wrote:[color=blue]
> Dietmar Kuehl wrote:[/color]
[color=blue][color=green]
> > 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.[/color]
>
> I have a doubt here. which among these causes undefined behavior?
> Because i was relying on these :-((
>
> negetive % negetive.
> negetive % positive.
> positive % negetive[/color]
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
[color=blue]
>From C Standard May 6,2005 draft Page 82[/color]
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? | | | | re: Please comment on my integer to string code.
Dietmar Kuehl wrote:[color=blue]
> manoj1978@gmail.com wrote:[color=green][color=darkred]
> >> 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.[/color]
> >
> > I have a doubt here. which among these causes undefined behavior?
> > Because i was relying on these :-((
> >
> > negetive % negetive.
> > negetive % positive.
> > positive % negetive[/color]
>
> 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.
>[/color]
A quick search of comp.lang.c shows that what you say is true for C90
also.but differs in C99.
Regards,
manoj |  | | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,449 network members.
|