2012-01-30 57 views
8

He estado jugando con la programación de Arduino, pero hoy he encontrado un problema que no puedo resolver con mi muy limitado conocimiento de C. Así es como funciona. Estoy creando una aplicación para PC que envía una entrada en serie al arduino (deviceID, command, commandparameters). Este arduino transmitirá ese comando por RF a otros Arduino. dependiendo del deviceID, el Arduino correcto ejecutará el comando.Split String en String array

Para poder determinar el deviceID quiero dividir esa cadena en el ",". este es mi problema, sé cómo hacerlo fácilmente en Java (incluso al no usar la función de división estándar), sin embargo, en C es una historia totalmente diferente.

¿Alguno de ustedes me puede decir cómo hacerlo funcionar?

gracias

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

yo hemos decidido que voy a utilizar la función de strtok. Me encuentro con otro problema ahora. El error ocurrió es

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

Código es como,

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

Mire la función 'strtok()'. –

+1

'strtok' está depreciado. use 'strsep' en su lugar – waspinator

+0

Para referencia futura, AFAIK' strtok() 'no _ está en desuso (o depreciado). El compilador de MS Visual C++ lo marca como anuncios inseguros y alternativos, al igual que GNU/POSIX (aunque con alternativas diferentes). Utilizado correctamente y teniendo en cuenta sus deficiencias, funcionará según lo previsto. – Toby

Respuesta

1

para la asignación dinámica de la memoria, que tendrá que utilizar malloc, es decir:

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

Usted también necesita el máximo longitud de la cuerda.

+1

No necesariamente necesita 'malloc()'. Si la cadena no va a cambiar entre la operación de división y la transmisión de datos, es perfectamente seguro mantener un conjunto de punteros en varias posiciones en la cadena original. También es más rápido, usa menos memoria y deja menos pérdidas potenciales de memoria. – japreiss

+0

Sí, eso podría funcionar, solo tendrías que mantener un seguimiento manual de la longitud/final de cada cadena para evitar la superposición, ya que no habría un carácter de terminación ''\ 0'' en ninguna excepto en la última. – 3Pi

+0

Buen punto. Supongo que podría no valer la pena. – japreiss

0

La forma C de dividir una cadena basada en un delimitador es usar strtok (o strtok_r). Véase también this pregunta.

+0

'strtok' se deprecia. use 'strsep' en su lugar – waspinator

+0

¿Obsoleto por quién? Diez minutos buscando en Google solo revelaron la depreciación en Microsoft Visual Studio C++. El OP está programando un Arduino, que usa su propia versión de C, por lo que si una función está obsoleta en Windows es totalmente irrelevante. – markgz

0

Creo que su idea es un buen punto de partida. Aquí hay un código que uso (para analizar las solicitudes HTTP GET REST con un escudo Ethernet).

La idea es utilizar un ciclo while y lastIndexOf de y almacenar las cadenas en una matriz (pero podría hacer otra cosa).

"request" es la cadena que desea analizar (para mí se llamó solicitud porque ... 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 ! 

He utilizado este código con éxito, pero que su es un problema de codificación cuando intento imprimir params [x] ... yo soy un principiante alos así que no domino caracteres vs cadena. ..

Espero que ayude.

28

Ésta es una vieja pregunta, pero he creado alguna pieza de código que puede ayudar:

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

Esta función devuelve una sola cadena separada por un carácter predefinido a un índice dado. Por ejemplo:

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

Debe imprimir 'is'. También puede intentar con el índice 0 devolviendo 'hi' o intentando con seguridad el índice 5 devolviendo 'prueba'.

¡Espero que esta ayuda!

+2

He estado buscando por horas para encontrar la manera más simple de hacer esto ... el tuyo es de lejos el más fácil –

+0

Thx! ¡Me alegra que ayude a alguien! ;) –

+0

Esta es una buena función. Hay muchas personas pidiendo una solución como esta. –

-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

Bienvenido a SO. Por favor, omita las respuestas del código solo proporcionando algún contexto y explicación. Ver http://stackoverflow.com/help/how-to-answer –