我有一个结构:
typedef struct message
{
char* dchatver;
int contype;
int conlen;
char* context;
} message_t;
我需要一个函数来获取指向已填充message_t
的指针,该函数会将message_t
写入文件描述符。 message_t可以包含dchatver = "DCHAT:1.0"; contype = 3; conlen = 6; context = "hello";
我希望将其连接到一个char[totallength]
,看起来像" DCHAT:1.0\n3\n6\nhello\n
"
我的问题是如何将dchatver
,contype
,conlen
和context
连接到一个char*
,以便将其用于写入?我考虑过使用snprintf
,但我不知道如何确定给定message_t
的长度。
答案 0 :(得分:1)
void WriteMessage(int fd, message_t *message)
{
char *writeBuf=NULL;
size_t writeBufSize;
/* Determine the size of the output string. */
writeBufSize = 1 + snprintf(NULL, 0, "%s\n%d\n%d\n%s\n",
message->dchatver,
message->contype,
message->conlen,
message->context
);
/* Allocate memory for the string */
writeBuf = malloc(writeBufSize);
/* Initialize the string. */
snprintf(writeBuf, writeBufSize, "%s\n%d\n%d\n%s\n",
message->dchatver,
message->contype,
message->conlen,
message->context
);
/* write the record */
write(fd, writeBuf, writeBufSize - 1);
free(writeBuf);
return;
}
答案 1 :(得分:0)
您可以使用dchatver
找到context
和strlen
的长度。要查找contype
和conlen
的长度比较困难,但您可以采取捷径。您可以使用以下方法计算其最大长度,而不是查找这些特定字段的长度:
#include <limits.h>
#define INT_STR_LEN_UPPER_BOUND (sizeof (int) * CHAR_BIT * 3.4)
因此,您可以为每个int
字段分配这么多空间,将其传递给snprintf
,然后在其上使用strlen
来获取整个字符串的实际长度。像这样:
size_t s = strlen (msg->dchatver) + strlen (msg->context) +
sizeof (int) * 54.4 + 4;
char *out = calloc (s, sizeof *out);
snprintf (out, s, "%s %d %d %s", msg->dchatver, msg->contype,
msg->conlen, msg->context);
答案 2 :(得分:0)
我正在解释这意味着您要将变量值打印到屏幕上。
如果您确定每个char *都正确地以null结尾,则可以使用sprintf()而不是snprintf()。
例如,这将在新行上打印出每个变量,其中的字符串用引号括起来:
char buf[256]; // make sure this buffer is large enough
message_t msg;
//
// assuming the variable 'msg' gets filled in here
//
sprintf(buf, "dchatver = \"%s\"\ncontype = %d\nconlen = %d\ncontext = \"%s\"\n",
msg.dchatver,
msg.contype,
msg.conlen,
msg.context);
// print the string to console, or do other stuff
printf("%s\n", buf);
答案 3 :(得分:0)
这是一个可以将message_t
转换为您想要使用的格式的字符串的函数。
char* messageToString(message_t m)
{
char buffer1[50]; // If your numbers can occupy more than 50 spaces,
char buffer2[50]; // these will have to be updated.
char* ret = NULL;
size_t len = 0;
sprintf(buffer1, "\n%d", m.contype);
sprintf(buffer2, "\n%d\n", m.conlen);
len = strlen(m.dchatver) + strlen(buffer1) + strlen(buffer2) + strlen(m.context);
ret = malloc(len+2); // One extra for the newline. One extra for the null
strcpy(ret, m.dchatver);
strcat(ret, buffer1);
strcat(ret, buffer2);
strcat(ret, m.context);
strcat(ret, "\n");
return ret;
}
确保在返回的值上调用free
以防止内存泄漏。
答案 4 :(得分:0)
诀窍在于,您不必知道格式化消息字符串的长度,您只需要一个上限即可。并且您知道格式化的消息永远不会超过strlen(dchatver)
+ 10(对于contype)+ 10(对于conlen)+ conlen(对于上下文)+ 3(对于&#39; \ n&#39 ; S)。 (conlen显然包含尾随null的空间,因此我们不必为此添加一个空格,但为了以防万一,它可能是好的。)
幻数10假设你的int
类型是32位,并且总是正数,如果这些不是安全的假设,你必须做更多的数学运算。
我喜欢这样做是为了灵活性。 (我的C生锈了,所以这里可能存在语法错误)
//this allows you to format to preallocated buffers, saving you
//allocation overhead, and possibly copy overhead
int printf_message(char* buffer, int len, message_t* msg)
{
assert(msg->conlen == strlen(msg->context)+1); //just in case
int r = snprintf(buffer, len, "%s\n%d\n%d\n%s\n",
msg->dchatver, msg->contype, msg->conlen, msg->context);
return r;
}
//this is slightly easier to use, with a small potential overhead
//free the return pointer with "free" when you're done
char* get_formatted_message(message_t* msg)
{
//contype is a 32bit positive integer, and therefore a maximum of 10 digits
//conlen is a 32bit positive integer, and therefore a maximum of 10 digits
//we need 3 '\n's, and one '\0'.
int len = strlen(msg->dchatver) + conlen + 24;
char* buffer = malloc(len);
if (buffer)
{
printf_message(buffer, len, msg);
}
return buffer;
}