17

How do i convert a string into a int? here is my code:

   pragma solidity ^0.4.6;

contract MyContract {
    string public a;
    /* Constructor */
    function MyContract() {
        a = "0.12312317314571638713891378174163782169246891247193811231231731";
    }

    function bytesToUInt(uint v) constant returns (uint ret) {
    if (v == 0) {
        ret = 0;
    }
    else {
        while (v > 0) {
            ret = uint(uint(ret) / (2 ** 8));
            ret |= uint(((v % 10) + 48) * 2 ** (8 * 31));
            v /= 10;
        }
    }
    return ret;
}

    function get() constant returns(string){
        return a;
    }
}
BokkyPooBah
  • 40,274
  • 14
  • 123
  • 193
Fadil
  • 171
  • 1
  • 1
  • 3

7 Answers7

10

Note that floating point numbers are not supported in Solidity and the Ethereum Virtual Machine at the moment.

While your question is asking about converting a string to an int, your sample code refers to uint rather than int, so I'll provide the solution to convert a string to a uint.

Following is a solution to convert a non-floating point number from a string to a uint (which is a uint256). I've added the solution to this question to my solution to Solidity concatenate uint into a string?:

pragma solidity ^0.4.4;

contract TestIntToString {

    string public uintToStringResult;
    string public appendUintToStringResult;
    uint public stringToUintResult;

    function TestIntToString() {
        uintToStringResult = uintToString(12345678901234567890);
        appendUintToStringResult = appendUintToString("My integer is: ", 1234567890);
        stringToUintResult = stringToUint("12312317314571638713891378174163782169246891247193811231231731");
    }

    function uintToString(uint v) constant returns (string str) {
        uint maxlength = 100;
        bytes memory reversed = new bytes(maxlength);
        uint i = 0;
        while (v != 0) {
            uint remainder = v % 10;
            v = v / 10;
            reversed[i++] = byte(48 + remainder);
        }
        bytes memory s = new bytes(i + 1);
        for (uint j = 0; j <= i; j++) {
            s[j] = reversed[i - j];
        }
        str = string(s);
    }

    function appendUintToString(string inStr, uint v) constant returns (string str) {
        uint maxlength = 100;
        bytes memory reversed = new bytes(maxlength);
        uint i = 0;
        while (v != 0) {
            uint remainder = v % 10;
            v = v / 10;
            reversed[i++] = byte(48 + remainder);
        }
        bytes memory inStrb = bytes(inStr);
        bytes memory s = new bytes(inStrb.length + i + 1);
        uint j;
        for (j = 0; j < inStrb.length; j++) {
            s[j] = inStrb[j];
        }
        for (j = 0; j <= i; j++) {
            s[j + inStrb.length] = reversed[i - j];
        }
        str = string(s);
    }

    function stringToUint(string s) constant returns (uint result) {
        bytes memory b = bytes(s);
        uint i;
        result = 0;
        for (i = 0; i < b.length; i++) {
            uint c = uint(b[i]);
            if (c >= 48 && c <= 57) {
                result = result * 10 + (c - 48);
            }
        }
    }
}

And here's the Browser Solidity screenshot showing the solution works:

enter image description here

BokkyPooBah
  • 40,274
  • 14
  • 123
  • 193
  • When converting a string to uInt, uint c = uint(b[i]); should be inside the if conditional, in case someone tries to pass a non-integer as an argument. The if should test the b[i]. – Jossie Calderon Jun 15 '17 at 08:12
  • Also, in uInt to string, bytes memory s = new bytes(i + 1); is incorrect. Instead, bytes memory s = new bytes(i); with reversed[i - j - 1] is correct. – Jossie Calderon Jun 15 '17 at 09:08
  • Lastly, your code fails because the docs say Index access: If x is of type bytesI, then x[k] for 0 <= k < I returns the k th byte (read-only). So you cannot overwrite a byte array. DO NOT use this code. – Jossie Calderon Jun 15 '17 at 11:10
  • Thanks for reviewing and providing an alternative solution. – BokkyPooBah Jun 15 '17 at 17:35
6

Some of BokkyPooBah's code is incorrect.

Here are the functions to convert uInt to string, and vice versa, along with my comments:

function stringToUint(string s) constant returns (uint) {
    bytes memory b = bytes(s);
    uint result = 0;
    for (uint i = 0; i < b.length; i++) { // c = b[i] was not needed
        if (b[i] >= 48 && b[i] <= 57) {
            result = result * 10 + (uint(b[i]) - 48); // bytes and int are not compatible with the operator -.
        }
    }
    return result; // this was missing
}

function uintToString(uint v) constant returns (string) {
    uint maxlength = 100;
    bytes memory reversed = new bytes(maxlength);
    uint i = 0;
    while (v != 0) {
        uint remainder = v % 10;
        v = v / 10;
        reversed[i++] = byte(48 + remainder);
    }
    bytes memory s = new bytes(i); // i + 1 is inefficient
    for (uint j = 0; j < i; j++) {
        s[j] = reversed[i - j - 1]; // to avoid the off-by-one error
    }
    string memory str = string(s);  // memory isn't implicitly convertible to storage
    return str;
}
Jossie Calderon
  • 792
  • 1
  • 8
  • 14
4

For Solidity 0.8.6

function stringToUint(string memory s) public pure returns (uint) {
        bytes memory b = bytes(s);
        uint result = 0;
        for (uint256 i = 0; i < b.length; i++) {
            uint256 c = uint256(uint8(b[i]));
            if (c >= 48 && c <= 57) {
                result = result * 10 + (c - 48);
            }
        }
        return result;
    }
BonisTech
  • 664
  • 5
  • 17
2

Someone posted the way the Oraclize library converts a string to uint here: http://remebit.com/converting-strings-to-integers-in-solidity/

There is a parseInt() function in the base Oraclize API Contract.

willjgriff
  • 1,658
  • 8
  • 13
  • Is using oraclize recommended in 2018? – Mittenchops Nov 14 '18 at 20:55
  • Copying this function from the Oraclize contract doesn't mean you're relying on Oraclize so I don't believe it matters. On the topic of whether or not Oraclize is recommended, this is probably best asked as an independent question. – willjgriff Nov 15 '18 at 12:02
1

library ConvertStringToUint {

function stringToUint(string _amount) internal constant returns (uint result) {
    bytes memory b = bytes(_amount);
    uint i;
    uint counterBeforeDot;
    uint counterAfterDot;
    result = 0;
    uint totNum = b.length;
    totNum--;
    bool hasDot = false;

    for (i = 0; i < b.length; i++) {
        uint c = uint(b[i]);

        if (c >= 48 && c <= 57) {
            result = result * 10 + (c - 48);
            counterBeforeDot ++;
            totNum--;
        }

        if(c == 46){
            hasDot = true;
            break;
        }
    }

    if(hasDot) {
        for (uint j = counterBeforeDot + 1; j < 18; j++) {
            uint m = uint(b[j]);

            if (m >= 48 && m <= 57) {
                result = result * 10 + (m - 48);
                counterAfterDot ++;
                totNum--;
            }

            if(totNum == 0){
                break;
            }
        }
    }
     if(counterAfterDot < 18){
         uint addNum = 18 - counterAfterDot;
         uint multuply = 10 ** addNum;
         return result = result * multuply;
     }

     return result;
}

}

0

Oraclize API has parseInt(): https://github.com/oraclize/ethereum-api/blob/master/lib-experimental/oraclizeAPI.lib.sol.

Denis Glotov
  • 131
  • 3
0

I've written better code to handle bytes convert with offset and length. The good point is, It's keep bytes order.

/**
* Convert bytes to uint
* @param _data bytes Byte array
* @param _offset uint256 Position to convert 
* @param _length uint256 Data length
*/
function toUint(bytes _data, uint256 _offset, uint256 _length)
internal pure
returns(uint256 _result) {
    require(_offset >= 0);
    require(_length > 0);
    require((_offset + _length) <= _data.length);
    uint256 _segment = _offset + _length;
    uint256 count = 0;
    for (uint256 i = _segment; i > _offset ; i--) {
        _result |= uint256(_data[i-1]) << ((count++)*8);
    }
}