Go Down

Topic: Do I need a special library for strcpy and strcat (Read 17011 times) previous topic - next topic

PeterH

Are those 'examples' actual values that you encountered when the problem occurred, or just values that you think are typical or noticed when the problem did not occur?

Sorry to harp on about this, but the symptoms suggest you may have an unterminated string and/or array overflow so it is quite important to know the actual precise values that cause the problem.

acboother

In your code

Code: [Select]
  gps.getPar(lon,lat,alt,time,vel);

what types are the parameters lon,lat,alt,time,vel? Char, float, char*, int or what?

PeterH


Try using snprintf


That would have the same effect as the existing code, and suffer from the same problems is any of the buffers overflow or are not correctly terminated.

nickgammon


Thank for all for your help,
but I do not undertand why it's so complicate to concatenate char variable. (I am a beginner as well :o)).

In resume , I have :
(x=a value that I may ignore..., may be it's the reason of my issue)
Code: [Select]
char coords[x];
char lat[15];
char lon[15]
char alt[15];
char vel[15];
char time[20];



The complicated and time-consuming thing here is getting you to post your code. Obviously that won't compile. What is "x"?

You are time-wasting here if you don't post your complete sketch.

Read this before posting a programming question
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

pierrot10

#19
Jul 14, 2013, 08:14 pm Last Edit: Jul 14, 2013, 08:46 pm by pierrot10 Reason: 1
Thank again all for helping
@PeterH
Those value are the excat value,  provided by
gps.getPar(lon,lat,alt,time,vel);
@acboother
Those value (lon, lat, alt, time, vel) are char
@Gammon
x is an value that I am not sure, but it should be aroud 114
I wrote this:
Quote

(x=a value that I may ignore..., may be it's the reason of my issue)

I posted the major code here
http://forum.arduino.cc/index.php?topic=177206.msg1315045#msg1315045

My code works fine excepted for my need to concatenate char variable, as I wrote before.


I also tried something like this
Keep in mind, lon, lat, alt, etc have 15 caraceter maximum
Code: [Select]

  char fix[144] = {"long=" + String(lon) + "&lat=" + String(lat) + "&alti=" + String(alt) + "&vel=" + String(vel) + "&time=" + String(time) + "\0"};

But I got this error message, because I miss the step to convert String to char. Can we do it simply?
Quote
Can not covert 'StringSumHelper' to 'char' in initlization

Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!
You can not know everything, perseverance, it is almost everything!

UKHeliBob

Quote
Can we do it simply?

We can do it very simply using strings rather than Strings
This code is based on the sample values that you have provided and works OK
Code: [Select]
char coords[100];

void setup()
{
  Serial.begin(115200);

  char lon[15] = {"712.585044"};
  char lat[15] = {"4705.587531"};
  char alt[15] = {"505.911530"};
  char time[20] = {"20130713210510.000"};
  char vel[15] = {"0.000000"};

  strcpy (coords,"lat=");
  strcat (coords,lat);

  strcat (coords,"&long=");
  strcat (coords,lon);

  strcat (coords,"&alt=");
  strcat (coords,alt);

  strcat (coords,"&vel=");
  strcat (coords,vel);

  strcat (coords,"&time=");
  strcat (coords,time);

  Serial.println(coords);
}

void loop()
{
}

The output is
Quote
lat=4705.587531&long=712.585044&alt=505.911530&vel=0.000000&time=20130713210510.000
so what is it about your code that causes the problem ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

AWOL

Quote
I posted the major code here

Ah yes! The code that was redacted to the point of illegibility, and that still has an orphaned comment.

pierrot10

Dear UKHeliBob

Thank for your proposition.

I am just confused with this, as you showed
Code: [Select]

char lon[15] = {"712.585044"};
  char lat[15] = {"4705.587531"};
  char alt[15] = {"505.911530"};
  char time[20] = {"20130713210510.000"};
  char vel[15] = {"0.000000"};


I can not hardly code this {"712.585044"};

The value are provided to lon, lat, alt, time, vel by a function
Code: [Select]
gps.getPar(lon,lat,alt,time,vel);
and all lon, lat, alt.. etc are char variable

I just declare
Code: [Select]

char coords[200]; //I gave this time a very large value, but it should be around 114
#define COORDSSIZ 15
char lon[COORDSSIZ];
char lat[COORDSSIZ];
char alt[COORDSSIZ];
char time[20];
char vel[COORDSSIZ];

and then the function give the value to the variable.

Code: [Select]

void getGPSCoords(){
  #ifdef DEBUG
    stat=gps.getStat();
    if(stat==1){
      Serial.println("NOT FIXED");
    }else if(stat==0){
      Serial.println("GPS OFF");
    }else if(stat==2){
      Serial.println("2D FIXED");
    }else if(stat==3){
      Serial.println("3D FIXED");
    }
    delay(5000);
  #endif   
 
  //Get data from GPS
 
  gps.getPar(lon,lat,alt,time,vel);
 
// Those Serial.println, print correctly the value of the variables
  Serial.println(lon);
  Serial.println(lat);
  Serial.println(alt);
  Serial.println(time);
  Serial.println(vel);
  /*
  String fix = "long=" + String(lon) + "&lat=" + String(lat) + "&alti=" + String(alt) + "&vel=" + String(vel) + "&time=" + String(time) + "\0";
//  char *fix[144] = {"long=" + String(lon) + "&lat=" + String(lat) + "&alti=" + String(alt) + "&vel=" + String(vel) + "&time=" + String(time) + "\0"};

  char *coord;
  coord = (char*)fix;
  */

  strcpy(coords,"long=");
  strncat(coords,lon,COORDSSIZ); //21 => This fonction is to limit the size of lon to 15. It uses the first 15 caracters, if there are more...

  strcat(coords,"&lat=");        //25
  strncat(coords,lat,COORDSSIZ);//40

  strcat(coords,"&alti=");        //46
  strncat(coords,alt,COORDSSIZ);  //61
 
  strcat(coords,"&t=");        //64
  strncat(coords,time,20);      //84
 
 
  strcat(coords,"&vel=");        //89
  strncat(coords,vel,COORDSSIZ);  //114
 
 
 
 
  #ifdef DEBUG
    Serial.print(F("Coords : "));                               
    Serial.println(coords);
  #endif

}

Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!
You can not know everything, perseverance, it is almost everything!

AWOL

Shall we just close this thread now, or are you going to post code?

pierrot10

#24
Jul 14, 2013, 09:35 pm Last Edit: Jul 14, 2013, 09:39 pm by pierrot10 Reason: 1
Here is my full full code

the function
void getGPSCoords(){} and
gps.getPar(lon,lat,alt,time,vel);
is at the bottom

and also look below
// GET GPS COORDS,
I call the function getGPSCoords, here, while I type "gps" in my terminal

Code: [Select]
#include "SIM900.h"
#include <SoftwareSerial.h>
#include "inetGSM.h"
#include "sms.h"
//#include "call.h"
#include "gps.h"

InetGSM inet;
//CallGSM call;
SMSGSM sms;
GPSGSM gps;

#define DEBUG

char number[]="0041000000000";  //Destination number

// INET
char apn[] = "internet"; // access-point name for GPRS
char username[] = "";
char password[] = "";
//char ip = "92.104.xx.xxx"; // IP address of server we're connecting to
int port_get = 80; // Port to use
int port_post = 80; // Port to use
char host[] = "xxx.dyndns.org"; // required in HTTP 1.1 - what's the name of the host at this IP address?
char path_post[] = "/opt/updatesql.php";
/*
const int buttonPin = 10;     // the number of the pushbutton pin
int buttonState = 0;
buttonState = digitalRead(buttonPin);
*/

// GPS

char coords[127];
#define COORDSSIZ 15
char lon[COORDSSIZ];
char lat[COORDSSIZ];
char alt[COORDSSIZ];
char time[20];
char vel[COORDSSIZ];
char msg1[5];
char msg2[5];

char stat;
char inSerial[20];
int i=0;
boolean started=false;

void setup()
{
  //Serial connection.
  Serial.begin(9600);
  #ifdef DEBUG
    Serial.println(F(""));
    Serial.println(F("\n--------------------------------"));
    Serial.println(F("Starting SIM908."));
    Serial.println(F("--------------------------------"));
    Serial.println(F("Please wait..."));
  #endif
  //Start configuration of shield with baudrate.
  //For http uses is raccomanded to use 4800 or slower.

  if (gsm.begin(2400)){
   
    #ifdef DEBUG
      Serial.println("\nstatus=READY\n");
    #endif
   
    gsm.forceON(); //To ensure that SIM908 is not only in charge mode
    started=true; 
   
  }else{
    #ifdef DEBUG
      Serial.println("\nstatus=IDLE");
    #endif
  }
  if(started){
    #ifdef DEBUG
      Serial.println(F("GPS"));
      Serial.println(F("--------------------------------"));
    #endif
    //GPS attach
    if (gps.attachGPS()){
      Serial.println("status=GPS_READY");
    }else{
      Serial.println("status=GPS_ERROR_NOT_ATTACHED");
    }
   
    #ifdef DEBUG
      Serial.println(F("\nGSM"));
      Serial.println(F("--------------------------------"));
    #endif
   
    #ifdef DEBUG
      Serial.println("Waiting for 20sec before trying to attach GSM");
    #endif
    delay(20000); //Time for fixing
   
   
   
    // GSM ATTACH
    if (inet.attachGPRS("internet", "", "")){
      #ifdef DEBUG
        Serial.println(F("status=GSM_ATTACHED"));
      #endif
      //Read IP address.
      gsm.SimpleWriteln("AT+CIFSR");
      delay(5000);
      //Read until serial buffer is empty.
      gsm.WhileSimpleRead();
    }else{
      Serial.println(F("status=GSM_ERROR_NOT_ATTACHED"));
    }
    #ifdef DEBUG
      Serial.println("\nWaiting for 1sec");
    #endif
    delay(1000);
   
   
   
    #ifdef DEBUG
      enterCommand();
    #endif
   
  }else{
    #ifdef DEBUG
      Serial.println(F("Not started"));
     #endif
  }
};

void loop()
{
  /*
  buttonState = digitalRead(buttonPin);
  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {     
    digitalWrite(GSM_ON, HIGH);
    delay(2000);
    digitalWrite(GSM_ON, LOW);
    delay(5000); 
  }
  else {
  }
  */
  //Read for new byte on serial hardware,
  //and write them on NewSoftSerial.
  serialhwread();
  //Read for new byte on NewSoftSerial.
  serialswread();
};

void serialhwread(){
  i=0;
  if (Serial.available() > 0){           
    while (Serial.available() > 0) {
      inSerial[i]=(Serial.read());
      delay(10);
      i++;     
    }
   
    inSerial[i]='\0';
    if(!strcmp(inSerial,"/END")){
      Serial.println("_");
      inSerial[0]=0x1a;
      inSerial[1]='\0';
      gsm.SimpleWriteln(inSerial);
    }
    //Send a saved AT command using serial port.
    if(!strcmp(inSerial,"test")){
      Serial.println(F("BATTERY TEST 1"));
      Serial.println(F("--------------------------------"));
      gps.getBattInf(msg1,msg2);
      Serial.println(msg1);
      Serial.println(msg2);
      Serial.println(F("BATTERY TEST 2"));
      Serial.println(F("--------------------------------"));
      gps.getBattTVol(msg1);
      Serial.println(msg1);
      Serial.println(F("GPS TEST"));
      Serial.println(F("--------------------------------"));
      getGPSCoords();
      Serial.println(F(""));
     
      #ifdef DEBUG
          enterCommand();
      #endif
    }
   
     // SEND SMS
    if(!strcmp(inSerial,"sms")){
      #ifdef DEBUG
        Serial.println(F("SENDING SMS"));
        Serial.println(F("--------------------------------"));
        Serial.println(F("In progress, wait..."));
      #endif
      if (sms.SendSMS(number, "Did you get that SMS?")){
        #ifdef DEBUG
          Serial.println("SMS sent OK\n");
        #endif
       }
       
       #ifdef DEBUG
          enterCommand();
        #endif
    }
   
    // GET GPS COORDS
    if(!strcmp(inSerial,"gps")){
      #ifdef DEBUG
        Serial.println(F("GETTING GPS COORDS"));
        Serial.println(F("--------------------------------"));
        Serial.println(F("In progress, wait..."));
      #endif
      getGPSCoords();
     
      #ifdef DEBUG
          enterCommand();
      #endif
    }
   
    // GET DATA FROM SERVER
    if(!strcmp(inSerial,"get")){
     
      #ifdef DEBUG
        Serial.println(F(""));
        Serial.println(F("The collection of data from the server, is not ready yet"));
       #endif
     /*
      #ifdef DEBUG
        Serial.print(F("Getting data from (Host/Port) "));
        Serial.print(host);
        Serial.print(F(" /  "));
        Serial.println(port_get);
      #endif
      */
     
      /*
      //TCP Client GET, send a GET request to the server and
      //save the reply.
      numdata=inet.httpGET(host, port_get, "/", msg, 50);
      //Print the results.
      Serial.println(F("\nNumber of data received:"));
      Serial.println(numdata); 
      Serial.println(F("\nData received:"));
      Serial.println(msg);
      */
     
       enterCommand();
    }
   
    // SEND DATA
    if(!strcmp(inSerial,"data")){
        #ifdef DEBUG
          Serial.println(F(""));
          Serial.println(F("Sending GPS coords to the remote server"));
          Serial.println(F("---------------------------------------"));
          Serial.println(F("Script not ready"));
         #endif
      /*
        inet.httpPOST(host, port_post, path_post, coords , "Result", 1000);
        delay(10000);
       */
        enterCommand();
    }
   
   
    //Read last message saved.
    if(!strcmp(inSerial,"msg")){
      Serial.println(msg1);
    }
    else{
      Serial.println(inSerial);
      gsm.SimpleWriteln(inSerial);
    }   
    inSerial[0]='\0';
  }
}

void serialswread(){
  gsm.SimpleRead();
}

void getGPSCoords(){
  #ifdef DEBUG
    stat=gps.getStat();
    if(stat==1){
      Serial.println("NOT FIXED");
    }else if(stat==0){
      Serial.println("GPS OFF");
    }else if(stat==2){
      Serial.println("2D FIXED");
    }else if(stat==3){
      Serial.println("3D FIXED");
    }
    delay(5000);
  #endif   
 
  //Get data from GPS
 
  gps.getPar(lon,lat,alt,time,vel);
 
  Serial.println(lon);
  Serial.println(lat);
  Serial.println(alt);
  Serial.println(time);
  Serial.println(vel);
  /*
  String fix = "long=" + String(lon) + "&lat=" + String(lat) + "&alti=" + String(alt) + "&vel=" + String(vel) + "&time=" + String(time) + "\0";
//  char *fix[144] = {"long=" + String(lon) + "&lat=" + String(lat) + "&alti=" + String(alt) + "&vel=" + String(vel) + "&time=" + String(time) + "\0"};

  char *coord;
  coord = (char*)fix;
  */

 
  strcpy(coords,"long=");
  strncat(coords,lon,COORDSSIZ); //21

  strcat(coords,"&lat=");        //25
  strncat(coords,lat,COORDSSIZ);//40

  strcat(coords,"&alti=");        //46

  strncat(coords,alt,COORDSSIZ);  //61
 
  strcat(coords,"&t=");        //64
  strncat(coords,time,20);      //84
 
  strcat(coords,"&vel=");        //89
  strncat(coords,vel,COORDSSIZ);  //114
 
 
  #ifdef DEBUG
    Serial.print(F("Coords : "));                               
    Serial.println(coords);
  #endif

}

void enterCommand(){
    Serial.println("\nEnter a command :");
    Serial.println(F("--------------------------------"));
    Serial.println(F("sms  => Send SMS"));
    Serial.println(F("data => Send GPS coords to the server"));
    Serial.println(F("get  => Get data from server"));
    Serial.println(F("gps  => Display GPS coords"));
    Serial.println(F("test => Test system"));
    Serial.println(F("--------------------------------\n"));
   
}
Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!
You can not know everything, perseverance, it is almost everything!

acboother

Can you post the header file that has

Code: [Select]
gps.getPar(lon,lat,alt,time,vel);

pierrot10

Really really thank for your help.

What do you mean ba the header?

The function is in another file. I past all of this function. I hope I answered to your question
(I have not wrote this function. It's a library I found.)
Code: [Select]

char GPSGSM::getPar(char *str_long, char *str_lat, char *str_alt, char *str_time, char *str_speed)
{
char ret_val=0;
char *p_char;
char *p_char1;
gsm.SimpleWriteln("AT+CGPSINF=0");
gsm.WaitResp(5000, 100, "OK");
if(gsm.IsStringReceived("OK"))
ret_val=1;

//longitude
p_char = strchr((char *)(gsm.comm_buf),',');
p_char1 = p_char+1;  //we are on the first char of longitude
p_char = strchr((char *)(p_char1), ',');
if (p_char != NULL) {
          *p_char = 0;
    }
strcpy(str_long, (char *)(p_char1));

// latitude
p_char++;
p_char1 = strchr((char *)(p_char), ',');
if (p_char1 != NULL) {
          *p_char1 = 0;
    }
strcpy(str_lat, (char *)(p_char));

// altitude
p_char1++;
p_char = strchr((char *)(p_char1), ',');
if (p_char != NULL) {
          *p_char = 0;
    }
strcpy(str_alt, (char *)(p_char1));

// UTC time
p_char++;
p_char1 = strchr((char *)(p_char), ',');
if (p_char1 != NULL) {
          *p_char1 = 0;
    }
strcpy(str_time, (char *)(p_char));

// TTFF
p_char1++;
p_char = strchr((char *)(p_char1), ',');
if (p_char != NULL) {
          *p_char = 0;
    }

// num
p_char++;
p_char1 = strchr((char *)(p_char), ',');
if (p_char1 != NULL) {
          *p_char1 = 0;
    }

// speed
p_char1++;
p_char = strchr((char *)(p_char1), ',');
if (p_char != NULL) {
          *p_char = 0;
    }
strcpy(str_speed, (char *)(p_char1));

return ret_val;
}
Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!
You can not know everything, perseverance, it is almost everything!

acboother

That's what I wanted. Just to check you really really ;) had char*

Try simulating the problem with a piece of code that has the essential parts that you think are 'faulty' including a simulated call to this function. Debug as best you can the individual returned strings and check to see where the NULL character is (within the length you allocate). That is your max string length plus one.

Check the string you are concatenating into after every concat.

Eliminate everything you don't think is relevant.

Keep checking until it works or you have the absolute minumum code which still doesn't work. Then you know its most likely in the bit you've just deleted (if it started to work) or in the unshrinkable bit that's left, which hopefully will be easier for you or others to spot the problem. If you don't fix it, post a fully compilable source code with the fault.

pierrot10

#28
Jul 14, 2013, 10:14 pm Last Edit: Jul 14, 2013, 10:16 pm by pierrot10 Reason: 1
Hello acboother,

Yes, I debug a bit as you explain.
Yesterday evening, I discivered that it work until this
Code: [Select]

/*
  strncat(coords,alt,COORDSSIZ);  //61
 
  strcat(coords,"&t=");        //64
  strncat(coords,time,20);      //84
 
  strcat(coords,"&vel=");        //89
  strncat(coords,vel,COORDSSIZ);  //114
  */


Code: [Select]

void getGPSCoords(){
  #ifdef DEBUG
    stat=gps.getStat();
    if(stat==1){
      Serial.println("NOT FIXED");
    }else if(stat==0){
      Serial.println("GPS OFF");
    }else if(stat==2){
      Serial.println("2D FIXED");
    }else if(stat==3){
      Serial.println("3D FIXED");
    }
    delay(5000);
  #endif   
 
  //Get data from GPS
 
    gps.getPar(lon,lat,alt,time,vel);
 
  Serial.println(lon);
  Serial.println(lat);
  Serial.println(alt);
  Serial.println(vel);
  Serial.println(time);
  Serial.println("-----");



  strcpy(coords,"long=");
  strncat(coords,lon,COORDSSIZ); //21

  strcat(coords,"&lat=");        //25
  strncat(coords,lat,COORDSSIZ);//40

  strcat(coords,"&alti=");        //46
/*
  strncat(coords,alt,COORDSSIZ);  //61
 
  strcat(coords,"&t=");        //64
  strncat(coords,time,20);      //84
 
  strcat(coords,"&vel=");        //89
  strncat(coords,vel,COORDSSIZ);  //114
  */
 
  // I am also trying this, but coords display nothing
  //snprintf(coords, sizeof coords,"lon=%s,lat=%s,alti=%s,vel=%s,time=%s",lon,lat,alt,vel,time);
 
  #ifdef DEBUG
    Serial.print(F("Coords : "));                               
    Serial.println(coords);
  #endif


I am also traing with this
Code: [Select]

char coords[]="";
snprintf(coords, sizeof coords,"lon=%s,lat=%s,alti=%s,vel=%s,time=%s",lon,lat,alt,vel,time);
Serial.println(coords);

With this, the code work and do not crash or restart. But coords display nothing
Il ne suffit pas de tout savoir, la persévérance, c'est déjà presque tout!
You can not know everything, perseverance, it is almost everything!

nickgammon

Code: [Select]
char coords[]="";
snprintf(coords, sizeof coords,"lon=%s,lat=%s,alti=%s,vel=%s,time=%s",lon,lat,alt,vel,time);


Try this test:

Code: [Select]

void setup ()
  {
  Serial.begin (115200);
  char coords[]="";
  Serial.println (sizeof coords);
  }  // end of setup

void loop () { }


That outputs:

Code: [Select]

1


So coords is one byte long. Will "lon=%s,lat=%s,alti=%s,vel=%s,time=%s" fit into one byte? No.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

Go Up