So konvertieren Sie Strings in Int

Wie konvertiere ich einen String in einen Int? hier ist mein 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;
    }
}

Antworten (7)

Beachten Sie, dass Gleitkommazahlen derzeit in Solidity und der Ethereum Virtual Machine nicht unterstützt werden.

Während Ihre Frage nach dem Konvertieren von a stringin ein fragt int, bezieht sich Ihr Beispielcode uinteher auf als auf int, also werde ich die Lösung zum Konvertieren einer Zeichenfolge in ein bereitstellen uint.

Im Folgenden finden Sie eine Lösung zum Konvertieren einer Nicht-Gleitkommazahl von einer Zeichenfolge in eine uint(die eine ist uint256). Ich habe die Lösung zu dieser Frage zu meiner Lösung zu Solidity concatenate uint into a string hinzugefügt? :

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);
            }
        }
    }
}

Und hier ist der Screenshot von Browser Solidity, der zeigt, wie die Lösung funktioniert:

Geben Sie hier die Bildbeschreibung ein

Beim Konvertieren eines Strings in uInt uint c = uint(b[i]);sollte innerhalb der ifBedingung stehen, falls jemand versucht, eine Nicht-Ganzzahl als Argument zu übergeben. Die ifsollten die testen b[i].
Auch in uInt to string bytes memory s = new bytes(i + 1);ist falsch. Stattdessen ist bytes memory s = new bytes(i);mit reversed[i - j - 1]richtig.
Schließlich schlägt Ihr Code fehl, weil die Dokumente sagen, dass Sie ein Array Index access: If x is of type bytesI, then x[k] for 0 <= k < I returns the k th byte (read-only).nicht überschreiben können . Verwenden Sie diesen Code NICHT.byte
Vielen Dank für die Überprüfung und Bereitstellung einer alternativen Lösung.

Ein Teil des Codes von BokkyPooBah ist falsch.

Hier sind die Funktionen zum Konvertieren von uInt in String und umgekehrt, zusammen mit meinen Kommentaren:

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;
}

Jemand hat hier gepostet, wie die Oraclize-Bibliothek einen String in uint konvertiert: http://remebit.com/converting-strings-to-integers-in-solidity/

Es gibt eine parseInt()-Funktion im Oraclize-Basis-API-Vertrag.

Wird die Verwendung von oraclize im Jahr 2018 empfohlen?
Das Kopieren dieser Funktion aus dem Oraclize-Vertrag bedeutet nicht, dass Sie sich auf Oraclize verlassen, daher glaube ich nicht, dass es darauf ankommt. Zum Thema, ob Oraclize empfehlenswert ist oder nicht, stellt man dies wohl am besten als eigenständige Frage.

Bibliothek 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;
}

}

Für Solidität 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;
    }

Ich habe besseren Code geschrieben, um byteskonvertieren mit offsetund zu handhaben length. Der gute Punkt ist, dass es die Reihenfolge der Bytes einhält.

/**
* 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);
    }
}
TypeError: Explizite Typkonvertierung von „bytes1“ nach „uint256“ nicht zulässig