使用 sprintf() 函数后 C 字符字符串不可读

C char string not readable after using sprintf() function

在 Arduino Sketch 上,我需要使用 C 字符串而不是 C++ 字符串对象,以最大限度地减少内存使用。这本身就是一个挑战,因为我不熟悉经典 C。

然而不知何故我让它工作(或多或少)但我遇到了问题。这是一个测试草图来解释它:

#define APIKEY "TWITTER_KEY" //  api key ThingSpeak
#define TARGET_IP "184.106.153.149"///         //local  direccion IP o Hosting  ThingSpeak
#define TARGET_PORT "80"          ///  puerto 80
#define ID "WiFi_ID"  //name of wireless access point to connect to   - Red de inhalambrica wifi 
#define PASS "WiFI_Password"  //wifi password                          - Contraseña de Wifi 



#define TWEET "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."


char foo[400]; //contains the tweet request
char bar[20]; //auxiliary
char numberString[3]; //contains numbers


void setup() {

  Serial.begin(9600);

  testMethod();

}


void testMethod(){

   Serial.println(" ");
   Serial.println("testMethod");
   Serial.println(" ");



    strcpy(foo, "api_key=");
    strcat(foo, APIKEY);
    strcat(foo, "&status=");
    strcat(foo, TWEET);

    Serial.println(foo);


  //sprintf(numberString, "%d", strlen(foo)); //converts the integer into a char


  Serial.println(numberString);


     // Create HTTP POST Data  


     strcpy(foo, "POST /apps/thingtweet/1/statuses/update HTTP/1.1\n");
     strcat(foo, "Host: api.thingspeak.com\n");
     strcat(foo, "Connection: close\n");
     strcat(foo, "Content-Type: application/x-www-form-urlencoded\n");
     strcat(foo, "Content-Length: ");
     strcat(foo, numberString);
     strcat(foo, "\n\n");
     strcat(foo, "api_key=");
     strcat(foo, APIKEY);
     strcat(foo, "&status=");
     strcat(foo, TWEET);


    Serial.println(foo);


  }




void loop() {


}

如果我要取消注释行

 //sprintf(numberString, "%d", strlen(foo)); //converts the integer into a char

然后我无法在串行监视器上打印 foo,也无法打印稍后生成的新 foo。如果我硬编码一个整数而不是 strlen() 函数,情况也是如此。

我会将此描述为一种奇怪的行为,但很可能只是我的无知。我阅读了有关 sprintf() 方法的文档,但我还没有看到有关此问题的任何信息。

任何帮助将不胜感激。 提前致谢!

strlen(foo) 是一个 3 位数字,因此您需要为 numberString 分配 4 个字节以容纳这 3 位数字和 NUL 终止符。

嗯,看来 foo(顺便说一句,这里的变量名很棒)的长度可以超过 99,所以你需要多于两位数。你知道 C 字符串是以 0 结尾的吗?字符串 "123" 在内存中的表示是:

+-+-+-+--+
|1|2|3|[=10=]|
+-+-+-+--+

其中 [=15=] 是一个值为 0 的 char。所以总是需要一个额外的位置来保存它。你应该让你的阵列更大:

char numberString[8];

为了安全起见。同样使用 snprintf() 在这里有所帮助:

snprintf(numberString, sizeof numberString, "%zu", strlen(foo));

因为从技术上讲,您也会从类型不匹配中获得未定义的行为(%d 适用于 int,但 strlen() returns size_t).

您为 numberString 保留了 3 个字符。这包括终止零字符。如果 strlen(foo) returns 大于 99 的整数,您将溢出 numberString 缓冲区。缓冲区溢出后可能会发生有趣的事情。

您在 strlen() 上遇到了问题,它没有给出以 null 结尾的字节长度。

  char foo[400] = "hello world";
 // here you allocated the less width, in  C strings are the sequence of character bytes terminated with NULL in the end.
  char number[4]; 

  sprintf(number, "value: %zu\n", strlen(foo));