Pages: 1 [2]   Go Down
Author Topic: indexOf does not work with a string value?  (Read 1138 times)
0 Members and 1 Guest are viewing this topic.
Rome, Italy
Offline Offline
Sr. Member
****
Karma: 20
Posts: 442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In the "time" case you were lucky to copy the remainder of the original string, starting from position 'a' and terminated by a null char. Not so with "page". As a quick and dirty solution you can initialize temp2 with zeroes, or append a null char after the copy, but if you don't take into account the length of the query string and the position of your keyword into it you are going to waste memory.
Logged

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 132
Posts: 6747
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Quote
You can use strstr() to locate a string within another string, and substr() to extract part of a string into another variable.
substr() is a C++ <string> method. ANy other options?
substr() is pretty easy to implement.  Something like:

Code:
void substr(char *source, uint8_t start, uint8_t end, char *dest, uint8_t maxlength)
{
  source += start;  // point to start of substring
  maxlength--;   // leave room for a null at the end.
  while ( (*dest++ = *source++) != 0) {
      if (--maxlength == 0)
         break;
   }
   *dest = 0;
}
//Call it like:
void myfunc () {
   char mysubstring[10];
   char netresponse[80] = ...;
   uint8_t start = strstr(netresponse, "&");
   uint8_t end = strstr(netresponse, "time");
     :
   substr(netresponse, start, end, mysubstring, sizeof(mysubstring));
     :

Quote
...regular expression...
http://regex.info/blog/2006-09-15/247   :-)
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 484
Posts: 18764
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
...regular expression...
http://regex.info/blog/2006-09-15/247   :-)

Well there are always PEGs but I find I really have to concentrate when using them, something I try not to do. smiley-wink

http://en.wikipedia.org/wiki/Parsing_expression_grammar
Logged


0
Offline Offline
Sr. Member
****
Karma: 8
Posts: 291
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Quote
You can use strstr() to locate a string within another string, and substr() to extract part of a string into another variable.
substr() is a C++ <string> method. ANy other options?
substr() is pretty easy to implement.  Something like:

Code:
void substr(char *source, uint8_t start, uint8_t end, char *dest, uint8_t maxlength)
{
  source += start;  // point to start of substring
  maxlength--;   // leave room for a null at the end.
  while ( (*dest++ = *source++) != 0) {
      if (--maxlength == 0)
         break;
   }
   *dest = 0;
}
//Call it like:
void myfunc () {
   char mysubstring[10];
   char netresponse[80] = ...;
   uint8_t start = strstr(netresponse, "&");
   uint8_t end = strstr(netresponse, "time");
     :
   substr(netresponse, start, end, mysubstring, sizeof(mysubstring));
     :

Quote
...regular expression...
http://regex.info/blog/2006-09-15/247   :-)


thanks for the code but strstr() requires a char * (it's a pointer) not uint8_t.

So in the end use the arduino String object or do what spatula suggests, whichever takes up less memory.

Code:
  char mystring[] = "GET /http://arduino/?page=1&time=20,40,30,2,14,2013&param2=54 HTTP/1.1";
    char temp1[40] = {0};
    char temp2[30] = {0};
    
    char *a = strstr(mystring, "time");
    strncpy(temp1, a, sizeof(temp1));
    
    char *b = strstr(temp1, "&");
    
    strncpy(temp2, a, b-temp1);
    
    printf("%s  :  %s ", temp1, temp2 );
« Last Edit: February 16, 2013, 01:57:09 pm by mistergreen » Logged

Rome, Italy
Offline Offline
Sr. Member
****
Karma: 20
Posts: 442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A quick example of the diy approach. This will locate the beginning of the query string:

Code:
char *find_start_of_query_string(char *s) {
  while (*s != '?' && *s != '\0') {
    s++;
  }
  return s;
}

and this will locate parameter names and values
Code:

void parse_query_parameters(char *s) {
  char *name_start_pos;
  char *value_start_pos;
  size_t name_length;
  size_t value_length;

  while(1) { // return only on '\0'

    name_start_pos = ++s;
    name_length = 0;
// look for the equals sign or end-of-string
    while (*s != '=' && *s != '\0') {
      name_length++;
      s++;
    }
    if (*s == '\0') {
      return;
    }

    value_start_pos = ++s;
    value_length = 0;
// look for ampersand, space or end-of-string
    while(*s != '&' && *s != ' ' && *s != '\0') {
      value_length++;
      s++;
    }
    if (value_length > 0) {
// assuming you have declared and initialized a time_value variable, e.g.
// char time_value[20] = {0};
      if (strncmp("time", name_start_pos, name_length)) {
        strncpy(time_value, value_start_pos, value_length);  
      }      
    }
    if (*s == '\0') {
      return;
    }
  }
}

A tangential issue is that you don't want people to mess around with your parameters (e.g., sending "time=999999,abc,-15" in the query string). So you will probably need to have some control in place before accepting the values.
Logged

0
Offline Offline
Tesla Member
***
Karma: 143
Posts: 9577
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Simple server code that uses indexOf and the memory saving F() macro for the static strings.

Code:
//zoomkat 5-1-12
//simple button GET for servo and pin 5
//for use with IDE 1.0
//open serial monitor to see what the arduino receives
//use ' instead of " in html
//address will look like http://192.168.1.102:84 when submited
//for use with W5100 based ethernet shields

#include <SPI.h>
#include <Ethernet.h>

#include <Servo.h>
Servo myservo;  // create servo object to control a servo

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // ip in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port

String readString;

//////////////////////

void setup(){

  pinMode(5, OUTPUT); //pin selected to control
  //start Ethernet
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();

  myservo.write(90); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo control
  //enable serial data print
  Serial.begin(9600);
  Serial.println("server servo/pin 5 test 1.0"); // so I can keep track of what is loaded
}

void loop(){
  // Create a client connection
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {

          //store characters to string
          readString += c;
          //Serial.print(c);
        }

        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging

          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: text/html");
          client.println();

          client.println(F("<HTML>"));
          client.println(F("<HEAD>"));
          client.println(F("<TITLE>Arduino GET test page</TITLE>"));
          client.println(F("</HEAD>"));
          client.println(F("<BODY>"));

          client.println(F("<H1>Zoomkat's simple Arduino button</H1>"));
          
          client.println(F("<a href='/?on'>ON</a>"));
          client.println(F("<a href='/?off'>OFF</a>"));

          client.println(F("</BODY>"));
          client.println(F("</HTML>"));
 
          delay(1);
          //stopping client
          client.stop();

          ///////////////////// control arduino pin
          if(readString.indexOf("on") >0)//checks for on
          {
            myservo.write(40);
            digitalWrite(5, HIGH);    // set pin 4 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            myservo.write(140);
            digitalWrite(5, LOW);    // set pin 4 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";

        }
      }
    }
  }
}

« Last Edit: February 16, 2013, 05:56:06 pm by zoomkat » Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 132
Posts: 6747
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
but strstr() requires a char * (it's a pointer) not uint8_t.
Ah.  I didn't notice  that it wasn't a direct replacement for indexOf...
Code:
   char mysubstring[80];
   char netresponse[80] = ...;
   char *substringStart = strstr(netresponse, "&"); // find start
   strcpy(mysubstring, substringStart);  // copy all stuff past start delimiter.
   substringStart = strstr(mysubstring, "time");  // find end
   *substringStart = 0;  // terminate the substring.
(Note that the storage reserved for the substring now needs to be larger, since it will temporarily hold the whole "second half" of the original string.)
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 484
Posts: 18764
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The regular expression library to which I alluded further up was designed so that the captures did not require any extra memory. Not, at least, unless you need to copy them somewhere.

However in a simple case like this, a state machine should be all that is required.
Logged


Pages: 1 [2]   Go Up
Jump to: