String to Int

Hello all i got a question about a code that i´m stuck at.

I have a string array

String Data[10];

which contains values like "50" , "1", "10000", etc. ( Numbers only )

Then i have some Int Variables like

int size1;

I want something like

amount = Data[0];
size1 = Data[1];
size2 = Data[2];

but of course the prorgramm says that the string cant be converted to Int.
How can i do this ?

You can use atoi() to achive this.
There are many topics on the forum about this.

#include <stdlib.h>
...
amount = atoi(Data[0]);
...

If the numbers might be greater than 32768 you will need to use atol instead of atoi and store the result in long variables instead of int.

Use the undocumented ...

long String::toInt() {
  return atol(_buffer);
}

Note there is no float equivalent in the string lib.

but of course the prorgramm says that the string cant be converted to Int.

The compiler says that the String object can not be explicitly cast to an int. The String class has a toInt() method that CAN perform the conversion.

dc42:

#include <stdlib.h>

...
amount = atoi(Data[0]);
...




If the numbers might be greater than 32768 you will need to use atol instead of atoi and store the result in long variables instead of int.

Have you actually tried this? The atoi() function does not know what a String is, so it has no idea how to get the characters from it.

PaulS:

dc42:

#include <stdlib.h>

...
amount = atoi(Data[0]);
...




If the numbers might be greater than 32768 you will need to use atol instead of atoi and store the result in long variables instead of int.

Have you actually tried this? The atoi() function does not know what a String is, so it has no idea how to get the characters from it.

Thanks for pointing this out, I didn't notice he was using the String class and not a character array. Personally, I don't think classes that use dynamic memory allocation - such as String - have any place on a small embedded device with only 2k of RAM.

As the String class doesn't provide a method for accessing the raw character array (unlike the proper STL std::string class), nor any methods for parsing the contents, doing the conversion isn't so straightforward. Here's another attempt, compiled but otherwise untested, and with no handling of leading minus signs or any other non-numeric characters:

unsigned int toInt(const String& s)
{
   unsigned int val = 0;
   for (unsigned int i = 0; i < s.length(); ++i) {
     val = (10 * val) + (s.charAt(i) - '0');
  }
  return val;
}

...
amount = toInt(Data[0]);
...

As the String class doesn't provide a method for accessing the raw character array (unlike the proper STL std::string class), nor any methods for parsing the contents, doing the conversion isn't so straightforward.

I do believe you should have another peek at the documentation for the String class. It does provide a toCharArray() method to get at the underlying character data, and it provides methods to locate specific characters in the String (the basis for a parsing function).

PaulS:

As the String class doesn't provide a method for accessing the raw character array (unlike the proper STL std::string class), nor any methods for parsing the contents, doing the conversion isn't so straightforward.

I do believe you should have another peek at the documentation for the String class. It does provide a toCharArray() method to get at the underlying character data, and it provides methods to locate specific characters in the String (the basis for a parsing function).

I have looked not only at the documentation but also at the implementation. The toCharArray function requires you to allocate a buffer and therefore to know how long the string might be; that is why I rejected it. I did use one of the methods to access specific characters in the string in the solution I proposed.

The String class does provide it's own toInt() method, which is just a wrapper for atol(), so a simple:

amount = s.toInt();

provides the same result.

Though I do agree that the String class just shouldn't be used.

hey all , thanks for all your answers ! :slight_smile:

The String class has a toInt() method that CAN perform the conversion.

worked pretty well , thanks :wink:

The toCharArray function requires you to allocate a buffer and therefore to know how long the string might be

Knowing in advance how long the String is is not required. You can use the length function to know how big the array needs to be, then use malloc to allocate the space, extract the array, convert it to a long/int/float/whatever, then free the array.

The toInt() method makes this unnecessary, but something like this might be needed for floats/doubles.

Granted, the String class has a lot of overhead, but it does simplify, for a beginner, the process of getting a string from the Serial port.

Yes, I see now that the String class does provide a toInt method. The reason I didn't spot it before is that it is NOT documented in the reference page String() - Arduino Reference.

then use malloc to allocate the space

Using malloc in C/C++-based embedded systems other than during initialization is generally a bad idea. For the reasons, see Dynamic Memory Allocation in Critical Embedded Systems | David Crocker's Verification Blog.

Granted, the String class has a lot of overhead, but it does simplify, for a beginner, the process of getting a string from the Serial port.

Yes, it makes things easier for a beginner, unless/until he/she gets strange crashes some while after the program started, due to memory allocation calls failing.

Using malloc in C/C++-based embedded systems other than during initialization is generally a bad idea.

The String class makes extensive use of the malloc function, and seems to work pretty well. Relying on malloc succeeding, without checking that it did, is a bad idea, I agree.

But, in general, if a String object contains data that atoi() or atof() are capable of processing, the char array needed to hold a copy of the data is going to be pretty small. If malloc()'s use is a concern, statically allocate a 24 byte array, and only process the String object if it is less than 24 bytes long.

PaulS:
The String class makes extensive use of the malloc function, and seems to work pretty well.

The danger is that in a long-running system that uses the String class, the heap will get fragmented to the point where eventually a malloc fails and the system crashes - especially if the programmer is using lots of arrays or string literals as well so that RAM is tight. Using the String class comes at the price of not knowing whether the system will run reliably for long periods of time.

PaulS:
Relying on malloc succeeding, without checking that it did, is a bad idea, I agree.

In an embedded system, there is often little you can do if a malloc fails, other than stop or restart the system.

dc42:
The danger is that in a long-running system that uses the String class, the heap will get fragmented to the point where eventually a malloc fails

What seems to happen in Arduino is that the brkval and stack cross, causing the stack to get smashed, and or heap contents to get corrupted. Threads that wind up with the root cause being some OOM problem are the second most common theme on these forums -- next to the "I have homework, won't someone do it for me?" theme, which is by far the most common.

There was a thread in Suggestions for the Arduino Project regarding this. I would like to see a super-lightweight trap that can use blink codes on pin 13 to report errors, and have things like a malloc() failure or an instance where the millis() interrup notices that brkval and the stack have crossed should branch there. Maybe other run-time catastrophic errors could use it, and generate unique blink codes.

I would also like to see a heuristic in the IDE where it looks at the sum of the sizes of the data, bss and largest stack frame and mentions something if the sum exceeds 70% of available memory on the target board.

gardner:
I would also like to see a heuristic in the IDE where it looks at the sum of the sizes of the data, bss and largest stack frame and mentions something if the sum exceeds 70% of available memory on the target board.

I agree - it is crazy that the IDE reports the amount of flash memory used (which rarely approaches the maximum for the atmega328) when uploading a sketch, but not the RAM. AFAIK you can't even get a map file out without hacking the IDE.