将sprintf用于多个输入的更好方法是什么?

时间:2019-01-09 09:59:18

标签: c

我有50多个输入要添加到缓冲区并从中创建一个字符串。 为了理解目的,可以说。

L1,L2,L3是具有多个变量的结构,例如

struct L1{
int a;
int b;
int c;
};
struct L2{
int l;
int m;
};
struct L3{
int p;
int q;
int r;
int s;
};

sprintf(buffer, "%s,%s,%d,%d,%d,%d,%d,%d,%d,%d,%d",time, pDeviceMO->getName(), L1.a, L1.b, L2.l, L3.q, L3.s, L2.m, L3.p, L3.r, L1.c);

比向文件写入缓冲区。

fprintf(File, "%s,%s\n",deviceSerialNum, buffer);

还有更好的方法吗?

对于每个输入,可能就像多个sprintf。 (从更好的编码角度来看)

2 个答案:

答案 0 :(得分:1)

没有更好的方法。例如参见内核proc输出,例如。 meminfo。您只需需要浏览所有变量。

您可以拥有一个single big call。或链接多个呼叫,例如:

int pos = 0;
pos += sprintf(&buffer[pos], "%d", var1);
pos += sprintf(&buffer[pos], "%d", var2);
pos += sprintf(&buffer[pos], "%d", var3);

(不检查错误),但是无论如何您都需要遍历所有变量。无论如何,我建议您使用snprintf

如果所有变量都具有相同的类型,则可以尝试一下:

int pos = 0;
int *list[] = { &var1, &var2, &var3, ... };
for (size_t i = 0; i < sizeof(list)/sizeof(*list); ++i) {
    pos = sprintf(&buffer[pos], "%d,", *list[i]);
}

看起来不错,但实际上没有任何意义。一旦其他人开始阅读您的代码,它将变得不可读且混乱。坚持简单的snprintf

答案 1 :(得分:0)

如果仅用50个变量拆分单个sprintf,则可以使用多个sprintf调用并使用返回值来计算下一部分的缓冲区位置。

未经测试的示例

int chars;
int pos = 0;

chars = sprintf(buffer+pos, "%s", one);
if(chars > 0) pos += chars;

chars = sprintf(buffer+pos, ",%s", two);
if(chars > 0) pos += chars;

chars = sprintf(buffer+pos, ",%d", three);
if(chars > 0) pos += chars;

...

当然,每个sprintf可以使用多个值

chars = sprintf(buffer+pos, "%s,%s,%d", one, two, three);
if(chars > 0) pos += chars;

请注意,该代码并不能防止缓冲区溢出。您可以使用snprintf来解决此问题,但是使用snprintf时,返回代码将更难处理。

如果您要对组合缓冲区进行的所有操作都将其写入文件,则可以直接fprintf各个值,这样可以避免可能的缓冲区溢出问题。

fprintf(File, "%s,",deviceSerialNum);
fprintf(File, "%s,", one);
fprintf(File, "%s,", two);
fprintf(File, "%d,", three);
/* ... */
fprintf(File, "%d\n", last);
相关问题