Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Extracting digits from a integer

This thread is locked; no one can reply to it. rss feed Print
Extracting digits from a integer
CIRCLE
Member #5,301
December 2004

Answers in this post are>>

    int score = 656;
    char scorestring[50];
    snprintf(scorestring, sizeof(scorestring), "%d", score);
    int scorelength = strlen(scorestring);
    for (scoredigit = 0; scoredigit < scorelength; scoredigit++)
    {
    textprintf_ex(activepage, font, 0 + (scoredigit * 17), 0, makecol(255, 255, 255), -1, "%i", scorestring[((scorelength - 1) - scoredigit)] - 48);
    }

also replacing the snprintf(scorestring, sizeof(scorestring), "%d", score); with

    itoa(score, scorestring, 10);

will do the same thing. But it is considered non standard.

Original question.
I am using a new numbering system in my game where as before I just put the text on the screen. What I can not figure out is how to.

1. Find out how many places my score uses. I.E. If score was 1423 it would be 4 places

2. How to take just 1 number from the score. I.E. 1423 is the score and I wanted just the 3rd number I would have 4.

I used to have an old program in Qb that a Binary number and made it decimal. Dont know how acurate it was but it did what I am looking for or close to it.

DIM BinNum(1 TO 300) AS STRING, NStringNum(1 TO 300) AS LONG
CLS
INPUT "Binary String:_ ", BinNum$
FOR LoopStart = 1 TO LEN(BinNum$)
 BinNum$(LoopStart) = MID$(BinNum$, LoopStart, 1)
 NStringNum(LoopStart) = VAL(BinNum$(LoopStart))
NEXT
FOR LoopStart = 1 TO LEN(BinNum$)
 DecimalNum = DecimalNum + NStringNum(LoopStart) * (2 ^ (LEN(BinNum$) - LoopStart))
NEXT
PRINT DecimalNum

other then the example I don't know what it is called if even pointed in the correct direction I could do a little research on it. But I never really learned more then the basics of C/C++ and when straight into allegro.

-I edit a lot. Prepare thyself.

HardTranceFan
Member #7,317
June 2006
avatar

sprintf(someChar, "%i", score)?

And then work with someChar to get the lengths and digits.

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

Matthew Leverton
Supreme Loser
January 1999
avatar

For positive numbers:

int digit_count = (int)log10(num) + 1;

int digit_value = (int)(num / pow(10, place)) % 10;

Jakub Wasilewski
Member #3,653
June 2003
avatar

Quote:

int digit_count = (int)log10(num) + 1;

Just don't try it on 0.

---------------------------
[ ChristmasHack! | My games ] :::: One CSS to style them all, One Javascript to script them, / One HTML to bring them all and in the browser bind them / In the Land of Fantasy where Standards mean something.

CIRCLE
Member #5,301
December 2004

Thanks that was what was needed

digit_count = (int)log10(score) + 1;

digit_value = (int)(score / pow(10, 1)) % 10;

textprintf_ex(active_page, font, 0, 0, makecol(255, 255,  255), -1, 
"Digits in score %i Digit Value %i", digit_count, digit_value);

Only thing is if score is 0 digit_count returns a large negitive number but that is easy to get around with a simple check if the number is not positive just post a 0 score.

Thanks a lot.

Well at the very beginning of the game the score is going to be 0 so that value will be returned until the score is >0

Finished Result:

digit_count = (int)log10(score + totalscore) + 1;
    for (scoredigit = 0; digit_count > scoredigit; scoredigit++)
    {
        draw_sprite(active_page, numbers[(int)((score + totalscore) / pow(10, scoredigit)) % 10], 275 - scoredigit *17, 15);
    }
    digit_count = (int)log10(lives) + 1;
    if ((int)log10(lives) + 1 < 0)
        draw_sprite(active_page, numbers[0], 275, 15);
    for (livesdigit = 0; (int)log10(lives) + 1 > livesdigit; livesdigit++)
    {
        draw_sprite(active_page, numbers[(int)(lives / pow(10, livesdigit)) % 10], 100 - livesdigit *17, 15);
    }

I have one last problem with this though if score + totalscore = 1000 it passes 0000 and if score + totalscore = 2000 it passes 1000 till 10000 it passes 19000 for some reason the 4th digit doesn't display properly until the score = 1001 and so on. I don't see where the problem is any one else?

Some where in here is the problem I just can't seem to isolate it.

digit_count = (int)log10(score + totalscore) + 1;
    for (scoredigit = 0; digit_count > scoredigit; scoredigit++)
    {
        draw_sprite(active_page, numbers[(int)((score + totalscore) / pow(10, scoredigit)) % 10], 275 - scoredigit *17, 15);
    }

-I edit a lot. Prepare thyself.

Matthew Leverton
Supreme Loser
January 1999
avatar

I wondered if you were doing something like this. It seems to me that you are reinventing the printf function:

myfont = load_font("font.bmp");
textprintf_right_ex(active_page, myfont, 275,15, -1, -1, "%d", score);

The above assumes a multi-color font. Replace the first -1 by the color if your font is a solid color.

If you really must do your own thing here (and I doubt it), I'd stick with the sprintf way because it's easier to read:

char score_str[100];
sprintf(score_str, "%i", score);

int x = 275, y = 15;
for (int i=strlen(score_str)-1; i>=0; --i)
{
  int digit_value = score_str<i> - '0';

  draw_sprite(active_page, numbers[digit_value], x, y);
  x-= 17;
}

piccolo
Member #3,163
January 2003
avatar

1//cant remember header file c++
2 
3 
4extern string NumberToString(int Number)
5{
6 ostringstream converter;
7 converter << Number;
8 return converter.str();
9}
10 
11int num= 346;
12 
13if(NumberToString(num)[0]=='0')
14{
15 
16}
17if(NumberToString(num)[0]=='1')
18{
19 
20}

Edit: wow i type slow 3 post came out of nowhere
Edit2: i think my way is better because you can get ohold of the 1st 2nd and nth numbers

Edit3:

Quote:

the 4th digit doesn't display properly until the score = 1001 and so on. I don't

i think your bug lie in the (int) casting

wow
-------------------------------
i am who you are not am i

CIRCLE
Member #5,301
December 2004

Quote:

i think your bug lie in the (int) casting

explaing please.

Whats odd is that if I

draw_sprite(active_page, numbers[(int)((score + totalscore) / pow(10, 3)) % 10], 275 - scoredigit *17, 15);

instead of...

draw_sprite(active_page, numbers[(int)((score + totalscore) / pow(10, scoredigit)) % 10], 275 - scoredigit *17, 15);

It shows the value as correct and if I use

textprintf_ex(screen, font, SCREEN_W/2 - (4*19) - scoredigit * 30, SCREEN_H/2, makecol(255,255,255), -1, "%i ", scoredigit);

it also shows the correct values but when I use the variables only the thousands place is messed up and only when the value is exact 1000,2000,10000 ect.

-I edit a lot. Prepare thyself.

Edgar Reynaldo
Member #8,592
May 2007
avatar

Hey Circle , this might help.

Until I decide to write my own function to convert integers into strings , I've been using Itoa

Link to usage at cplusplus.com
http://www.cplusplus.com/reference/clibrary/cstdlib/itoa.html

Example

1int score = 12345;
2char numberstring[50];
3for (x = 0 ; x < 50 ; x++) {numberstring[x] = '\0';}
4 
5itoa(score , numberstring , 10);
6 
7// Now "12345" is stored in numberstring
8// use strlen to find out it is 5 digits
9// then access the digit like this
10int score_length = strlen(numberstring);
11 
12// example if you want the hundreds digit this will access it
13numberstring[((score_length - 1) - 2)];
14 
15// If you are looking for the 10^x digit place this should do it
16numberstring[((score_length - 1) - x)];
17// x = 0 is ones place and so on.

Then if you wanted to convert the digit you found from numberstring use
atoi (in stdlib.h) to change it back to an integer.

Hope this was helpful.

CIRCLE
Member #5,301
December 2004

Ok BIG thanks for all the help from everyone you all are great.

Ended up with

itoa(score + totalscore, scorestring, 10);
    itoa(lives, livesstring, 10);
    int score_length = strlen(scorestring);
    int lives_length = strlen(livesstring);
    for (scoredigit = 0; scoredigit < score_length; scoredigit++)
    {
        draw_sprite(active_page, numbers[scorestring[((score_length - 1) - scoredigit)]- 48], 275 - scoredigit *17, 15);
        textprintf_ex(screen, font, SCREEN_W/2 - (4*19) - scoredigit * 30, SCREEN_H/2, makecol(255,255,255), -1, "%i ", scorestring[((score_length - 1) - scoredigit)]- 48);
    }
    for (livesdigit = 0; livesdigit < lives_length; livesdigit++)
    {
        draw_sprite(active_page, numbers[livesstring[((lives_length - 1) - livesdigit)]- 48], 100 - livesdigit *17, 15);
    }

Works fantastic now and the 4th digit errors are gone. Odd I am still using all the same variables. Besides digit_value and digit_count but they were just replaced with lives_length and score_length and either way still worked with the iota. I also decided to skip a lot of work and just subtract 48 from the itoa value to get the correct numbers I needed.

-I edit a lot. Prepare thyself.

gnolam
Member #2,030
March 2002
avatar

I suggest you use snprintf() instead of itoa(). itoa() is non-standard. Plus, you get some extra memory safety you wouldn't get otherwise.

[EDIT]

Quote:

textprintf_ex(screen, font, SCREEN_W/2 - (4*19) - scoredigit * 30, SCREEN_H/2, makecol(255,255,255), -1, "%i ", scorestring[((score_length - 1) - scoredigit)]- 48);

You're transforming the digit into ASCII, then transforming it into an integer, and then printing it (which will, again, transform it into ASCII). Just print it as a char instead.
textprintf_ex(screen, font, SCREEN_W/2 - (4*19) - scoredigit * 30, SCREEN_H/2, makecol(255,255,255), -1, "%c", scorestring[(score_length - 1) - scoredigit]);

And might I suggest you stop draw directly to the screen? Use a buffer of some kind.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

CIRCLE
Member #5,301
December 2004

the part that posts to the screen is my test line. It is removed when things are working correctly. every thing else uses buffers.

I am using bitmaps to place the numbers on the screen instead of dealing with fonts.

-I edit a lot. Prepare thyself.

HardTranceFan
Member #7,317
June 2006
avatar

You can have an allegro font and replace the digit bitmaps in that font with your own digit bitmaps. That would save you the hassle of rewriting the functionality (well, too late now :)), but it may also be faster.

--
"Shame your mind don't shine like your possessions do" - Faithless (I want more part 1)

Tobias Dammers
Member #2,604
August 2002
avatar

Quote:

I suggest you use snprintf()

Please, please, please, follow this advice.
And use qualifiers on the snprintf call. For example, if you want to display a score acrade-style, with a maximum of 8 digits, and leading zeroes, you'd do:

snprintf(buf, "%08.8i", score);

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

Ron Ofir
Member #2,357
May 2002
avatar

Quote:

itoa() is non-standard.

Nooo!! My whole world just collapsed... :'(

CIRCLE
Member #5,301
December 2004

Only one problem the snprintf makes no sence to me in

int snprintf (char *buffer, size_t n, const char *format,
              ...);

format. I was for some reason never able to completely understand those. How ever if you have a small example I seem to understand those easier.

1itoa(score + totalscore, scorestring, 10);
2 itoa(lives, livesstring, 10);
3 itoa(mouseh, mousehstring, 10);
4 int scorelength = strlen(scorestring);
5 int liveslength = strlen(livesstring);
6 int mousehlength = strlen(mousehstring);
7 for (mousehdigit = 0; mousehdigit < mousehlength; mousehdigit++)
8 {
9 stretch_sprite(activepage, numbers[mousehstring[((mousehlength - 1) - mousehdigit)] - 48], 500 - mousehdigit * 10, 12, 10, 10);
10 }
11 for (scoredigit = 0; scoredigit < scorelength; scoredigit++)
12 {
13 draw_sprite(activepage, numbers[scorestring[((scorelength - 1) - scoredigit)] - 48], 275 - scoredigit *17, 15);
14 }
15 for (livesdigit = 0; livesdigit < liveslength; livesdigit++)
16 {
17 draw_sprite(activepage, numbers[livesstring[((liveslength - 1) - livesdigit)] - 48], 100 - livesdigit *17, 15);
18 }

currently this is what I am using and it works. Maybe there is something else besides itoa that I can use and keep much this same code?

-I edit a lot. Prepare thyself.

LennyLen
Member #5,313
December 2004
avatar

Quote:

lease, please, please, follow this advice.
And use qualifiers on the snprintf call. For example, if you want to display a score acrade-style, with a maximum of 8 digits, and leading zeroes, you'd do:
snprintf(buf, "%08.8i", score);

You've missed a parameter there.

Quote:

I was for some reason never able to completely understand those. How ever if you have a small example I seem to understand those easier.

<snip code sample>

currently this is what I am using and it works. Maybe there is something else besides itoa that I can use and keep much this same code?

Replace the first two lines with:

snprintf(livestring, sizeof(livestring), "%d", score + totalscore);
snprintf(mousehstring, sizeof(mousehstring), "&d", mouseh);

The first parameter of snprintf() is the character array (string) you're writing to, the second parameter is the maximum number of characters to write (though, it will actually copy this ammount minus one characters, since it appends a null terminator). From there after, you write a format specifier, and supply additional variables, as you would to any of the printf() variants.

CIRCLE
Member #5,301
December 2004

LennyLen said:

The first parameter of snprintf() is the character array (string) you're writing to, the second parameter is the maximum number of characters to write (though, it will actually copy this ammount minus one characters, since it appends a null terminator). From there after, you write a format specifier, and supply additional variables, as you would to any of the printf() variants.

Now that I understand. ^^
But actually it would be

snprintf(livesstring, sizeof(livesstring), "%d", lives);
snprintf(mousehstring, sizeof(mousehstring), "%d", mouseh);
snprintf(scorestring, sizeof(scorestring), "%d", score);

works great and easier to understand. Thanks. Why is the mouseh given a &d instead of %d in your example and livesstring getting the value from score + totalscore. Although I like the mistakes. I think it gave me an error because my int wasn't given enough space to hold &mouseh. and when the score and lives went up at the same time that was just a given.

-I edit a lot. Prepare thyself.

LennyLen
Member #5,313
December 2004
avatar

Quote:

Why is the mouseh given a &d instead of %d in your example

Because it was 2am, and I'd been drinking for a couple of hours. ;) They should of course both be %d, as you figured out.

Quote:

and livesstring getting the value from score + totalscore.

Same as above.

Quote:

I think it gave me an error because my int wasn't given enough space to hold &mouseh.

There was no &mouseh in my example. The line I wrote should have just given you a warning about having too many format arguments.

CIRCLE
Member #5,301
December 2004

Well anyways it was tons of help. Thanks.

-I edit a lot. Prepare thyself.

Go to: