0

I am trying to read a string of 9 characters into 9 integer values, to be stored in an array (for now I store them in 9 separate ints, will put them in the array once they read in OK). General approach i took: con the string, split it into 9 character values, convert (atoi) each into an integer and store as 9 ints, put the ints into the array. What is strange is, while the single values get split into the single characters with no problems, atop somehow "sees" the other neighboring values (not contained in that character at all!) and converts them backwards.

sample code:

countrows = 1;
countcols = 1;
cout << endl << "Enter values for boxes in row " << countrows << ", enter 0 for open boxes (enter 9 numbers, with no spaces or delimiters): ";
string inputline;
cin >> inputline;
char col1, col2, col3, col4, col5, col6, col7, col8, col9;
int int1, int2, int3, int4, int5, int6, int7, int8, int9;
col1 = inputline[0];
col2 = inputline[1];
col3 = inputline[2];
col4 = inputline[3];
col5 = inputline[4];
col6 = inputline[5];
col7 = inputline[6];
col8 = inputline[7];
col9 = inputline[8];
int1 = atoi(&col1);
int2 = atoi(&col2);
int3 = atoi(&col3);
int4 = atoi(&col4);
int5 = atoi(&col5);
int6 = atoi(&col6);
int7 = atoi(&col7);
int8 = atoi(&col8);
int9 = atoi(&col9);
cout << "inputline: " << inputline << endl;
cout << "col1: " << col1 << " col2: " << col2 << " col3: " << col3 << endl; //debug line
cout << "int1: " << int1 << " int2: " << int2 << " int3: " << int3 << endl; //debug line

the result of this is:

Enter values for boxes in row 1, enter 0 for open boxes (enter 9 numbers, with no spaces or delimiters): 456123789 inputline: 456123789 col1: 4 col2: 5 col3: 6 int1: 4 int2: 54 int3: 654

why does int contain 5 and int3 65 (should be int1: 4 int2: 5 int3: 6)

user2333388
  • 25
  • 1
  • 1
  • 5

1 Answers1

3

atoi is used for converting NULL-terminated strings (char*), and not characters into integer. Your col1, col2, are not NULL terminated strings, and the atoi will read the memory until it gets to the NULL value (which will end the string).

If you want to change ASCII digits into numbers, you could use simple math:

int1 = col1 - '0';

col1: 4 col2: 5 col3: 6 int1: 4 int2: 54 int3: 654

All these values are stored on stack. Let's assume that stack is currently empty (it isn't, there are other locals, return address, and such things), and that top element is 0:

 STACK
 ----------
 0           <- top

Now, your col1, col2, col3 are placed on the stack, as you declare them:

 STACK
 ----------
 0
 col1
 col2
 col3

And, once you assing them values, you will get following picture:

 STACK
 ----------
 0
 '4'
 '5'
 '6'

When you call atoi(col1) it will read '4', and then, 0, which will terminate string, and it will parse only ASCII '4'. When you call atoi(col2), it will read '5', '4', and then 0, so input string will be "54" so it will parse exactly that. Similar will hapen for all other col variables.

Note that there is nothing magical about reading stack elements in the reverse order - actually, you are reading memory in the direct order - because on my (and probably yours) machine stack is growing downward. On some machines this would not be the case (check this link for more details), and you would get 456... for col1 or probably just zero (atoi will return zero if you pass non-number string as the argument).

Community
  • 1
  • 1
Nemanja Boric
  • 21,627
  • 6
  • 67
  • 91
  • isn't a C-string just a character array, and a character is a character array of size 1? – user2333388 Apr 29 '13 at 19:21
  • 1
    No, C-string is a character array which is ended with a 0 (NULL) element. Somehow C needs to know how long string is, doesn't it? – Nemanja Boric Apr 29 '13 at 19:22
  • And character is not a character array. It is just a primitive type. – Nemanja Boric Apr 29 '13 at 19:23
  • ah ok, now it makes sense what happened. Using the character math worked, thanks! – user2333388 Apr 29 '13 at 19:39
  • 1
    Every object can be treated as an array of size 1. But of course there's no terminator included. – Ben Voigt Apr 29 '13 at 19:50
  • @BenVoigt, and every object can be treated as an array of any size right? :). – Nemanja Boric Apr 29 '13 at 19:53
  • @NemanjaBoric: No, doing so leads to unsafely-derived pointers and undefined behavior. – Ben Voigt Apr 29 '13 at 20:04
  • The Standard says "For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type." were *these operators* are pointer arithmetic which includes array subscripting. – Ben Voigt Apr 29 '13 at 20:06
  • @BenVoigt, well, that makes your comment "Every pointer to any object can be treated as an array of size 1", doesn't it? – Nemanja Boric Apr 29 '13 at 20:15
  • @NemanjaBoric: Basically, but you've now unbalanced the statement by adding the word "pointer" to only half of it. – Ben Voigt Apr 29 '13 at 20:19