0

我有一个 char 数组,我试图将其转换为指向字符串的 char 指针。我相信这涉及获取指向 char 数组的第一个元素的指针,并在 char 数组的末尾添加一个空字符。这样做的原因是我试图将它传递给SimpleMenuItempebble 智能手表的 a ,其中.title需要获取 a char*,指向一个字符串。

虽然我已经能够填充 char 数组并且(我认为)添加了空字符并获得了指针,但我无法在我的鹅卵石上看到标题。我不确定这是一个鹅卵石问题还是我对 C 的理解的问题,但我深感它可能是前者。

卵石代码(C):

void in_received_handler(DictionaryIterator *received, void *context) {
    dataReceived = dict_read_first(received);
    APP_LOG(APP_LOG_LEVEL_DEBUG, "read first");

    while (dataReceived != NULL){

        if (dataReceived->key == 0x20) {

            //original is of the format "# random string", i.e. "4 test name"
            char* original = dataReceived->value->cstring;
            APP_LOG(APP_LOG_LEVEL_DEBUG, original);

            char originalArray[strlen(original)];
            //copy over to originalArray
            for (unsigned int i = 0; i < strlen(original); i++) {
                originalArray[i] = original[i];
            }

            char* keysplit = strtok(originalArray, " ");
            APP_LOG(APP_LOG_LEVEL_DEBUG, keysplit);

            //key
            int key = atoi(keysplit);
            APP_LOG(APP_LOG_LEVEL_DEBUG, "Int Key: %d", key);

            //good until here
            char remainderArray[sizeof(originalArray)-strlen(keysplit) +1];

            //assign rest of string to new array
            for (unsigned int i = 1; i < sizeof(remainderArray)-1; i++){
                APP_LOG(APP_LOG_LEVEL_DEBUG, "Character             : %c", originalArray[i+strlen(keysplit)]);
                remainderArray[i] = originalArray[i+strlen(keysplit)];
                APP_LOG(APP_LOG_LEVEL_DEBUG, "Character in new Array: %c", remainderArray[i]);
            }

            remainderArray[sizeof(remainderArray)-1] = '\0';

            //data is sucesfully placed into remainderArray
            char* ptr = remainderArray;
            strncpy(ptr, remainderArray, sizeof(remainderArray)+1);
            ptr[sizeof(remainderArray)+1] = '\0';

            chats[key] = (SimpleMenuItem){
                // You should give each menu item a title and callback
                .title = &remainderArray[0],
                .callback = selected_chat,
            };

        }

        dataReceived = dict_read_next(received);
        APP_LOG(APP_LOG_LEVEL_DEBUG, "read again");

    }

    layer_mark_dirty((Layer *)voice_chats);
}

如果有人对为什么 pebble 没有显示分配给它的数据有任何建议.title,我很想听听他们的意见。

谢谢!

4

2 回答 2

2

(我不知道Pebble是什么,所以这个答案完全基于 C 语言。)

我认为你的主要问题在这里:

char* ptr = remainderArray;
strncpy(ptr, remainderArray, sizeof(remainderArray)+1);

源指针和目标指针是相同的。你想在这里做什么?

C 标准(或它的最终公开草案)说:

7.24.2.4 strncpy 函数

2.strncpy函数从 308 所指向的数组中复制不超过308所指向的数组中n的字符(不复制空字符后的字符) 。如果复制发生在重叠的对象之间,则行为未定义。s2s1

如果您需要复制重叠的对象,您必须使用memmove(), 或自己循环复制字符。

我还认为您的代码中存在一些错误:

char originalArray[strlen(original)];

这不会为终止空字符留下空间。

ptr[sizeof(remainderArray)+1] = '\0';

这会在结束后写入一个字节remainderArray

于 2014-07-03T22:35:56.843 回答
1

解决方案实际上比这简单得多。

首先,请注意 char 数组和指向字符串的指针实际上是相同的东西。它们都是指向第一个字节地址的指针。在这两种情况下,系统函数都会搜索空字符来标识字符串的结尾(strlen、strcpy、printf 等)。char*并且char[]可以互换。

当您在 中接收数据时in_received_handler(),您获得的指针 ( dataReceived->value->cstring) 指向蓝牙接收缓冲区,您需要将该字符串复制到其他地方。这样,每次需要重新绘制屏幕时,字符都将可用。

因为您获得的是动态数量的项目,所以您必须使用malloc(). 您应该记住稍后释放该内存(使用free())。

这编译并应该做你想要的:

void in_received_handler(DictionaryIterator *received, void *context) {
  Tuple *dataReceived = dict_read_first(received);

  while (dataReceived != NULL){
    if (dataReceived->key == 0x20) {
      //original is of the format "# random string", i.e. "4 test name"
      char* original = dataReceived->value->cstring;
      APP_LOG(APP_LOG_LEVEL_DEBUG, original);

      char* keysplit = strtok(original, " ");
      APP_LOG(APP_LOG_LEVEL_DEBUG, keysplit);

      //key
      int key = atoi(keysplit);
      APP_LOG(APP_LOG_LEVEL_DEBUG, "Int Key: %d", key);

      // This will return the second part of the string.
      char *message = strtok(NULL, " ");
      // Allocate some memory to hold a copy of that message
      char *copyOfMessage = malloc(strlen(message));
      // And copy the message from the bluetooth buffer to the new memory
      strcpy(copyOfMessage, message);
      APP_LOG(APP_LOG_LEVEL_DEBUG, "Message: %d", key);

      chats[key] = (SimpleMenuItem){
        // You should give each menu item a title and callback
        .title = copyOfMessage,
        .callback = selected_chat,
      };
    }

    dataReceived = dict_read_next(received);
  }
  layer_mark_dirty((Layer *)voice_chats);
}

顺便说一句,我建议您使用另一个应用程序消息键索引来传输您的“密钥”,而不是使用一个带有密钥和消息的字符串并在客户端中用 C 解析它。例如,您可以:

{
  0x1: 33,                 // the key
  0x20: "message"           // the actual message
}
于 2014-07-07T20:57:18.587 回答