[solved]Atoi not working properly

Hi all,

I just started out with Arduino and I absolutely love it!
At the moment I’m working on a identification system which requires the user to enter a 6-number ID on a keypad, which will be displayed on a LCD.
This number has to be an unsigned int. To reach this, I use a char array to hold the individual numbers and then cast it using atoi().
The problem is: A totally different value is displayed!

So for example: I enter ‘123123’ on my keypad and I’d expect the LCD to show this number. Instead, it shows 57587.

I hope someone can help me, I’ve been stuck on this for a day now, and a lot of googling didn’t help :frowning:

Here’s the function:

void getStudentNr() {
  char digits[7];
  unsigned int id;

  mySerial.write(12); 
  mySerial.print("Enter your ID:  ");
  
  for (int i = 0; i < 6; i++) { // get the password
	  digits[i] = keypad.waitForKey(); 
	  mySerial.print(digits[i]);	
	  if(digits[i] == '*') { //the user pressed reset
		  mySerial.write(12); mySerial.print("Enter your ID:  ");
		  i = -1; 	       }    
  }

  digits[6] = '\0';

  id = (unsigned int)atoi(digits); // convert the char array to the pin (an int)

  delay(500);
  mySerial.write(12); 

  mySerial.print("Your id:   "); mySerial.print(id);
  delay(2000);
}

Thank you so much in advance! :slight_smile:

There are lots of things not working properly in that sketch, but "atoi" isn't one of them.

Hi,

Thanks for your reply. Could you give me a hint please? :)

It would be useful to post all your code.

Thanks again for your (fast!) response.
You can find the code below. It still contains some ugly stuff like global variables but I will get rid of those in a later stadium.
As you can see I also have a method called getPincode() which uses a short, this one works as it should. That’s why I’m guessing my problem has something to do with the size of the char array, but I can’t seem to figure out the exact problem…

#include <Keypad.h>
#include <SoftwareSerial.h>
#include <stdio.h>
#include <stdlib.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
  {'1','2','3', 'a'},
  {'4','5','6', 'b'},
  {'7','8','9', 'c'},
  {'*','0','#', 'd'}
};
byte rowPins[ROWS] = {0, 1, 2, 3}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {4, 5, 6, 7}; //connect to the column pinouts of the keypad
short pin; // the pincode
unsigned int id; // the student ID

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
SoftwareSerial mySerial = SoftwareSerial(255, A0);

void getPincode();
void getStudentNr();

void setup(){
  mySerial.begin(9600);
 
  for (int i = 2; i < 9; i++)  {
	  pinMode(i, INPUT);
	  digitalWrite(i, HIGH);   }

  pinMode(A0, OUTPUT);
  digitalWrite(A0, HIGH);

  delay(5);

  getStudentNr();

  getPincode();

  mySerial.write(12); mySerial.println("Identification   done");
}
  
void loop(){ // not necessary here
}

void getStudentNr() {
  char digits[7];

  mySerial.write(12); 
  mySerial.print("Enter your ID:  ");
  
  for (int i = 0; i < 6; i++) { // get the password
	  digits[i] = keypad.waitForKey(); 
	  mySerial.print(digits[i]);	
	  if(digits[i] == '*') { //the user pressed reset
		  mySerial.write(12); mySerial.print("Enter your ID:  ");
		  i = -1; 	       }    
  }

  digits[6] = '\0';

  id = (unsigned int)atoi(digits); // convert the char array to the id (an int)

  delay(500);
  mySerial.write(12); 

  mySerial.print("Your id:   "); mySerial.print(id);
  delay(2000);
}

void getPincode() {
  char digits[4];

  mySerial.write(12); 
  mySerial.print("Enter your pin: ");
  
  for (int i = 0; i < 4; i++) { // get the password
	  digits[i] = keypad.waitForKey(); 
	  mySerial.print(digits[i]);	
	  if(digits[i] == '*') { //the user pressed reset
		  i = -1; }			  }

  pin = atoi(digits); // convert the char array to the pin (a short)

  delay(500);
  mySerial.write(12); 

  mySerial.print("Your pincode:   "); mySerial.println(pin);
  delay(2000);
}

unsigned int has a max value of 65535. You simply produced an overflow. Use unsigned long, that has a much bigger range.

fairyglen: So for example: I enter '123123' on my keypad and I'd expect the LCD to show this number. Instead, it shows 57587.

I hope someone can help me, I've been stuck on this for a day now, and a lot of googling didn't help :(

Right, well atoi converts things to an int, right? And an int is -32767 to +32768.

So you are hardly going to fit 123123 into an int.

In fact 123123 is 0x1E0F3 (in hex).

Now since it only holds 2 bytes it will in fact be (truncated to) 0xE0F3.

Turn 0xE0F3 back into decimal and you have 57587.

Magically, almost, the number you see appears!

Oh, and atoi works properly.

Thank you so much for pointing me in the right direction, it's working now! I changed unsigned int to unsigned long as you said and of course used atol instead of atoi. Never ran in a problem like this before but I will definitely look into it earlier in future bugs. Thanks again!