views:

1319

answers:

7

I have a string of digits, e.g. "123456789", and I need to extract each one of them to use them in a calculation. I can of course access each char by index, but how do I convert it into an int?

I've looked into atoi(), but it takes a string as argument. Hence I must convert each char into a string and then call atoi on it. Is there a better way?

+21  A: 

If you're not worried about encodings (and as this sounds like homework I doubt you are) you can utilise the fact that the character encodings for digits in ascii are all in order from 48 (for '0') to 57 (for '9').

Therefore, the integer value for any digit is the digit less 48 or, expressed in code (and you don't even need to know that '0' is 48, also you can do arithmetic with chars, there just really small ints under the covers). .

char c = '1';
int i = c - '0'; // i is now equal to 1, not '1'

Hope this helps,

EDIT:

Me saying "If you're not worried about encodings" can (and probably should) be interpeted as "I hope to hell you are not worried about encodings, because I don't know enough about them, and I can only be sure about how decimal digits are represented in AscII".

Apologies if this has caused any confusion.

Binary Worrier
This is an interesting approach. I never thought about doing it that way. Learn something new every day I suppose.
Matthew Brubaker
Since this does sound like a homework question, I'm glad you did not give more details than that!
tristan
@tristan: Indeed, I don't mind "helping", but I will not answer those "plez send me the codz" questions.
Binary Worrier
Is there any encoding in which '9'-'0' != 9 ? I'm not even sure if such an encoding would be allowed per ISO C++.
MSalters
This is a real app, not homework :)
jonsb
Oops, it's sounds like part of an assignment we were given back in the day. Sorry mate :( P.S. Thanks for selecting this answer :)
Binary Worrier
On encodings and the order of digits, I asked this question http://stackoverflow.com/questions/782373/are-digits-represented-in-sequence-in-all-text-encodings. The short answer is "Any encoding based on Ascii or EBCDIC, yes" (which means 99.9% of encodings we'll meet in everyday life and the web). Also interestingly the c/c++ standards seem to state that they only support encodings where the digits are ordered.
Binary Worrier
Is there any encoding where it does not hold '0' < '1' < '2' < '3' It would be at least a very very strange decision
Friedrich
+1  A: 

If you are worried about encoding, you can always use a switch statement.

Just be careful with the format you keep those large numbers in. The maximum size for an integer in some systems is as low as 65,535 (32,767 signed). Other systems, you've got 2,147,483,647 (or 4,294,967,295 unsigned)

How can a simple switch-statement help with different encodings?
gimpf
Because unicode digits cover exactly 10 positions, and ascii digits cover exactly 10 positions.Am I missing something?
you don't need to be worried about encoding. even if the numbers are not from 48 to 58 - the numbers must all be adjacent in their encoding. so you can still subtract '0' from any digit and get correct results. i believe i read that in the standard
Johannes Schaub - litb
+3  A: 

Or you could use the "correct" method, similar to your original atoi approach, but with std::stringstream instead. That should work with chars as input as well as strings. (boost::lexical_cast is another option for a more convenient syntax)

(atoi is an old C function, and it's generally recommended to use the more flexible and typesafe C++ equivalents where possible. std::stringstream covers conversion to and from strings)

jalf
Nice one, my C++ is rusty and I thought there was a safer way but didn't have time to look.
Binary Worrier
A: 

Any problems with the following way of doing it?

int CharToInt(const char c)
{
    switch (c)
    {
    case '0':
     return 0;
    case '1':
     return 1;
    case '2':
     return 2;
    case '3':
     return 3;
    case '4':
     return 4;
    case '5':
     return 5;
    case '6':
     return 6;
    case '7':
     return 7;
    case '8':
     return 8;
    case '9':
     return 9;
    default:
     return 0;
    }
}
jonsb
None, except that it's a lot of duplicated code to do something fairly trivial. Binary Worrier's answer is a lot simpler as long as the input encoding is known, and allows this shortcut. My version is shorter too, and works no matter the encoding, but will be a bit slower.
jalf
A: 
#include<iostream>
#include<stdlib>
using namespace std;

viod main()
{
     char ch;
     int x;
     cin>>ch;
     x=char (ar[1]);
     cout<<x;
}
A: 

The answers provided are great as long as you only want to handle Arabic numerals, and are working in an encoding where those numerals are sequential, and in the same place as ASCII.

This is almost always the case.

If it isn't then you need a proper library to help you.

Let's start with ICU.

  1. First convert the byte-string to a unicode string. (Left as an exercise for the reader).
  2. Then use uchar.h to look at each character.
  3. if we the character is UBool u_isdigit (UChar32 c)
  4. then the value is int32_t u_charDigitValue ( UChar32 c )

Or maybe ICU has some function to do it for you - I haven't looked at it in detail.

Douglas Leeder
A: 

char a='5',b='7';

int c,d;

c=atoi(&a);

d=atoi(&b);

the above code does not work properly; when a is converted in to integer the value of 'c' become 5 but after the second execution the value of 'd' become 75.... plz give me its solution......

zari