我有一个char数组,我试图将其变成指向字符串的char指针。我相信这涉及获取指向char数组的第一个元素的指针,并在char数组的末尾添加一个空字符。这样做的原因是我试图将它传递给SimpleMenuItem
用于pebble智能手表,其中.title
需要获得char*
,指向一个字符串。
虽然我已经能够填充char数组并且(我认为)添加了null字符并获得了指针,但是我无法在我的卵石上看到标题。我不确定这是一个卵石问题还是我的C理解问题,但我觉得它可能是前者。
Pebble代码(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);
}
如果有人对于为什么鹅卵石没有显示其在.title
中分配的数据有任何建议,我很乐意听到它们。
谢谢!
答案 0 :(得分:2)
(我不知道 Pebble 是什么,所以这个答案完全基于C语言。)
我认为你的主要问题在于:
char* ptr = remainderArray;
strncpy(ptr, remainderArray, sizeof(remainderArray)+1);
源指针和目标指针是相同的。你想在这做什么?
C标准(或其final public draft)说:
7.24.2.4 strncpy函数
2。strncpy
功能副本不超过n
个字符(不会复制空字符后面的字符) )从s2
指向的数组到s1
308)指向的数组。 如果在重叠的对象之间进行复制,则行为未定义。
如果您需要复制重叠对象,则必须使用memmove()
,或者自行复制字符。
我还认为您的代码中存在一些错误的错误:
char originalArray[strlen(original)];
这不会为终止空字符留出空间。
ptr[sizeof(remainderArray)+1] = '\0';
这会在remainderArray
的末尾写入一个字节。
答案 1 :(得分: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
}