Reputation: 3
I am using sprintf
to make nicely columned output (via printf
and fprintf
) but am having issue with variable string length when combining two strings.
For the most part, I use this and it works:
sprintf(strtmp, "%i\t%-20s\t% 2.2f\t% 2.2f", measnum,
measurementname, setvalue, measuredvalue);
When run in each measurement function, it outputs like this:
1 MeasurementNameA 75 77 8
2 MeasNameB 50 52 2
However,sometimes I want to a add to the string but keep it right adjusted. Without fixed width, the code looks like this:
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
How can I combine these without using multiple steps such that my output is:
1 MeasureNameA 75 77 8
2 MeasNameB_x1 50 52 2
3 MeasNameB_x2 51 53 6
I cannot use boost.
Maybe necessary additional information.
My pseudocode is something like this:
(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
Upvotes: 0
Views: 6615
Reputation: 27864
There are some ways you can do this, you can use a temporary buffer to generate the names and then print them:
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);
Or you can explore the wonders of variable padding:
sprintf(strtmp, "%i\t%s_setup%*i\t% 2.2f\t% 2.2f", measnum,
measurementname, strlen(measurementname) - 14, counter, setvalue, measuredvalue);
Upvotes: 2
Reputation: 1317
There's no simple way to do this via only the format specifier. You could use the * specifier in the string format to specify a dynamic string width, but that's still going to require you to calculate the name string length, as well as the added string + number length.
Upvotes: 0
Reputation:
How can I combine these without using multiple steps [...]
You can't. But you can write a helper function and use that:
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;
}
and then provide a char buf[21]
and use it like this:
sprintf(strtmp, "%i\t%s%i\t% 2.2f\t% 2.2f", measnum,
combineFixedWidth(buf, 20, measurementname, "_setup"),
counter, setvalue, measuredvalue);
Disclaimer: code typed here, untested, may contain bugs.
Upvotes: 0
Reputation: 532
You could split your sprintf
's (and, in the meantime, use snprintf
instead, for safety), and use the return value of the previous one to know exactly how much characters have been printed.
Something like that :
// 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);
}
This should work. You can change the split columns by changing the constants, and adjust for thour format. If the inputs are longer than the expected size, then no padding is done.
Upvotes: 0
Reputation: 1436
You can specify second column width when formating to maximum length of the text it'll hold. If necessary bump up that value.
printf("%-40s", "Some text");
The -
left-justifies your text in that field long 40 charcters, otherwise it would be right. There isn't any nice other way to do this.
Same applies for sprintf
and fprintf
.
If you always output to file, you can dump sprintf
and directly replace it by fprintf
.
Upvotes: 0