|
1. You should try to use a nice string lib.
There are so many around (at this codeproject)
So you will overcome many buffer stuff.
2. Try to modulize the actual text to support another language.
E.x : Store
single num English French VietNamese
4 , "four" , "quatre" , "bon"
3. I don't know what algorith you are using but take a look at mine NumToText Excel macro at
www.coderfarm.com/pubs/Excel
I "steal" that code somewhere I can't remember.
Nguyen Binh.
|
|
|
|
|
Thanks for the suggestions, but my primary goal with this was to keep things simple and fast, something wich a robust string library make make it slower.
Also, do not prefer to use "stolen" code as you put it. I believe in always giving credit where it's do.
Jeremy Falcon
|
|
|
|
|
You missed my Idea. I donot convert any typed data to their textual but a string pointer.
|
|
|
|
|
Here's your prototype:
char *getNumCardinal (char *szDest, unsigned long num, short isProper, short isAnd);
You indicate szDest needs to be passed in, fine... However, consider the following code:
char buffer[3];
getNumCardinal (buffer,12,TRUE,TRUE);
That just caused a buffer overwrite, because you wrote "twelve\0" into my 3-byte buffer. That's no good. Not at all. You need to either use a string class (which manages it's own internal buffer), or have the caller pass in the length of the string he has allocated.
Look up some references on the usage of strcpy vs. strncpy. It's essentially the same problem, and I can't believe noone here pointed it out...
|
|
|
|
|
Anonymous wrote:
That just caused a buffer overwrite, because you wrote "twelve\0" into my 3-byte buffer. That's no good. Not at all.
The intent was that the caller would have enough sense to allocate a proper buffer. How many times do you see in MS documentation that the behavior is "undefined" unless you do something the way it's expected?
Regardless, you do serve a valid point that I will take into consideration. But, who am I to give credit to for the tip? I always give credit where it's do. If you prefer to stay anonymous, no problem, I just won't be able to give you credit.
Thanks!
Jeremy L. Falcon<nobr>
Homepage : Sonork = 100.16311
"Victims falling under chains ~ You hear them crying dying pains
The fist of terrors breaking through ~ Now there's nothing you can do"
Song: Phantom Lord - Album: Kill 'em All - Artist: Metallica
|
|
|
|
|
You return values by using strdup(). It should be noted that strdup() is a common extension, but not in the ANSI standard (you meantion that ANSI compliance is important). Further, it gets it memory via malloc, which means that the returned value needs to be free'd or a memory leak will occur. Usage like you do in your demo:
printf("\nProper Cardinal:\n%s\n\nCardinal:\n%s\n\nProper Ordinal:\n%s\n\nOrdinal:\n%s\n\n",
getNumWord(x, TRUE, FALSE),
getNumWord(x, FALSE, FALSE),
getNumWord(x, TRUE, TRUE),
getNumWord(x, FALSE, TRUE));
guarantees a memory leak.
Truth,
James
|
|
|
|
|
Yeah, I just checked it out in MSDN and sure enough it isn't. It's amazing how you can get so used to something. I have used strdup() on other systems as well, I guess it slipped my mind after a while.
Either way, I'll make another update. I sent a second update last week but it hasn't been uploaded yet. Now I know why the unedited contributions are becoming popular. I'll make a third update real soon, and hope it gets online pronto.
Thanks for the tip!
Jeremy L. Falcon
"The One Who Said, 'The One Who Said...'"
<nobr>
Homepage : Feature Article : Sonork = 100.16311
|
|
|
|
|
Jeremy Falcon wrote:
Now I know why the unedited contributions are becoming popular
hey! I heard that! :P
cheers,
Chris Maunder
|
|
|
|
|
I didn't think you were watching!
Jeremy L. Falcon
"The One Who Said, 'The One Who Said...'"
<nobr>
Homepage : Feature Article : Sonork = 100.16311
|
|
|
|
|
Hello
A colleague tell me about Jeremy Falcon interger to text code. I already developed an interger to text for my project. My prog is far more better cos I can convert "double" number, not only interger. It means you can convert a number of 40 digits or more ?
Even It can convert negative and decimal number with scale of 2. Please try my code
P/s (it is used for vietnamese)
extern "C" NUMANALYSE_API char *VS_MainNum(char *numstr)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString ret("");
double x;
char *stopstring;
//char frac[20];
CString cstmp("");
int d;
int itmp;
int decimal, sign;
int signall;
char *buffer;
d = 0;
signall = 0;
if ((x = strtod( numstr, &stopstring )) == HUGE_VAL )
return("NG Error overflow");
*stopstring = '\0';
ret.Format("%s", numstr);
if (x <0)
signall = 1;
itmp = ret.Find('.');
if ( itmp != -1)
{
cstmp = ret.Right(ret.GetLength() - itmp - 1);
cstmp = cstmp.Left(2);
d = atoi(cstmp);
ret = ret.Left(itmp);
}
if ((x = strtod( ret, &stopstring )) == HUGE_VAL )
return("NG Error overflow");
buffer = _fcvt( x, 0, &decimal, &sign );
if (sign != 0)
x = -x ;
decimal = strlen(buffer);
strcpy(buffer,ret.Right(decimal));
ret = NumComb( x, buffer);
ret.TrimLeft(" ");
ret.TrimRight(" ");
if (d != 0)
ret = ret + " point " + Fractal(cstmp);
if (signall != 0)
ret = "minus " + ret;
ret = "OK " + ret;
strcpy(g_ConvStr,ret);
return(g_ConvStr) ;
}
CString Fractal(CString cstw)
{
CString two("");
int dz;
int unt;
int il;
int tw;
il = cstw.GetLength();
tw = atoi(cstw);
dz = tw/10;
unt = tw%10;
if ( il == 1)
return(unit_arr[tw]);
else
if ( tw < 10 )
{
two.Format("%s %s",unit_arr[0],unit_arr[tw]);
return(two);
}
else
if ( unt == 0 )
return(unit_arr[dz]);
switch ( dz )
{
case 1:
switch ( unt )
{
case 5:
two.Format("%s %s",unit_arr[10],unit_arr[12]);
break;
case 0:
two.Format("%s",unit_arr[10]);
break;
default:
two.Format("%s %s",unit_arr[10],unit_arr[unt]);
}
break;
case 0:
two.Format("%s %s",unit_arr[0],unit_arr[unt]);
break;
default:
switch ( unt )
{
case 5:
two.Format("%s %s",unit_arr[dz],unit_arr[11]);
break;
case 0:
two.Format("%s %s",unit_arr[dz],sup_arr[0]);
break;
case 1:
two.Format("%s %s",unit_arr[dz],unit_arr[14]);
break;
case 4:
two.Format("%s %s",unit_arr[dz],unit_arr[15]);
break;
default:
two.Format("%s %s",unit_arr[dz],unit_arr[unt]);
}
break;
}
return(two);
}
CString NumComb(double x, char *s)
{
int it;
CString numall;
CString stemp(s);
CString ct(s);
int ilen;
int im;
if (x == 0)
return(unit_arr[(int)x]);
ilen = stemp.GetLength();
im = ilen%3;
stemp = ct.Left(im);
it = atoi(stemp);
switch ( im )
{
case 1:
numall.Format("%s",unit_arr[(int)it]);
break;
case 2:
numall = FirstTwo((int)it);
break;
}
if (ilen == 3 )
{
numall = FirstThree((int)x);
return(numall);
}
im = ilen - im;
ct = ct.Right(im);
int z;
z=4;
BOOL bt;
bt=TRUE;
while ( im > 0 )
{
stemp = ct.Left(3);
it = atoi(stemp);
if ( z == 4)
{
z = (im /3)%3;
if (z == 0)
z = 3;
}
if (it == 0)
{
if (bt)
{
if (numall != "")
numall = " " + numall + " " + sup_arr[(z + 1)] ;
}
im -= 3;
ct = ct.Right(im);
z = (im /3)%3;
if (z == 0)
z = 3;
if (z == 3)
bt = TRUE;
else
bt = FALSE;
continue;
}
if (bt)
if (numall != "")
{
numall = " " + numall + " " + sup_arr[(z + 1)] + " "+ FirstThree(it);
}
else
numall = FirstThree(it);
else
if (numall != "")
{
numall = " " + numall + " " + FirstThree(it);
}
else
numall = FirstThree(it);
im -= 3;
ct = ct.Right(im);
z = (im /3)%3;
if (z == 0)
z = 3;
bt=TRUE;
}
return(numall);
}
CString FirstThree(int th)
{
CString three;
if (th == 0)
{
three ="";
return(three);
}
if ( ( th%100 ) == 0 )
three.Format("%s %s",unit_arr[th/100],sup_arr[1]);
else
three.Format("%s %s %s",unit_arr[th/100],sup_arr[1],FirstTwo(th%100));
return(three);
}
CString FirstTwo(int tw)
{
CString two;
int dz;
int unt;
dz = tw/10;
unt = tw%10;
switch ( dz )
{
case 1:
switch ( unt )
{
case 5:
two.Format("%s %s",unit_arr[10],unit_arr[12]);
break;
case 0:
two.Format("%s",unit_arr[10]);
break;
default:
two.Format("%s %s",unit_arr[10],unit_arr[unt]);
}
break;
case 0:
two.Format("%s %s",unit_arr[13],unit_arr[unt]);
break;
default:
switch ( unt )
{
case 5:
two.Format("%s %s",unit_arr[dz],unit_arr[11]);
break;
case 0:
two.Format("%s %s",unit_arr[dz],sup_arr[0]);
break;
case 1:
two.Format("%s %s",unit_arr[dz],unit_arr[14]);
break;
case 4:
two.Format("%s %s",unit_arr[dz],unit_arr[15]);
break;
default:
two.Format("%s %s",unit_arr[dz],unit_arr[unt]);
}
break;
}
return(two);
}
Where should I go tomorow?
From Vietnam
|
|
|
|
|
Nguyen Luong Son wrote:
My prog is far more better cos I can convert "double" number, not only interger.
Nice thought, I may include sign and decimal places in the near future.
Nguyen Luong Son wrote:
It means you can convert a number of 40 digits or more
Pulled from MSDN...
type = double : bytes = 8 : range of values = 1.7E +/- 308 (15 digits)
This is on a 32-bit system of course.
I appreciate the code, but one of my design goals was speed. I like MFC, but we all know of the overhead CString has. Also, I have to stay ANSI compliant for this project. The (updated) algorithm I designed logically follows the structure of the way we count in the first place and doesn't have any theoretical limitations.
Thanks for the idea though! When I make a newer version I'll incorporate a long double instead of a unsigned long, and I'll be sure to give you credit for the idea.
Jeremy L. Falcon
"The One Who Said, 'The One Who Said...'"
[My Latest Article]
Homepage: imputek.com
|
|
|
|
|
You missed my Idea. I donot convert any typed data to their textual but a string pointer.
|
|
|
|
|
Today (April 2nd) I became anxious and decided to make the updates, but they are at work. I had to leave quickly. I'll send them in to CP tomorrow when I get back to the office.
Jeremy L. Falcon
"The One Who Said, 'The One Who Said...'"
[My Latest Article]
Homepage: imputek.com
|
|
|
|
|
0 = squat
100 = a hunnerd
101 = a hunnerd an one
anything more = "a bunch" or "a mess", except for familiar ones like "tree fitty seven", "four fitty four" and "nine eleven".
-c
"Do you mind if I smoke?"
"Madam, I don't care if you burn."
-Oscar Wilde
Smaller Animals Software, Inc.
|
|
|
|
|
|
Those of us in England will pronounce "2002" as "Two thousand and two" rather than the American "Two thousand two"
101 = one hundred and one
175 = one hundred and seventy five
1175 = one thousand one hundred and seventy five
etc
(i.e. wwxxyyzz would be said as wwxxyy and zz)
--
Help me! I'm turning into a grapefruit!
|
|
|
|
|
Thanks for the suggestion! I'll try to squeeze some time in this weekend to include another parameter for the English method.
Jeremy L. Falcon
"The One Who Said, 'The One Who Said...'"
[My Latest Article]
Homepage: imputek.com
|
|
|
|
|
Well, in America I have always used the "and".
However, when doing checks (cheques?) I omit the "and".
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
Yeah, I've seen it go both ways. The update will have the option to add an "and".
Jeremy L. Falcon
"The One Who Said, 'The One Who Said...'"
[My Latest Article]
Homepage: imputek.com
|
|
|
|
|
Ok. I guess I'd just assumed saying it without the and was a standard American film (from seeing all the movie trailers with the American gravel gargling guy saying "Coming Summer two thousand two" )
I always right everything on a cheque, but bunch it all together without spaces
i.e.
onehundredandfortyfivepoundsseventyfivepenceonly
(That's what my Mum taught me, as it makes it much harder for a dishonest shopkeeper to slip in extra digits)
--
Help me! I'm turning into a grapefruit!
|
|
|
|
|
I recall as far back as the early 80's I saw an algorithm to do this in BASIC. It is often used to print amounts on checks in accounting programs. But please do keep up the good work. What is your AI project?
Dave Goodman
dgoodman@infoway.com
www.dkgoodman.com
"Actio sequitur esse."
|
|
|
|
|
It's actually a fairly common 'do my homework' request, so I'm sure it will be very popular
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
"I'm somewhat suspicious of STL though. My (test,experimental) program worked first time. Whats that all about??!?!
- Jon Hulatt, 22/3/2002
|
|
|
|
|
Alas, I tried! Waahhh!!
That's okay! I needed (err, wanted) this, and I figured someone else will get some use out of it too.
Jeremy L. Falcon
"The One Who Said, 'The One Who Said...'"
[My Latest Article]
Homepage: imputek.com
|
|
|
|
|
Dave Goodman wrote:
What is your AI project?
To beat A.L.I.C.E. for the Loebner Prize. This is a long-term project (> year) mixed in with my others, but I intend to do it.
Jeremy L. Falcon
"The One Who Said, 'The One Who Said...'"
[My Latest Article]
Homepage: imputek.com
|
|
|
|
|
hmmm... I actually don't think ALICE should be that hard to beat. I'm working on an AI project of my own, to develop an NPC so human-like that casual interactions would leave the player with the impression that the NPC was played by a human. I have a working prototype, but it needs more features and content to reach the level of naturalness I'm looking for. If I get those working in time, I'm hoping to enter the contest myself. If not this year, then next.
Rather than just a chatterbot, which tends to answer with intelligent-sounding phrases but doesn't really know what's going on, my AI tries to understand the topic it's discussing, uses natural language parsing as well as keyword matching, has goals and emotions, can solve problems, assess and remember people and events, can form sentences from content as well as filling in blanks in stock sentences, and is designed to create and tell stories and participate in plotlines.
The more of us working on these problems, the better. I hope someday soon we can all share a working model of humanlike behavior. Go for it!
Dave Goodman
dgoodman@infoway.com
www.dkgoodman.com
"Actio sequitur esse."
|
|
|
|
|