简体   繁体   中英

Split String into String array

I have been playing around with programming for arduino but today i've come across a problem that i can't solve with my very limited C knowledge. Here's how it goes. I'm creating a pc application that sends serial input to the arduino (deviceID, command, commandparameters). This arduino will transmit that command over RF to other arduino's. depending on the deviceID the correct arduino will perform the command.

To be able to determine the deviceID i want to split that string on the ",". this is my problem, i know how to do this easily in java (even by not using the standard split function), however in C it's a totally different story.

Can any of you guys tell me how to get this working?

thanks

/*
  Serial Event example

 When new serial data arrives, this sketch adds it to a String.
 When a newline is received, the loop prints the string and 
 clears it.

 A good test for this is to try it with a GPS receiver 
 that sends out NMEA 0183 sentences. 

 Created 9 May 2011
 by Tom Igoe

 This example code is in the public domain.

 http://www.arduino.cc/en/Tutorial/SerialEvent

 */

String inputString;         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete
String[] receivedData;

void setup() {
    // initialize serial:
    Serial.begin(9600);
    // reserve 200 bytes for the inputString:
    inputString.reserve(200);
}

void loop() {
    // print the string when a newline arrives:
    if (stringComplete) {
        Serial.println(inputString); 
        // clear the string:
        inputString = "";
        stringComplete = false;
    }
}

/*
  SerialEvent occurs whenever a new data comes in the
 hardware serial RX.  This routine is run between each
 time loop() runs, so using delay inside loop can delay
 response.  Multiple bytes of data may be available.
 */
void serialEvent() {
    while (Serial.available()) {
        // get the new byte:
        char inChar = (char)Serial.read(); 
        if (inChar == '\n') {
            stringComplete = true;
        } 
        // add it to the inputString:
        if(stringComplete == false) {
            inputString += inChar;
        }
        // if the incoming character is a newline, set a flag
        // so the main loop can do something about it:
    }
}

String[] splitCommand(String text, char splitChar) {
    int splitCount = countSplitCharacters(text, splitChar);
    String returnValue[splitCount];
    int index = -1;
    int index2;

    for(int i = 0; i < splitCount - 1; i++) {
        index = text.indexOf(splitChar, index + 1);
        index2 = text.indexOf(splitChar, index + 1);

        if(index2 < 0) index2 = text.length() - 1;
        returnValue[i] = text.substring(index, index2);
    }

    return returnValue;
}

int countSplitCharacters(String text, char splitChar) {
    int returnValue = 0;
    int index = -1;

    while (index > -1) {
        index = text.indexOf(splitChar, index + 1);

        if(index > -1) returnValue+=1;
    }

    return returnValue;
} 

I have decided I'm going to use the strtok function. I'm running into another problem now. The error happened is

SerialEvent.cpp: In function 'void splitCommand(String, char)':

SerialEvent:68: error: cannot convert 'String' to 'char*' for argument '1' to 'char* strtok(char*, const char*)'

SerialEvent:68: error: 'null' was not declared in this scope

Code is like,

String inputString;         // a string to hold incoming data

void splitCommand(String text, char splitChar) {
    String temp;
    int index = -1;
    int index2;

    for(temp = strtok(text, splitChar); temp; temp = strtok(null, splitChar)) {
        Serial.println(temp);
    }

    for(int i = 0; i < 3; i++) {
        Serial.println(command[i]);
    }
}

This is an old question, but i have created some piece of code that may help:

 String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

This function returns a single string separated by a predefined character at a given index. For example:

String split = "hi this is a split test";
String word3 = getValue(split, ' ', 2);
Serial.println(word3);

Should print 'is'. You also can try with index 0 returning 'hi' or safely trying index 5 returning 'test'.

Hope this help!

Implementation:

int sa[4], r=0, t=0;
String oneLine = "123;456;789;999;";

for (int i=0; i < oneLine.length(); i++)
{ 
 if(oneLine.charAt(i) == ';') 
  { 
    sa[t] = oneLine.substring(r, i).toInt(); 
    r=(i+1); 
    t++; 
  }
}

Result:

    // sa[0] = 123  
    // sa[1] = 456  
    // sa[2] = 789  
    // sa[3] = 999

I think your idea is a good start point. Here is a code that i use (to parse HTTP GET REST requests with an Ethernet shield).

The idea is to use a while loop and lastIndexOf of and store the strings into an array (but your could do something else).

"request" is the string you want to parse (for me it was called request because.. it was).

    int goOn = 1;
    int count = -1;
    int pos1;
    int pos2 = request.length();

    while( goOn == 1 ) {
        pos1 = request.lastIndexOf("/", pos2);
        pos2 = request.lastIndexOf("/", pos1 - 1);

        if( pos2 <= 0 ) goOn = 0;

        String tmp = request.substring(pos2 + 1, pos1);

        count++;
        params[count] = tmp;

        // Serial.println( params[count] );

        if( goOn != 1) break;
    }
    // At the end you can know how many items the array will have: count + 1 !

I have used this code successfully, but i thing their is an encoding problem when i try to print params[x]... i'm alos a beginner so i don't master chars vs string...

Hope it helps.

I believe this is the most straight forward and quickest way:

String strings[10]; // Max amount of strings anticipated

void setup() {
  Serial.begin(9600);
  
  int count = split("L,-1,0,1023,0", ',');
  for (int j = 0; j < count; ++j)
  {
    if (strings[j].length() > 0)
      Serial.println(strings[j]);
  }
}

void loop() {
  delay(1000);
}

// string: string to parse
// c: delimiter
// returns number of items parsed
int split(String string, char c)
{
  String data = "";
  int bufferIndex = 0;

  for (int i = 0; i < string.length(); ++i)
  {
    char c = string[i];
    
    if (c != ',')
    {
      data += c;
    }
    else
    {
      data += '\0';
      strings[bufferIndex++] = data;
      data = "";
    }
  }

  return bufferIndex;
}

For dynamic allocation of memory, you will need to use malloc, ie:

String returnvalue[splitcount];
for(int i=0; i< splitcount; i++)
{
    String returnvalue[i] = malloc(maxsizeofstring * sizeof(char));
}

You will also need the maximum string length.

The C way to split a string based on a delimiter is to use strtok (or strtok_r ). See also this question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM