2012-01-30 31 views
8

Ho giocato con la programmazione per arduino ma oggi ho trovato un problema che non riesco a risolvere con la mia conoscenza C molto limitata. Ecco come va. Sto creando un'applicazione per PC che invia l'input seriale all'arduino (deviceID, command, commandparameters). Questo arduino trasmetterà il comando su RF ad altri arduino. a seconda del deviceID, il comando arduino funzionerà correttamente.Split String in String array

Per essere in grado di determinare il deviceID voglio dividere quella stringa sul ",". questo è il mio problema, so come farlo facilmente in java (anche se non si usa la funzione split standard), tuttavia in C è una storia completamente diversa.

Qualcuno di voi ragazzi può dirmi come farlo funzionare?

grazie

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

ho deciso che ho intenzione di usare la funzione strtok. Sto correndo in un altro problema ora. L'errore che è successo è

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

codice è come,

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]); 
    } 
} 
+1

Osservare la funzione 'strtok()'. –

+1

'strtok' è ammortizzato. usa 'strsep' invece – waspinator

+0

Per riferimento futuro, AFAIK' strtok() 'è _not_ deprecato (o ammortizzato). Il compilatore MS Visual C++ lo segnala come annuncio non sicuro e alternativo, come fa GNU/POSIX (diverse alternative però). Utilizzato correttamente e con consapevolezza delle sue carenze, funzionerà come previsto. – Toby

risposta

1

per l'allocazione dinamica della memoria, è necessario utilizzare malloc, vale a dire:

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

Sarà inoltre necessario il massimo lunghezza della corda

+1

Non è necessario necessariamente 'malloc()'. Se la stringa non cambierà tra l'operazione di divisione e la trasmissione dei dati, è perfettamente sicuro mantenere una serie di puntatori in varie posizioni nella stringa originale. È anche più veloce, utilizza meno memoria e lascia meno perdite di memoria. – japreiss

+0

Sì, potrebbe funzionare, dovresti semplicemente tenere traccia manuale della lunghezza/fine di ogni stringa per evitare sovrapposizioni, poiché non ci sarebbe un carattere di terminazione ''\ 0'' su nessuno tranne l'ultimo. – 3Pi

+0

Buon punto. Indovina che potrebbe non valerne la pena. – japreiss

0

Il modo C per dividere una stringa in base a un delimitatore è utilizzare strtok (o strtok_r). Vedere anche la domanda this.

+0

'strtok' è ammortizzato. usa 'strsep' invece – waspinator

+0

Deprecato da chi? Dieci minuti su google ha fatto solo la deprecazione in Microsoft Visual Studio C++. L'OP sta programmando un Arduino, che usa la propria versione di C, quindi se una funzione è deprecata in Windows è assolutamente irrilevante. – markgz

0

Penso che la tua idea sia un buon punto di partenza. Ecco un codice che uso (per analizzare le richieste HTTP GET REST con uno scudo Ethernet).

L'idea è di utilizzare un ciclo while e lastIndexOf di e memorizzare le stringhe in un array (ma si potrebbe fare qualcos'altro).

"request" è la stringa che si desidera analizzare (per me è stata chiamata richiesta perché .. era).

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 ! 

Ho usato questo codice con successo, ma io cosa loro è un problema di codifica quando provo a stampare params [x] ... io sono Alos un principiante in modo che io non padroneggiare caratteri vs stringa. ..

Spero che aiuti.

28

Questa è una vecchia questione, ma ho creato un certo pezzo di codice che può aiutare:

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

Questa funzione restituisce una singola stringa separati da un carattere predefinito a un determinato indice. Ad esempio:

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

In caso di stampa 'è'. Puoi anche provare con l'indice 0 restituendo 'hi' o cercando con sicurezza l'indice 5 restituendo 'test'.

Spero che questo aiuto!

+2

Sono stato alla ricerca di ore per trovare il modo più semplice per farlo ... il tuo è di gran lunga il più semplice –

+0

Thx! Sono contento che aiuti qualcuno! ;) –

+0

Questa è una bella funzione. Ci sono molte persone che chiedono una soluzione come questa. –

-1
int sa[4], r=0, t=0; 
String oneLine = "aa;bb;cc;dd;"; 

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

// sa[0] = aa sa[1] = bb sa[2] = cc sa[3] = dd 
+1

Benvenuti in SO. Si prega di omettere le sole risposte del codice fornendo alcuni contesto e spiegazione. Vedi http://stackoverflow.com/help/how-to-answer –