使用具有固定宽度、左对齐字段和串联的 sprintf
Use sprintf with fixed width, left-justified field and concatenation
我正在使用 sprintf
制作漂亮的分栏输出(通过 printf
和 fprintf
),但是在组合两个字符串时遇到可变字符串长度的问题。
在大多数情况下,我使用它并且它有效:
sprintf(strtmp, "%i\t%-20s\t% 2.2f\t% 2.2f", measnum,
measurementname, setvalue, measuredvalue);
在每个测量函数中运行时,输出如下:
1 MeasurementNameA 75 77 8
2 MeasNameB 50 52 2
然而,有时我想添加到字符串但保持正确调整。如果没有固定宽度,代码如下所示:
sprintf(strtmp, "%i\t%s_setup%i\t% 2.2f\t% 2.2f", measnum,
measurementname, counter, setvalue, measuredvalue);
1 MeasureNameA 75 77 8
2 MeasNameB_setup1 50 52 2
3 MeasNameB_setup2 50 51 6
如何在不使用多个步骤的情况下将这些组合起来,这样我的输出是:
1 MeasureNameA 75 77 8
2 MeasNameB_x1 50 52 2
3 MeasNameB_x2 51 53 6
我无法使用 boost。
可能需要更多信息。
我的伪代码是这样的:
(measurementA)
-Setup measurement A -
-Take measurement A -
-sprintf
-printf, fprintf
(measB)
-Setup measurement B
for(x=1; x<10; x++)
-Set x
-Take measurement B
-sprintf
-printf, fprintf
-end for loop
您可以在格式化时指定第二列的宽度,以达到它将容纳的文本的最大长度。如有必要,请提高该值。
printf("%-40s", "Some text");
-
左对齐您在该字段中的文本长 40 个字符,否则就是正确的。没有任何其他好方法可以做到这一点。
同样适用于 sprintf
和 fprintf
.
如果一直输出到文件,可以转储sprintf
,直接替换成fprintf
。
How can I combine these without using multiple steps [...]
你不能。但是你可以编写一个辅助函数并使用它:
const char *combineFixedWidth(char *buf, size_t width, const char *str, const char *suff)
{
size_t len, slen;
memset(buf, ' ', width);
buf[width] = 0;
len = strlen(str);
slen = strlen(suff);
if (len > width)
{
memcpy(buf, str, width);
return buf;
}
memcpy(buf, str, len);
width -= len;
if (slen < width) width = slen;
memcpy(buf+len, suff, width);
return buf;
}
然后提供一个char buf[21]
并像这样使用它:
sprintf(strtmp, "%i\t%s%i\t% 2.2f\t% 2.2f", measnum,
combineFixedWidth(buf, 20, measurementname, "_setup"),
counter, setvalue, measuredvalue);
免责声明:此处输入的代码未经测试,可能包含错误。
您可以拆分您的 sprintf
(同时,为了安全起见,请使用 snprintf
),并使用前一个的 return 值来了解到底打印了多少字符。
类似的东西:
// Will split in columns = 10, 50, 60
void formatMyString(int num, char *name, int counter, float setval, float mes)
{
char buf[256] = {0};
int cnt = 0;
cnt = snprintf(buf, 256-cnt, "%i ", num);
if (cnt < 10) {
memset(&buf[cnt], ' ', 10-cnt);
cnt = 10;
}
cnt += snprintf(&buf[cnt], 256-cnt, "%s_setup%i ", name, counter);
if (cnt < 50) {
memset(&buf[cnt], ' ', 50-cnt);
cnt = 50;
}
cnt += snprintf(&buf[cnt], 256-cnt, "%2.2f ", setval);
if (cnt < 60) {
memset(&buf[cnt], ' ', 60-cnt);
cnt = 60;
}
snprintf(&buf[cnt], 256-cnt, "%2.2f", mes);
printf("%s\n", buf);
}
这应该有效。您可以通过更改常量来更改拆分列,并根据您的格式进行调整。
如果输入长于预期大小,则不进行填充。
没有仅通过格式说明符即可完成此操作的简单方法。您可以在字符串格式中使用 * 说明符来指定动态字符串宽度,但这仍然需要您计算名称字符串长度,以及添加的字符串 + 数字长度。
有一些方法可以做到这一点,您可以使用临时缓冲区生成名称然后打印它们:
char buf[64];
snprintf(buf, 64, "%s_setup%i", measurementname, counter);
sprintf(strtmp, "%i\t%-20s\t% 2.2f\t% 2.2f", measnum, buf, setvalue, measuredvalue);
或者您可以探索可变填充的奥妙:
sprintf(strtmp, "%i\t%s_setup%*i\t% 2.2f\t% 2.2f", measnum,
measurementname, strlen(measurementname) - 14, counter, setvalue, measuredvalue);
我正在使用 sprintf
制作漂亮的分栏输出(通过 printf
和 fprintf
),但是在组合两个字符串时遇到可变字符串长度的问题。
在大多数情况下,我使用它并且它有效:
sprintf(strtmp, "%i\t%-20s\t% 2.2f\t% 2.2f", measnum,
measurementname, setvalue, measuredvalue);
在每个测量函数中运行时,输出如下:
1 MeasurementNameA 75 77 8
2 MeasNameB 50 52 2
然而,有时我想添加到字符串但保持正确调整。如果没有固定宽度,代码如下所示:
sprintf(strtmp, "%i\t%s_setup%i\t% 2.2f\t% 2.2f", measnum,
measurementname, counter, setvalue, measuredvalue);
1 MeasureNameA 75 77 8
2 MeasNameB_setup1 50 52 2
3 MeasNameB_setup2 50 51 6
如何在不使用多个步骤的情况下将这些组合起来,这样我的输出是:
1 MeasureNameA 75 77 8
2 MeasNameB_x1 50 52 2
3 MeasNameB_x2 51 53 6
我无法使用 boost。
可能需要更多信息。
我的伪代码是这样的:
(measurementA)
-Setup measurement A -
-Take measurement A -
-sprintf
-printf, fprintf
(measB)
-Setup measurement B
for(x=1; x<10; x++)
-Set x
-Take measurement B
-sprintf
-printf, fprintf
-end for loop
您可以在格式化时指定第二列的宽度,以达到它将容纳的文本的最大长度。如有必要,请提高该值。
printf("%-40s", "Some text");
-
左对齐您在该字段中的文本长 40 个字符,否则就是正确的。没有任何其他好方法可以做到这一点。
同样适用于 sprintf
和 fprintf
.
如果一直输出到文件,可以转储sprintf
,直接替换成fprintf
。
How can I combine these without using multiple steps [...]
你不能。但是你可以编写一个辅助函数并使用它:
const char *combineFixedWidth(char *buf, size_t width, const char *str, const char *suff)
{
size_t len, slen;
memset(buf, ' ', width);
buf[width] = 0;
len = strlen(str);
slen = strlen(suff);
if (len > width)
{
memcpy(buf, str, width);
return buf;
}
memcpy(buf, str, len);
width -= len;
if (slen < width) width = slen;
memcpy(buf+len, suff, width);
return buf;
}
然后提供一个char buf[21]
并像这样使用它:
sprintf(strtmp, "%i\t%s%i\t% 2.2f\t% 2.2f", measnum,
combineFixedWidth(buf, 20, measurementname, "_setup"),
counter, setvalue, measuredvalue);
免责声明:此处输入的代码未经测试,可能包含错误。
您可以拆分您的 sprintf
(同时,为了安全起见,请使用 snprintf
),并使用前一个的 return 值来了解到底打印了多少字符。
类似的东西:
// Will split in columns = 10, 50, 60
void formatMyString(int num, char *name, int counter, float setval, float mes)
{
char buf[256] = {0};
int cnt = 0;
cnt = snprintf(buf, 256-cnt, "%i ", num);
if (cnt < 10) {
memset(&buf[cnt], ' ', 10-cnt);
cnt = 10;
}
cnt += snprintf(&buf[cnt], 256-cnt, "%s_setup%i ", name, counter);
if (cnt < 50) {
memset(&buf[cnt], ' ', 50-cnt);
cnt = 50;
}
cnt += snprintf(&buf[cnt], 256-cnt, "%2.2f ", setval);
if (cnt < 60) {
memset(&buf[cnt], ' ', 60-cnt);
cnt = 60;
}
snprintf(&buf[cnt], 256-cnt, "%2.2f", mes);
printf("%s\n", buf);
}
这应该有效。您可以通过更改常量来更改拆分列,并根据您的格式进行调整。 如果输入长于预期大小,则不进行填充。
没有仅通过格式说明符即可完成此操作的简单方法。您可以在字符串格式中使用 * 说明符来指定动态字符串宽度,但这仍然需要您计算名称字符串长度,以及添加的字符串 + 数字长度。
有一些方法可以做到这一点,您可以使用临时缓冲区生成名称然后打印它们:
char buf[64];
snprintf(buf, 64, "%s_setup%i", measurementname, counter);
sprintf(strtmp, "%i\t%-20s\t% 2.2f\t% 2.2f", measnum, buf, setvalue, measuredvalue);
或者您可以探索可变填充的奥妙:
sprintf(strtmp, "%i\t%s_setup%*i\t% 2.2f\t% 2.2f", measnum,
measurementname, strlen(measurementname) - 14, counter, setvalue, measuredvalue);