how to combine const char variables

Hello,

I would like to make an url from a few const char* variable as you can see below:

   fb_url = "https://graph.facebook.com/" + fb_pagename + "?access_token=" + fb_accesstoken + "&fields=fan_count";

but I got the following error when I try the code:

invalid operands of types ‘const char [28]’ and ‘const char*’ to binary ‘operator+’

I’m a newby with arduino, so I have a lot to studdy. Can someone explain me what should I do, and what is the different between char and const char at all?

Thank you for your support!

SOURCE

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ArduinoJson.h>

#include <ESP8266HTTPClient.h>

#include <WiFiClientSecureBearSSL.h>
// Fingerprint for demo URL, expires on June 2, 2019, needs to be updated well before this date

const char* fb_fingerprint = "";
const String fb_url = "";
const char* fb_accesstoken ="EAAFBCZCd1lKoBACGKAtbt8aP79IW9CfiDaAWX4nflBcjebWg81ZB04zrKrLAmebyxCDDPjVNLCTHgyDFURiUIbvJSKfFLB898UkQD7Rwfnjp4auprM5QKwICsmPouml6zGRpG3ZCpYBXJZBLxampZCdbKq11ePjYlMNwLHSxoPwZDZD";
const char* fb_pagename ="shapenbake2018";
ESP8266WiFiMulti WiFiMulti;

void setup() {

  Serial.begin(115200);
  // Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  for (uint8_t t = 4; t > 0; t--) {
    Serial.printf("[SETUP] WAIT %d...\n", t);
    Serial.flush();
    delay(1000);
  }

  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("UPC4191181", "UYGRXZZG");
}

void loop() {
  // wait for WiFi connection

 DynamicJsonBuffer jsonBuffer;

//

Serial.print("[HTTP] begin...\n");

     if ((WiFiMulti.run() == WL_CONNECTED)) {

    WiFiClient client;
    
 HTTPClient http;
     
    if (http.begin(client, "http://faktotum.hu/fb_counter/fingerprint.php")) {  // HTTP


      Serial.print("[HTTP] GET...\n");
      // start connection and send HTTP header
      int httpCode = http.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTP] GET... code: %d\n", httpCode);

        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = http.getString();
        
           Serial.println("json...");
           JsonObject& root = jsonBuffer.parseObject(payload);
          fb_fingerprint = root[String("fb_fingerprint")];
          Serial.println(fb_fingerprint);
        }
      } else {
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }

      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }


//


  
  if ((WiFiMulti.run() == WL_CONNECTED)) {

    std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);

    client->setFingerprint(fb_fingerprint);

    HTTPClient https;

    Serial.print("[HTTPS] begin...\n");

    fb_url = "https://graph.facebook.com/" + fb_pagename + "?access_token=" + fb_accesstoken + "&fields=fan_count";
    //fb_url = "https://graph.facebook.com/" + fb_pagename + "?access_token=" + fb_accesstoken + "&fields=fan_count";
    if (https.begin(*client, fb_url)) {  // HTTPS

      Serial.print("[HTTPS] GET...\n");
      // start connection and send HTTP header
      int httpCode = https.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);

        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = https.getString();
          Serial.println("json...");
           JsonObject& root = jsonBuffer.parseObject(payload);
          int fan_count = root[String("fan_count")];
          Serial.println(fan_count);
        }
      } else {
        Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      }

      https.end();
    } else {
      Serial.printf("[HTTPS] Unable to connect\n");
    }
  }

  Serial.println("Wait 10s before next round...");
  delay(10000);
}

You should always post a complete program. Your snippet gives no idea how your data items are defined. I use the words "data items" because, by definition, a const is not a variable.

My guess is that you are using String class and it is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

...R

Robin2:
You should always post a complete program. Your snippet gives no idea how your data items are defined. I use the words “data items” because, by definition, a const is not a variable.

My guess is that you are using String class and it is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with ‘\0’ (NULL).

…R

Sorry for that. I put the code both here and the original post.
I would really apprichiate if you could help me to solve this one.

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ArduinoJson.h>

#include <ESP8266HTTPClient.h>

#include <WiFiClientSecureBearSSL.h>
// Fingerprint for demo URL, expires on June 2, 2019, needs to be updated well before this date

const char* fb_fingerprint = "";
const String fb_url = "";
const char* fb_accesstoken ="EAAFBCZCd1lKoBACGKAtbt8aP79IW9CfiDaAWX4nflBcjebWg81ZB04zrKrLAmebyxCDDPjVNLCTHgyDFURiUIbvJSKfFLB898UkQD7Rwfnjp4auprM5QKwICsmPouml6zGRpG3ZCpYBXJZBLxampZCdbKq11ePjYlMNwLHSxoPwZDZD";
const char* fb_pagename ="shapenbake2018";
ESP8266WiFiMulti WiFiMulti;

void setup() {

  Serial.begin(115200);
  // Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  for (uint8_t t = 4; t > 0; t--) {
    Serial.printf("[SETUP] WAIT %d...\n", t);
    Serial.flush();
    delay(1000);
  }

  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("UPC4191181", "UYGRXZZG");
}

void loop() {
  // wait for WiFi connection

 DynamicJsonBuffer jsonBuffer;

//

Serial.print("[HTTP] begin...\n");

     if ((WiFiMulti.run() == WL_CONNECTED)) {

    WiFiClient client;
    
 HTTPClient http;
     
    if (http.begin(client, "http://faktotum.hu/fb_counter/fingerprint.php")) {  // HTTP


      Serial.print("[HTTP] GET...\n");
      // start connection and send HTTP header
      int httpCode = http.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTP] GET... code: %d\n", httpCode);

        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = http.getString();
        
           Serial.println("json...");
           JsonObject& root = jsonBuffer.parseObject(payload);
          fb_fingerprint = root[String("fb_fingerprint")];
          Serial.println(fb_fingerprint);
        }
      } else {
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }

      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }


//


  
  if ((WiFiMulti.run() == WL_CONNECTED)) {

    std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);

    client->setFingerprint(fb_fingerprint);

    HTTPClient https;

    Serial.print("[HTTPS] begin...\n");

    fb_url = "https://graph.facebook.com/" + fb_pagename + "?access_token=" + fb_accesstoken + "&fields=fan_count";
    //fb_url = "https://graph.facebook.com/" + fb_pagename + "?access_token=" + fb_accesstoken + "&fields=fan_count";
    if (https.begin(*client, fb_url)) {  // HTTPS

      Serial.print("[HTTPS] GET...\n");
      // start connection and send HTTP header
      int httpCode = https.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);

        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = https.getString();
          Serial.println("json...");
           JsonObject& root = jsonBuffer.parseObject(payload);
          int fan_count = root[String("fan_count")];
          Serial.println(fan_count);
        }
      } else {
        Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      }

      https.end();
    } else {
      Serial.printf("[HTTPS] Unable to connect\n");
    }
  }

  Serial.println("Wait 10s before next round...");
  delay(10000);
}

These things should not be constants - because AFAIK you want to be able to change them

const char* fb_fingerprint = "";
const String fb_url = "";

...R

To combine null terminated character arrays use the strcat() function.

If you want to build a string with const literals and variable data use the sprintf() function

The + operator works with Strings, but not with strings. Don't use Strings.

invalid operands of types 'const char [28]' and 'const char*' to binary 'operator+'

You are trying to concatenate a mixture of strings and Strings using the + operator

Use strings throughout and strcat() to concatenate them

Use google to find documentation on how to use strcat(), strcopy() and sprintf(). Those three words should get you going with string (lowercase s) manipulation.

The reason you want to use strings instead of Strings is memory - Arduino only has a fer hundred bytes of memory, and it gets used up quickly when Strings are used, especially when you are copying and concatenating them. Each time a memory allocation is done, a bit of memory is left unusable and the next String has to fit around it. Eventually this renders all of your memory unusable and your sketch crashes. Since Arduino has no operating system to do 'garbage collection', there is no built-in cure for this - you'd need to call free() yourself after you use a string. So it's best to use character arrays as c-strings.

ChrisTenone: The reason you want to use strings instead of Strings is memory - Arduino only has a fer hundred bytes of memory, and it gets used up quickly when Strings are used, especially when you are copying and concatenating them. Each time a memory

Based on the source it looks like OP is using the ESP8266. Lots more memory available (50-60k RAM), nonetheless your comments remain valid. C-strings take much less memory, and are almost as easy to manipulate as String.

Unfortunately it seems that the default http library expects to receive and return String objects. I've tried to use C-strings (char arrays) but it just didn't compile. Same for receiving data from the http server: it comes as String object.

There's just no (easy) way around the String when using ESP8266 and the web server... So for me it's string where I can, String where I must. Not happy either way.

There’s just no (easy) way around the String when using ESP8266 and the web server…

This works for me and not a String in sight anywhere

  snprintf(HTMLbuffer, HTMLbufferSize, "<!DOCTYPE html>\
<html>\
<head>\
<style>\
.colourSquare {width: 300px; height: 300px; font-size: 80px; color: WHITE; font-weight:bold; display: inline-block;}\
</style>\
</head>\
<form action=\"/redLED\" method=\"POST\"><input type=\"submit\" class=\"colourSquare\" style=\"background-color:RED;\" value=\"%s\"></form>\
<form action=\"/greenLED\" method=\"POST\"><input type=\"submit\" class=\"colourSquare\" style=\"background-color:GREEN;\" value=\"%s\"></form>\
<form action=\"/blueLED\" method=\"POST\"><input type=\"submit\" class=\"colourSquare\" style=\"background-color:BLUE;\" value=\"%s\"></form>\
</html>", redText, greenText, blueText);
  server.send(200, "text/html", HTMLbuffer );