让我解释一下情况: 我有一个C结构如下:
typedef struct {
int *val;
char *name;
} tStruct;
此结构可能填充如下: - 如果“val”值不可用,则val可以为null,否则val是整数值(可以是负数) - 如果名称不可用,则name可以是空字符串;如果名称可用,则name可以是填充字符串(此处不是空指针)。
我希望写一个日志行如下:
LOG val =#name = WOOT
LOG val =#name =#
LOG val = 123456 name =#
LOG val = 123456 name = WOOT
这意味着我需要使用printf(“val =%s name =%s”,...)或printf(“val =%d name =%s”,...),具体取决于id值(这样我可以输出#或整数)。当val无效时输出伪整数值是不合适的,因为任何有符号或无符号值都是可能的。
有什么想法吗?我希望我可以避免使用以下类型的构造,因为我的struct实际上会包含很多字段,使得“if”组合太多了:
if ( (struct.val == NULL ) && ( struct.name ) ) then printf ("val=# name=%");
else if ((struct.val == NULL ) && ( ! struct.name ) ) then printf ("val=# name=#");
else if ...
谢谢
答案 0 :(得分:3)
创建一个返回该类型的字符串表示形式的函数,然后在printf
中使用它printf("%s", tStruct_to_string(contents));
请注意,除非你的转换函数有一些静态缓冲区,否则很难以的方式使用它。
编辑:这里使用单个静态缓冲区是错误的,因为它不适用于多个参数。正如@pmg所说,接受缓冲区更好,但风险缓冲区溢出,所以也许你可以传递长度作为参数,但现在优雅的解决方案并不像它那样优雅。因此,您的函数可以返回malloced char *,但之后您可以释放它,并且动态分配可能很慢。 Ufff ...在C中管理字符串是相当痛苦的。
我现在能想到的最好的方法(但是它存在重入问题)是拥有静态字符串数组并在每次调用时循环使用它们。
char* tStruct_to_string(tStruct st)
{
/*
* here assuming no one will call printf
* with more than 32 arguments of this type,
* and assuming length of string 100.
*/
static char strings[32][100];
static int next = 0;
int current = next;
// here you write to strings[current]
// use s(n)printf for writing to string
next = (next+1)%32;
return strings[current];
}
此外,其他答案提供了如何避免重复条件的极好建议。
答案 1 :(得分:2)
printf("LOG val=");
if (struct.val) printf("%d", *struct.val); else printf("#");
printf(" name=");
if (*struct.name) printf("%s", struct.name); else printf("#");
printf("\n");
答案 2 :(得分:1)
对于val
成员,您必须使用if
语句,因为输出是字符串或数字,但对于name
,您可以使用ternary expression }:
if (str.val)
printf("val=%d name=%s", *str.val, *str.name == '\0' ? "#" : str.name);
else
printf("val=# name=%s", *str.name == '\0' ? "#" : str.name);
答案 3 :(得分:1)
如果你的结构有很多这样的对,那么显而易见的是将一个对的打印分解为一个函数,然后为实际结构中的每一对调用它。
void print_pair(const int *value, const char *name)
{
if(value == NULL && name == NULL)
printf("val=# name=#");
else if(value == NULL && name != NULL)
printf("val=# name=%s", name);
else if(value != NULL && name == NULL)
printf("val=%d name=#", *value);
else
printf("val=%d name=%s", *value, name);
}
您可以使用#
也可以表示为字符串的事实来缩短上述内容。
你可以通过分解出以两种方式将整数转换为字符串的想法来缩短它,但这可能会过度:
void print_pair(const int *value, const char *name)
{
char vbuf[32];
if(value == NULL)
strcpy(vbuf, "#");
else
snprintf(vbuf, sizeof vbuf, "%d", *value);
printf("val=%s name=%s", vbuf, name != NULL ? name : "#");
}
答案 4 :(得分:1)
为什么要通过所有这些努力将所有内容压缩到一个printf调用中?只需打两次电话。
if (s.val)
printf("val=%d ", *s.val);
else
printf("val=# ");
printf("s.name=%s", s.name ? *s.name : "#");