关于 C 中的结构,如何将数据从结构复制到字符串数组
Regarding structs in C, how to copy the data from a struct to a string array
如果使用 mDNS 在网络上找到服务器,我有一个程序。它来自开源堆栈。
目前,我需要以下用例的指导。
用例:每当我 运行 找到服务器的程序时,我计划添加一个额外的逻辑,它会尝试连接到提到的服务器,如果连接失败,我会打印一条警告消息,说明服务器上的网络连接可能有问题。
所以对代码来说,
它具有如下定义的类型结构
typedef struct {
size_t length; /* The length of the string */
UA_Byte *data; /* The content (not null-terminated) */
} UA_String;
typedef struct {
UA_UInt32 recordId;
UA_String serverName;
UA_String discoveryUrl;
size_t serverCapabilitiesSize;
UA_String *serverCapabilities;
} UA_ServerOnNetwork;
默认代码的逻辑运行是这样的:
for(size_t i = 0; i < serverOnNetworkSize; i++) {
UA_ServerOnNetwork *server = &serverOnNetwork[i];
printf("Server[%lu]: %.*s", (unsigned long) i,
(int) server->serverName.length, server->serverName.data);
printf("\n\tRecordID: %d", server->recordId);
printf("\n\tDiscovery URL: %.*s", (int) server->discoveryUrl.length,
server->discoveryUrl.data);
printf("\n\tCapabilities: ");
/*for(size_t j = 0; j < server->serverCapabilitiesSize; j++) {
printf("%.*s,", (int) server->serverCapabilities[j].length,
server->serverCapabilities[j].data);
}*/
//added below
printf("%.*s", (int) server->serverCapabilities[0].length,
server->serverCapabilities[0].data);
printf("\n\tStatus: ");
printf("%.*s", (int) server->serverCapabilities[1].length,
server->serverCapabilities[1].data);
printf("\n\n");
}
观察到的输出形式为
Server[0]: name1
RecordID: 0
Discovery URL: opc.tcp://hostname2:4840
Capabilities: LDSME-DESKTOPSIDE
Status: Available
Server[1]: name2
RecordID: 1
Discovery URL: opc.tcp://hostname:4842
Capabilities: Crane
Status: Starting...
Server[2]: hostname
RecordID: 2
Discovery URL: opc.tcp://hostname:4840
Capabilities: LDSME-NOTEBOOKSIDE
Status: AVailable
这是默认情况。但我计划对提到的每个 URL 执行 ping 操作(或尝试发送消息)以检查网络是否一切正常。
所以我打算提取URL信息。
因此我声明了一个字符数组 A,并尝试使用 strcpy 和 memcpy 函数将内容从 server->discoveryURL.data 复制到数组 A。
但是失败了。
for(size_t i = 0; i < serverOnNetworkSize; i++) {
UA_ServerOnNetwork *server = &serverOnNetwork[i];
strcpy(A[i], server->discoveryUrl.data);
printf("URL %d: %s\n",(unsigned long) i,A[i]);
}
它失败了,甚至 运行 都没有通过循环。需要一些指导才能输出以下格式
URL 0 : opc.tcp://hostname2:4840
URL 1 : opc.tcp://hostname:4842
URL 2 : opc.tcp://hostname:4840
我也不明白为什么,在结构字符串的 printf 语句中,“%s”在末尾给出了一个额外的字符,而“%.*s”给出了正确的输出。敬请期待指导。
编辑:我稍微修改了代码并引入了一个新的全局字符数组,并使用了 memcpy 函数。但是我正在努力,因为我在 URL 字段中获得了一个额外的字符。
char *A[] = {};
int main(){
for(size_t i = 0; i < serverOnNetworkSize; i++) {
UA_ServerOnNetwork *server = &serverOnNetwork[i];
A[i] = (char*)UA_malloc(server->discoveryUrl.length+1);
memcpy(A[i],server->discoveryUrl.data,server->discoveryUrl.length);
printf("URL %d: %.*s\n",(unsigned long) i,A[i]);
}
}
输出显示为:
URL 0: opc.tcp://o755-gksr:48401
URL 1: opc.tcp://o755-gksr:48421
末尾多了一个字符1是错误的。请提供有关如何处理该问题的任何指导。
您需要在复制后以'\0'结束字符串数据。
这样 printf 的 %s 就会知道什么时候停止:
// first we need some memory for the destination of the copy
A[i] = malloc(server->discoveryUrl.length+1); // +1 for the '[=10=]' at the end
// then we copy exactly the number of characters we want
strncpy(A[i], server->discoveryUrl.data, server->discoveryUrl.length);
// then we add the '[=10=]' terminator
A[i][server->discoveryUrl.length] = '[=10=]'; // add the '[=10=]' at the end
这是一个示例:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
// defien these so we don't need mDNS
typedef char UA_Byte;
typedef uint32_t UA_UInt32;
typedef struct {
size_t length; /* The length of the string */
UA_Byte *data; /* The content (not null-terminated) */
} UA_String;
typedef struct {
UA_UInt32 recordId;
UA_String serverName;
UA_String discoveryUrl;
size_t serverCapabilitiesSize;
UA_String *serverCapabilities;
} UA_ServerOnNetwork;
// for testing we only need one of these
UA_ServerOnNetwork serverOnNetwork[1] = {
{
1, // recordId
{3,"abcd"}, // serverName
{3,"efgh"}, // discoveryUrl
0, // serverCapabilitiesSize
NULL // serverCapabilities
}
};
int serverOnNetworkSize = sizeof(serverOnNetwork)/sizeof(serverOnNetwork[0]);
int main() {
// first print it using the %.*s printf formatter
for(size_t i = 0; i < serverOnNetworkSize; i++) {
UA_ServerOnNetwork *server = &serverOnNetwork[i];
printf("Server[%lu]: %.*s", (unsigned long) i,
(int) server->serverName.length, server->serverName.data);
printf("\n\tRecordID: %d", server->recordId);
printf("\n\tDiscovery URL: %.*s", (int) server->discoveryUrl.length,
server->discoveryUrl.data);
}
// now make an array of '[=11=]' terminated strings, fill them in, and print them
printf("\n\nURLs:");
char *A[serverOnNetworkSize];
for(size_t i = 0; i < serverOnNetworkSize; i++) {
UA_ServerOnNetwork *server = &serverOnNetwork[i];
// first we need some memory for the destination of the copy
A[i] = malloc(server->discoveryUrl.length+1); // +1 for the '[=11=]' at the end
// then we copy exactly the number of characters we want
strncpy(A[i], server->discoveryUrl.data, server->discoveryUrl.length);
// then we add the '[=11=]' terminator
A[i][server->discoveryUrl.length] = '[=11=]'; // add the '[=11=]' at the end
// and finally we print it
printf("\n\tURL %lu: %s\n", (unsigned long) i, A[i]);
}
return 0;
}
如果使用 mDNS 在网络上找到服务器,我有一个程序。它来自开源堆栈。 目前,我需要以下用例的指导。 用例:每当我 运行 找到服务器的程序时,我计划添加一个额外的逻辑,它会尝试连接到提到的服务器,如果连接失败,我会打印一条警告消息,说明服务器上的网络连接可能有问题。
所以对代码来说,
它具有如下定义的类型结构
typedef struct {
size_t length; /* The length of the string */
UA_Byte *data; /* The content (not null-terminated) */
} UA_String;
typedef struct {
UA_UInt32 recordId;
UA_String serverName;
UA_String discoveryUrl;
size_t serverCapabilitiesSize;
UA_String *serverCapabilities;
} UA_ServerOnNetwork;
默认代码的逻辑运行是这样的:
for(size_t i = 0; i < serverOnNetworkSize; i++) {
UA_ServerOnNetwork *server = &serverOnNetwork[i];
printf("Server[%lu]: %.*s", (unsigned long) i,
(int) server->serverName.length, server->serverName.data);
printf("\n\tRecordID: %d", server->recordId);
printf("\n\tDiscovery URL: %.*s", (int) server->discoveryUrl.length,
server->discoveryUrl.data);
printf("\n\tCapabilities: ");
/*for(size_t j = 0; j < server->serverCapabilitiesSize; j++) {
printf("%.*s,", (int) server->serverCapabilities[j].length,
server->serverCapabilities[j].data);
}*/
//added below
printf("%.*s", (int) server->serverCapabilities[0].length,
server->serverCapabilities[0].data);
printf("\n\tStatus: ");
printf("%.*s", (int) server->serverCapabilities[1].length,
server->serverCapabilities[1].data);
printf("\n\n");
}
观察到的输出形式为
Server[0]: name1
RecordID: 0
Discovery URL: opc.tcp://hostname2:4840
Capabilities: LDSME-DESKTOPSIDE
Status: Available
Server[1]: name2
RecordID: 1
Discovery URL: opc.tcp://hostname:4842
Capabilities: Crane
Status: Starting...
Server[2]: hostname
RecordID: 2
Discovery URL: opc.tcp://hostname:4840
Capabilities: LDSME-NOTEBOOKSIDE
Status: AVailable
这是默认情况。但我计划对提到的每个 URL 执行 ping 操作(或尝试发送消息)以检查网络是否一切正常。 所以我打算提取URL信息。
因此我声明了一个字符数组 A,并尝试使用 strcpy 和 memcpy 函数将内容从 server->discoveryURL.data 复制到数组 A。
但是失败了。
for(size_t i = 0; i < serverOnNetworkSize; i++) {
UA_ServerOnNetwork *server = &serverOnNetwork[i];
strcpy(A[i], server->discoveryUrl.data);
printf("URL %d: %s\n",(unsigned long) i,A[i]);
}
它失败了,甚至 运行 都没有通过循环。需要一些指导才能输出以下格式
URL 0 : opc.tcp://hostname2:4840
URL 1 : opc.tcp://hostname:4842
URL 2 : opc.tcp://hostname:4840
我也不明白为什么,在结构字符串的 printf 语句中,“%s”在末尾给出了一个额外的字符,而“%.*s”给出了正确的输出。敬请期待指导。
编辑:我稍微修改了代码并引入了一个新的全局字符数组,并使用了 memcpy 函数。但是我正在努力,因为我在 URL 字段中获得了一个额外的字符。
char *A[] = {};
int main(){
for(size_t i = 0; i < serverOnNetworkSize; i++) {
UA_ServerOnNetwork *server = &serverOnNetwork[i];
A[i] = (char*)UA_malloc(server->discoveryUrl.length+1);
memcpy(A[i],server->discoveryUrl.data,server->discoveryUrl.length);
printf("URL %d: %.*s\n",(unsigned long) i,A[i]);
}
}
输出显示为:
URL 0: opc.tcp://o755-gksr:48401
URL 1: opc.tcp://o755-gksr:48421
末尾多了一个字符1是错误的。请提供有关如何处理该问题的任何指导。
您需要在复制后以'\0'结束字符串数据。 这样 printf 的 %s 就会知道什么时候停止:
// first we need some memory for the destination of the copy
A[i] = malloc(server->discoveryUrl.length+1); // +1 for the '[=10=]' at the end
// then we copy exactly the number of characters we want
strncpy(A[i], server->discoveryUrl.data, server->discoveryUrl.length);
// then we add the '[=10=]' terminator
A[i][server->discoveryUrl.length] = '[=10=]'; // add the '[=10=]' at the end
这是一个示例:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
// defien these so we don't need mDNS
typedef char UA_Byte;
typedef uint32_t UA_UInt32;
typedef struct {
size_t length; /* The length of the string */
UA_Byte *data; /* The content (not null-terminated) */
} UA_String;
typedef struct {
UA_UInt32 recordId;
UA_String serverName;
UA_String discoveryUrl;
size_t serverCapabilitiesSize;
UA_String *serverCapabilities;
} UA_ServerOnNetwork;
// for testing we only need one of these
UA_ServerOnNetwork serverOnNetwork[1] = {
{
1, // recordId
{3,"abcd"}, // serverName
{3,"efgh"}, // discoveryUrl
0, // serverCapabilitiesSize
NULL // serverCapabilities
}
};
int serverOnNetworkSize = sizeof(serverOnNetwork)/sizeof(serverOnNetwork[0]);
int main() {
// first print it using the %.*s printf formatter
for(size_t i = 0; i < serverOnNetworkSize; i++) {
UA_ServerOnNetwork *server = &serverOnNetwork[i];
printf("Server[%lu]: %.*s", (unsigned long) i,
(int) server->serverName.length, server->serverName.data);
printf("\n\tRecordID: %d", server->recordId);
printf("\n\tDiscovery URL: %.*s", (int) server->discoveryUrl.length,
server->discoveryUrl.data);
}
// now make an array of '[=11=]' terminated strings, fill them in, and print them
printf("\n\nURLs:");
char *A[serverOnNetworkSize];
for(size_t i = 0; i < serverOnNetworkSize; i++) {
UA_ServerOnNetwork *server = &serverOnNetwork[i];
// first we need some memory for the destination of the copy
A[i] = malloc(server->discoveryUrl.length+1); // +1 for the '[=11=]' at the end
// then we copy exactly the number of characters we want
strncpy(A[i], server->discoveryUrl.data, server->discoveryUrl.length);
// then we add the '[=11=]' terminator
A[i][server->discoveryUrl.length] = '[=11=]'; // add the '[=11=]' at the end
// and finally we print it
printf("\n\tURL %lu: %s\n", (unsigned long) i, A[i]);
}
return 0;
}