Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   C (http://www.programmingforums.org/forum60.html)
-   -   printf Alignment (http://www.programmingforums.org/showthread.php?t=15003)

Sane Jan 22nd, 2008 5:42 PM

printf Alignment
 
A quick question. I know printf makes aligning variables easy. But what about absolute alignment? The only alignment I can figure out to do with printf is relative.

:

printf("This is a variable %3d. This is some text.\n", 5);
printf("This is a variable %3d. This is some text.\n", 15);


That is all fine and dandy. Unsurprisingly, it aligns the variables and outputs:

:

This is a variable  5. This is some text.
This is a variable  15. This is some text.


But that is relative to the text that comes before it. What if we want absolute alignment, where the interval specifies the character's position relative to the start of the line?

:

Garbage              5. This is some text.
...                15. This is some text.


We can't use relative alignment, because then the 5 and 15 are no longer aligned with eachother, only with the text before it. Like so:

:

Garbage  5. This is some text.
...  15. This is some text.


So. We could potentially...
  • Use tabs ('\t'), but that only works if the text before each variable doesn't differ by the length of one tab.
  • Write a wrapper to printf, or use sprintf to add up each string with correct padding. But that kind of effort is a load of bullocks.
  • Perhaps rewind the cursor to the first'th position on the line, and then pad relative to that point, in effect producing an absolute pad. But is that even possible?

This is all so silly, for such a seemingly simple aesthetic.

Salem Jan 22nd, 2008 6:21 PM

Re: printf Alignment
 
An indirect approach perhaps?
:

    printf( "%-10s %3d This is some text\n", "Garbage", 5 );
    printf( "%-10s %3d This is some text\n", "...", 15 );

produces
:

$ gcc foo.c
$ ./a.exe
Garbage      5 This is some text
...        15 This is some text


Fall Back Son Jan 22nd, 2008 7:02 PM

Re: printf Alignment
 
You're simply saying that you want output where it outputs

blah blah blah 5. text text
blah blah blah blah 15. text text

So... in other words, you want the text to line up on each line in the same position regardless of the output before it, is that correct?

bldnfx Jan 22nd, 2008 7:07 PM

Re: printf Alignment
 
Is there anything analogous to setw() available in C? I was able to make some nice columns regardless of the length of the members in the first position with:

:

  1. // Some Loop prints out, say, 50 rows of:
  2.  
  3. cout << left << setw(20) << some_string
  4.               << "Number of Occurrences: " << sameWrdCnt
  5.               << endl;


And all columns come out nice nice.
Of course, this is directly from a C++ program, not C. some_string is a word that varies that varies in length in each row. (It could be different sized numbers.) The words are usually no more than a dozen characters, and then "Number of Occurrences: " and the word count all line up neatly at column twenty, regardless of first string length.

Sane Jan 22nd, 2008 8:36 PM

Re: printf Alignment
 
Salem, that would work, but unfortunately the text that comes beforehand is the result of multiple printf statements. So it's basically garbage text that I can't control. Unless I were to wrap it all into one string with sprintf. But yuck.

Ancient Dragon Jan 22nd, 2008 10:32 PM

Re: printf Alignment
 
If Salem's suggestion won't work then I guess you could move the cursor to a specific location. How to do that is os-dependent. Here is another thread that discusses that a little bit.

Ancient Dragon Jan 22nd, 2008 10:36 PM

Re: printf Alignment
 
Quote:

Originally Posted by bldnfx (Post 140099)
Is there anything analogous to setw() available in C? .

Yes, see Salem's example.

grumpy Jan 23rd, 2008 5:16 AM

Re: printf Alignment
 
Quote:

Originally Posted by Sane (Post 140104)
Salem, that would work, but unfortunately the text that comes beforehand is the result of multiple printf statements. So it's basically garbage text that I can't control. Unless I were to wrap it all into one string with sprintf. But yuck.

If you want to align something relative to the left hand column, you need to either control the preceding output (i.e. ensure that the preceding output finishes in the required position, which is what the C++ setw() approach does) or keep track of the length of what is output since the last newline.

Wrapping it into one string with sprintf() still requires you to keep track of the length of output since the last newline, but I suppose it's easier to count back if you do that.

Rewinding the cursor to the first position on a line can often be done practically for console output, by outputting a '\r' (a carriage return with no line feed). The problem with that is: any text you write to the same line will typically overwrite whatever is on the line. It also does not work for other types of output device (eg files) .... the data is still in the file. It also relies on things like console drivers, screen drivers, etc .... depending on what operating system your program runs on, and what hardware (eg display device) is attached to the machine.

Salem Jan 23rd, 2008 2:14 PM

Re: printf Alignment
 
Writing a wrapper for printf, using say vsnprintf() and some additional formatting of your own may seem a long way round, but it will give the most predictable results in the long run, and would be readily expandable to cater for future requirements.

Is glibc your standard C library by any chance?
You can register your own printf formats in this library, though I don't know if they get passed enough information to do what you want to do.

WaltP Jan 25th, 2008 1:36 AM

Re: printf Alignment
 
Quote:

Originally Posted by Sane (Post 140104)
Salem, that would work, but unfortunately the text that comes beforehand is the result of multiple printf statements. So it's basically garbage text that I can't control. Unless I were to wrap it all into one string with sprintf. But yuck.

Yuck indeed.

printf() returns the number of characters output. So use the return value to count the number of characters already displayed and use the '*' formatting character to align your numbers.

Another thing to know is how the %s modifier work. Run this to understand the details in how %n.ms formatting works:
:

#include <stdio.h>
#include <string.h>
#define NEXTCOL 38

int main()
{
    char *strs      = "ABCDEF";
    char *strl      = "ABCDEFGHIJKL";
    int  sizesingle= 9;
    int  size[][2]= {  3,  3,  -3,  3,    3,  9,  -3,  9,
                        3, -3,    3, -9,  -3, -3,  -3, -9,
                        3, 15,    3,-15,  -3, 15,  -3,-15,
                        0,  0,
                        9,  3,  -9,  3,  -9,  9,  -9, -3,
                        -9, -9,  -9, 15,  -9, -15,  9,  9,
                        9, -9,    9, -3,    9,  15,  9,-15,
                        0,  0,
                        15,  3,  15,  9,  15, -3,  15, -9,
                        15, 15,  15,-15,  -15,  3,  -15,  9,
                      -15, -9,  -15, 15,  -15,-15,  -15, -3,
                        -1,  0
                      };
    char buf[20];
               
    int  i = 0;
    int  j;
   
    j = printf("  Short -- %d chars <%s> ", strlen(strs), strs);
    while (j++ < NEXTCOL)  putchar(' ');
    printf("  Long -- %d chars <%s>  \n", strlen(strl), strl);
    printf("\n");
   
    j = sprintf(buf,"%*s", sizesingle, strs);
    j = printf("      %%%3ds (%2d)  <%s> ", sizesingle, j, buf);
    while (j++ < NEXTCOL)  putchar(' ');
    j = sprintf(buf,"%*s", sizesingle, strl);
    j = printf("      %%%3ds (%2d)  <%s> ", sizesingle, j, buf);
    printf("\n");
   
    j = sprintf(buf,"%*s", -sizesingle, strs);
    j = printf("      %%%3ds (%2d)  <%s> ", -sizesingle, j, buf);
    while (j++ < NEXTCOL)  putchar(' ');
    j = sprintf(buf,"%*s", -sizesingle, strl);
    j = printf("      %%%3ds (%2d)  <%s> ", -sizesingle, j, buf);
    printf("\n");
   
    j = sprintf(buf,"%.*s", sizesingle, strs);
    j = printf("      %%.%2ds (%2d)  <%s> ", sizesingle, j, buf);
    while (j++ < NEXTCOL)  putchar(' ');
    j = sprintf(buf,"%.*s", sizesingle, strl);
    j = printf("      %%.%2ds (%2d)  <%s> ", sizesingle, j, buf);
    printf("\n");
   
    j = sprintf(buf,"%.*s", -sizesingle, strs);
    j = printf("      %%.%2ds (%2d)  <%s> ", -sizesingle, j, buf);
    while (j++ < NEXTCOL)  putchar(' ');
    j = sprintf(buf,"%.*s", -sizesingle, strl);
    j = printf("      %%.%2ds (%2d)  <%s> ", -sizesingle, j, buf);
    printf("\n");
   
    printf("\n");

    while (size[i][0] != -1)
    {
            if (size[i][0] != 0)
            {
            j = sprintf(buf,"%*.*s", size[i][0], size[i][1], strs);
            j = printf("  %%%3d.%3ds (%2d)  <%s> ", size[i][0], size[i][1], j, buf);
            while (j++ < NEXTCOL)  putchar(' ');
            j = sprintf(buf,"%*.*s", size[i][0], size[i][1], strl);
            j = printf("  %%%3d.%3ds (%2d)  <%s> ", size[i][0], size[i][1], j, buf);
        }
        printf("\n");
        i++;
    }
    printf("done... \n");
    return 0;
}



All times are GMT -5. The time now is 3:52 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC