[Ethereum] Solidity Split Comma-Delimited String into Individual words

blockchaingo-ethereumsoliditystring

Since Solidity functions can't accept String Arrays as arguments, I'm trying instead to pass in a long comma-delimited string, and then convert it to an array of strings on the fly.

I'm close – but the one line in the else statement towards the bottom – which I've pointed out in a comment – keeps crashing the contract.

Here's my code:

function splitString(string calldata stringToSplit) external pure returns(string memory) {
    // 1. Declare a string array to hold all the individual words I'm able to tease 
    //    out of the passed-in string: 
    string[] memory finalWordsArray;
    
    // 2. Declare a word-counter var to keep track of how many words I've gotten:
    uint256 wordCounter = 0;

    // 3. Convert and store the passed-in String argument into a Bytes Array so 
    //    I can iterate through it one character at a time:
    bytes memory stringAsBytesArray = bytes(stringToSplit);

    // 4. Declare another bytes array to contain all the characters that will be
    //    in my next full individual Word:
    string memory tmp = new string(stringAsBytesArray.length);
    bytes memory tempWord = bytes(tmp);
    
    
    // 5. Iterate through the "stringAsBytesArray" one Char at a time:
    // ["Hello,here,we,are,today"]
    for(uint i = 0; i < stringAsBytesArray.length; i++) {
        // if current char is NOT a comma, append it to my "tempWord":
        if (stringAsBytesArray[i] != ",") {
            tempWord[i] = stringAsBytesArray[i];
        }
        else {
            // We found a Comma, which means we've reached the end of a word. So 
            // let's convert our "tempWord" from a bytes Array to a String:
            string memory newWord = string(tempWord);
            
            // And then add that word to our "finalWordsArray":  
            // -->this next line causes a crash!
            // finalWordsArray[wordCounter] = newWord;
            
            // Iterate our wordCounter:
             wordCounter++;
             
            // And reset/blank-out our "tempWord" for the next go-around:
            tempWord = bytes(tmp);
            

            // This next statement DOES work: it returns the first word it
            // found before hitting that first comma. I put this in just to
            // see that I am getting at least SOMETHING out of this:
            return newWord;
        }
    }

    return "no Commas found!!!";

    // return string(finalWordsArray[2]);
}

Best Answer

Since Solidity functions can't accept String Arrays as arguments

This technically doesn't answer your question, but if you enable ABIEncoderV2 you can simply pass a string array to a function, rather than trying to split it yourself. This is likely a lot more efficient with regards to gas usage.

For example:

pragma solidity ^0.7.4;
pragma experimental ABIEncoderV2;

contract Foo {
  function bar (string[] calldata baz) public {
    // do something with `baz` here 
  }
}
Related Topic