-1

One of the training exercises in my C programming book goes like following: (translated from swedish)

If you use a writing/typing terminal you kan sometimes, just like a normal typewriter, underline a word by stepping back on the line and writing _ under the word. Write a program that writes the string in the variable s underlined.

my attempt looks like this:

#include <stdio.h>

int main(void) {
  char *s;
  printf("input: ");
  scanf("%ms", &s);
  for (int i=0; s[i] != '\0'; i++) {
    printf("%c\b_", s[i]);
  }
  printf("\n");
  return 0;
}

This does not work i expect terminal output to be:

$> gcc -Wall -std=c99 file.c  
$> ./file.c  
input: test  
test //underlined
$>

but instead i get:

$> gcc -Wall -std=c99 file.c  
$> ./file.c  
input: test  
____  
$> 

does anyone know how to do that or is the book wrong?

  • 1
    Read about [ANSI escape code](https://en.wikipedia.org/wiki/ANSI_escape_code)s. – Basile Starynkevitch Sep 12 '17 at 15:39
  • Possible duplicate of [The "backspace" escape character '\b' in C, unexpected behavior?](https://stackoverflow.com/questions/6792812/the-backspace-escape-character-b-in-c-unexpected-behavior) – Neil Locketz Sep 12 '17 at 15:39
  • Read also http://utf8everywhere.org/ – Basile Starynkevitch Sep 12 '17 at 15:40
  • see: https://stackoverflow.com/a/26423857/390913 – perreal Sep 12 '17 at 15:40
  • 2
    If I'm interpreting correctly, you want to literally overlay two characters - so have the single terminal cell display both an alphabetical character and an underline, to create the impression of an underlined character. Afaik, on most **modern** terminals, this is impossible (maybe possible with some terminal-specific hackiness). While `\b` is non-destructive, printing a new character is treated as destructive. You can however print a unicode character with an underline, but you'll need a terminal that supports printing unicode. – hnefatl Sep 12 '17 at 15:43
  • 2
    It also works if you pipe it through `less` (because traditional pagers have to be able to display traditional man pages via nroff, which traditionally used overstriking because it was meant to be used on teletypes!) –  Sep 12 '17 at 15:45
  • just do `printf("\033[XD");` – perreal Sep 12 '17 at 15:48

1 Answers1

1

I haven't found a way to allow the literal rendering of one character over another, sadly (I didn't think this was possible with modern terminals, but I'm happy to be proven wrong as Wumpus Q. Wumbley has made the point that piping through less allows for this. I've not had time to look at how/why it works within less though).

I'd like to propose a workaround - there is a way to enable underscoring a little more directly using the ANSI code \033[4m.

Modifying your code:

#include <stdio.h>

int main()
{
  char *s;

  printf("input: ");
  scanf("%ms", &s);
  printf("\033[4m"); // Enable underlining
  printf("%s", s); // Print your string
  printf("\033[0m"); // Reset text attributes (disable underlining)
  printf("\n");
  return 0;
}

You can find the other ANSI graphic settings in the SGR table in the CSI Codes section on wikipedia, here.

The \033 specifies it's a terminal escape code, the combination of \e with [ specifies it's a terminal control signal, then the <number>m specifies we're doing an "SGR", "Select Graphic Rendition" command, and the number 4 as a parameter corresponds to an effect "Underline: Single". The 0 corresponds to a reset.

I welcome any corrections though, as I don't know much about the ANSI code format.


I've just skimmed through the less source, and I suspect it's converting sequences like _\ba into UTF underlined characters - but I haven't quite got to the bottom of it yet.

hnefatl
  • 5,860
  • 2
  • 27
  • 49
  • 1
    As far as I can tell, there is no provision in the Standard for `\e` being a valid character constant; this must be implementation dependent. It does appear to work in gcc for me, but a compiler warning is generated: "warning: non-ISO-standard escape sequence, '\e'". The usual escape sequence is `\x1b` or `\033`, which are ASCII hex and octal values for the ESC character, respectively. – ad absurdum Sep 12 '17 at 16:54
  • @DavidBowling Thank you for the correction - I've edited the answer. – hnefatl Sep 12 '17 at 17:26