Hacker News new | ask | show | jobs
by Someone 2206 days ago
One use is aligning outputs:

  char *prefix = "example";
  char *line1 = "line 1";
  char *line2 = "line 2";
  printf("%s: %n%s\n", prefix, &n, line1);
  printf("%*s%s\n", n, "", line2);
will output

  example: line 1
           line 2
That’s a bit more robust than using strlen(s)+2, where you have to keep that magic constant 2 in sync with ": ". Moving ": " to a variable and using strlen(s)+strlen(separator) would fix that, though (at the price of speed, unless you’ve a compiler that optimizes that away)
3 comments

> That’s a bit more robust than using strlen(s)+2

strlen wouldn't even be an option if you were formatting something that's not a string e.g.

    int n;
    int prefix_num = 23;
    char *line1 = "line 1";
    char *line2 = "line 2";
    printf("example %d: %n%s\n", prefix_num, &n, line1);
    printf("%*s%s\n", n, "", line2);
This only works if you're not dealing with Unicode, where the number of bytes, the number of characters, and the width of those characters can all vary.
You don’t need Unicode for that. It also requires you use a monospaced font.

I think the feature predates that and Unicode, though. But even then, it fails if you underline text the way it was done at the time, either by using backspace and underline characters or by using termcap (https://en.wikipedia.org/wiki/Termcap)

This makes me wonder if there's some sort of Unicode equivalent for this?
wcwidth()
Thanks, I wasn't aware of this. Here's a man page for anyone else that was interested: https://man7.org/linux/man-pages/man3/wcwidth.3.html
I'd never heard of %n, but I use printf's return value (the number of bytes written) for this kind of purpose, so

  n = printf("%s: ", prefix);
  printf("%s\n", line1);
  printf("%*s%s\n", n, " ", line2);
Yeah but the difference is that you can use %n wherever you need it in the format string. Depending on what arguments come after it figuring out the length of the printed arguments might not be trivial whereas with printf, it already has to keep a count of it during execution in order to return it at the end so it's easy to add support for it.