web-dev-qa-db-fra.com

Scinder la chaîne en tableau

Je me suis amusé avec la programmation pour Arduino, mais aujourd’hui, j’ai rencontré un problème que je ne saurais résoudre avec ma connaissance très limitée du C. Voici comment cela se passe. Je crée une application PC qui envoie une entrée série à l’arduino (deviceID, command, commandparameters). Cet arduino transmettra cette commande sur RF à d'autres arduino. En fonction du deviceID, le bon arduino exécutera la commande.

Pour pouvoir déterminer le deviceID, je souhaite scinder cette chaîne sur le caractère ",". C'est mon problème, je sais comment le faire facilement en Java (même en n'utilisant pas la fonction split standard), cependant en C c'est une histoire totalement différente.

Est-ce que l'un de vous peut me dire comment faire fonctionner ça?

merci

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

J'ai décidé d'utiliser la fonction strtok. Je rencontre un autre problème maintenant. L'erreur s'est produite est

SerialEvent.cpp: Dans la fonction 'void splitCommand (String, char)': 

SerialEvent: 68: error: impossible de convertir 'String' en 'char *' pour l'argument '1' en 'char * strtok (char *, const char *)'

SerialEvent: 68: erreur: 'null' n'a pas été déclaré dans cette étendue

Le code est comme,

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]);
    }
}
10
NightWalker

C'est une vieille question, mais j'ai créé un morceau de code qui peut aider:

 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]) : "";
}

Cette fonction renvoie une seule chaîne séparée par un caractère prédéfini à un index donné. Par exemple:

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

Faut-il imprimer 'est'. Vous pouvez également essayer avec l'index 0 renvoyant «hi» ou en toute sécurité, l'index 5 renvoyant «test».

J'espère que cette aide!

30

La mise en oeuvre:

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

Résultat:

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

Je pense que votre idée est un bon point de départ. Voici un code que j'utilise (pour analyser les requêtes HTTP GET REST avec un bouclier Ethernet).

L'idée est d'utiliser une boucle while et lastIndexOf et de stocker les chaînes dans un tableau (mais vous pouvez faire autre chose).

"demande" est la chaîne que vous souhaitez analyser (pour moi, cela s'appelait demande parce que ... c'était).

    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 !

J'ai utilisé ce code avec succès, mais je pense que c'est un problème d'encodage lorsque j'essaie d'imprimer params [x] ... je suis un débutant, donc je ne maîtrise pas les caractères vs chaîne ...

J'espère que ça aide.

0
Romain Bruckert

Pour l'allocation dynamique de mémoire, vous devrez utiliser malloc, à savoir:

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

Vous aurez également besoin de la longueur maximale de la chaîne.

0
3Pi

La méthode C pour fractionner une chaîne en fonction d'un délimiteur consiste à utiliser strtok (ou strtok_r). Voir aussi this question.

0
markgz