Welcome, Guest. Please login or register.

Author Topic: C++ - convert string to array of ints  (Read 3862 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
C++ - convert string to array of ints
« on: September 01, 2007, 12:01:06 PM »
I need to convert a string, which is guaranteed to contain only numbers, to an array of ints. Or at least convert each digit from the string to an int so I can add it to an array. Here's what I was thinking of doing:

str="12345";
int nums = str.length();
for ( int i=0; i{
    n = atoi( str );
}


The effect should be that the for loops runs once for each digit in str (in this case five times) and sets n to the numerical value of str. However, this gives me an error "invalid conversion from `char' to `const char*' ". Is there any way to do this?

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: C++ - convert string to array of ints
« Reply #1 on: September 01, 2007, 12:16:43 PM »
Ah, the old gotchas :-D

In C(++) a C style string is simply an array of char (more precisely, a null terminated array). Consequently, for any given C style string, any indexed position is of type char, not the full string (const char*), which is what atoi() is expecting.

The same applies to the C++ string when you subscript with the [ ] operator - the individual characters themselves aren't regarded as strings in their own right. What's more, it's almost certain that string is wrapping a dynamically allocated array of char (ie a C style string) anyway.

Luckily for you, since char is basically a numeric type, you can do this instead:

n = str - '0';

Note carefully the single quotes around the character literal. As the ASCII character set contains 0-9 in a continuous block, this will convert any ASCII character from 0 - 9 to the corresponding integer value. No need for the library call at all.
int p; // A
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: C++ - convert string to array of ints
« Reply #2 on: September 01, 2007, 12:21:52 PM »
Thanks Karlos! I had actually already tried "int num=scorestr-'0';" but I missed the quotes around the 0 which is subtracted from the character. I thought you were subtracting zero to make it think it was an integer (because it was being used like one), when further reading reveals that you are subtracting the ASCII code '0' to get the value of the digit.


Here is the solution, where "scorestr" is a string containing the player's score:

CODE
for ( int i=0; i{
    int num=scorestr-'0';
    apply_surface( scorestartpos+(i*12), 10, font, screen, &fontClips[ num ] );
}

Thanks again

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: C++ - convert string to array of ints
« Reply #3 on: September 01, 2007, 12:30:11 PM »
You know, using a string to hold the score is probably something you could eliminate if your score is an integer type to start with:

Code: [Select]


int tempScore   = playerScore;
int scoreCursor = .... ; // starting at right hand side
int cursorStep  = 12;


while ( tempScore>0 )
{
  int digit  = tempScore%10; // next decimal digit
  tempScore  /= 10;
  apply_surface( scoreCursor, 10, font, screen, &fontClips[ digit ] );
  scoreCursor -= cursorStep;
}


Note, however, that this method will right align the output and won't zero fill the result, either. That would be easy to add though, just a loop afterwards that renders your "zero" character until you've emitted the required fixed length of digits overall.

-edit-

Actually the above assumes the score must be greater than zero to start with. A better version would be:

Code: [Select]


int tempScore   = playerScore;
int scoreCursor = .... ; // starting at right hand side
int cursorStep  = 12;


do {
  int digit  = tempScore%10; // next decimal digit
  tempScore  /= 10;
  apply_surface( scoreCursor, 10, font, screen, &fontClips[ digit ] );
  scoreCursor -= cursorStep;
} while (tempScore != 0);


This version should work with zero score.

It could probably even negative scores, though I'd need to check the side effects of the number rendering - you'd need to abs() the digit for sure and you'd have to render the minus sign yourself afterwards. But at least the scoreCursor would already be at the right position.
int p; // A
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: C++ - convert string to array of ints
« Reply #4 on: September 01, 2007, 12:44:22 PM »
Would that be significantly more efficient than converting it to a string, extracting each character and then converting the character back to an int?

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: C++ - convert string to array of ints
« Reply #5 on: September 01, 2007, 12:49:26 PM »
Almost certainly. However, depending on the specification of your machine to start with, who can say wether or not you'd notice?

The worst part of that code is the modulus and division, but your implementation's int to string conversion almost certainly has to do this too. This way, you avoid all the string handling that sits on top.

If you wanted to be really 1337, you could show your score in hex, then you can use >>4 instead of /10 and &F instead of %10, thereby saving those pesky cycles :lol:
int p; // A
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: C++ - convert string to array of ints
« Reply #6 on: September 01, 2007, 12:58:12 PM »
The target platform is the GP2X, so the code needs to be as efficient as possible. The GP2X doesn't handle floating point maths well (apparently) so a solution which avoids this might end up more efficient.

In any case, the routine to convert the integer score to a string and then to an array of ints only needs to be run when the score changes. Then all the main loop has to do is iterate through the array of ints and draw the corresponding numbers on the screen.

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: C++ - convert string to array of ints
« Reply #7 on: September 01, 2007, 01:05:35 PM »
Well, the method I presented is likely to be significantly faster than the string one, simply because you arent using strings, be they const char* or std::string so yo don't have any of their corresponding (hidden) overheads.

What I am saying is, the int to string conversion alone has to do something like that loop just presented just to turn the integer into a string of ASCII chars (it's likely to be even worse, since it probably has to add '0' to each one and do various other checks too).

All this loop depends on is the integer value of the score and you can apply the same "render on change only" strategy to that*

If you are coding for efficiency, never make the mistake of "least lines of source code" equates to "most efficient object code". It's often not true at all (unless you are coding in 1 line per instruction assembler anyway :lol:)


*caveat:

If you constantly have to redraw the score text and the score hasn't changed value then the string version has some merit in that it avoids parsing the int repeatedly. You can, however, have an array of the 'digit' values calculated in the loop method which can be used to redraw an unchanged score value even faster. This is basically the same then as iterating your string score, except you wouldnt need the -'0' per character.
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: C++ - convert string to array of ints
« Reply #8 on: September 01, 2007, 01:24:21 PM »
You might go for something like this:

Code: [Select]


int startCursor     = .... ; // right hand side
int cursorStep      = 12;    // on screen font spacing
int lastScoreLength = 0;
int scoreDigits[MAX_SCORE_DIGITS] = { 0 };
int oldPlayerScore  = 0;
int playerScore     = 0;

//....

if (oldPlayerScore!=playerScore) {
  // redraw with calculation
  int tempScore       = playerScore;
  int scoreCursor     = startCursor;
  int i = 0;

  do {
    int digit         = tempScore%10; // next decimal digit
    tempScore        /= 10;
    apply_surface( scoreCursor, 10, font, screen, &fontClips[ digit ] );
    scoreCursor      -= cursorStep;
    scoreDigits[i++]  = digit;
  } while (tempScore != 0);

  lastScoreLength     = 0;
  oldPlayerScore      = playerScore;

} else {
  // redraw without recalculation
  int scoreCursor     = startCursor;

  for (i=0; i<lastScoreLength; i++) {
    apply_surface( scoreCursor, 10, font, screen, &fontClips[ scoreDigits[i] ] );
    scoreCursor      -= cursorStep;  
  }
}

int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: C++ - convert string to array of ints
« Reply #9 on: September 01, 2007, 02:19:04 PM »
Damn you Mark, you're making me think of C/C++ and distracting me from so called "Web 2.0" development...

Pretty soon I'll be in danger of booting up a miggy.
int p; // A
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: C++ - convert string to array of ints
« Reply #10 on: September 01, 2007, 03:23:51 PM »
Quote
Karlos wrote:
Damn you Mark, you're making me think of C/C++ and distracting me from so called "Web 2.0" development...

You know it's got bad when C++ is a break from what you were doing before :lol:

Quote
Karlos wrote:
Pretty soon I'll be in danger of booting up a miggy.

God forbid! It's been a while since I did that too :-( Mind you, my new game (a port of GridWars to the GP2X) is written in C++/SDL, so I suppose I could port it to the Amiga.....

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: C++ - convert string to array of ints
« Reply #11 on: September 01, 2007, 04:58:55 PM »
Quote
You know it's got bad when C++ is a break from what you were doing before


I'm so busy at the moment that the happy days of coding C/C++/assembler on the amiga seems like a distant dream :-(

Of all the development work I've done, that was surely the most fun. Many times, I'd simply have an idea and I'd just sit down and code to see "what happens if we try this...". So many strange ideas, some of which were even useful :lol:

Never have the time now. Financial considerations have crushed all forms of creativity outside the defined constraints of whatever it is I'm working on for someone else :-(
int p; // A
 

Offline motorollinTopic starter

  • Hero Member
  • *****
  • Join Date: Nov 2005
  • Posts: 8669
    • Show only replies by motorollin
Re: C++ - convert string to array of ints
« Reply #12 on: September 01, 2007, 05:27:16 PM »
Quote
Karlos wrote:
Financial considerations have crushed all forms of creativity outside the defined constraints of whatever it is I'm working on for someone else :-(

You know I understand that after my thread on [not] making music. I was hoping to use my current sabbatical to write some music, but I need the new version of Reason to finish my new track. I don't want to move on to something else until I finish it in case I forget it :-) Hopefully I'll still have time to write it when it has been released - by which time I will have started my degree!

--
moto
Code: [Select]
10  IT\'S THE FINAL COUNTDOWN
20  FOR C = 1 TO 2
30     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NAAAA
40     DA-NA-NAAAA-NAAAA DA-NA-NA-NA-NA-NA-NAAAAA
50  NEXT C
60  NA-NA-NAAAA
70  NA-NA NA-NA-NA-NA-NAAAA NAAA-NAAAAAAAAAAA
80  GOTO 10