Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove a character from a Linux terminal in C

Tags:

c

linux

terminal

How can I remove a character on the terminal before the cursor in Linux? In the past I used something like this:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define KEY_BACKSPACE 127

int main(){
    printf("%s", "abc"); // add something so we can see if delete works
    char * buf = malloc(3*sizeof(char));
    *(buf+0)=KEY_BACKSPACE;
    *(buf+1)=' ';
    *(buf+2)=KEY_BACKSPACE;
    write(1,buf,3);
    free(buf);
}

This is only a small example demonstrating this technique. In the original program I disabled canonical mode and handled every keystroke myself. That's why I needed to remove characters.

Writing backspace, space, backspace worked fine in my original program. Now when I run same program after a few years, it didn't remove anything. What changed? What can I do to fix this?

like image 297
user224348 Avatar asked Nov 30 '25 01:11

user224348


2 Answers

As I noted in a comment, you need to use backspace instead of '\177' (or '\x7F') to move backwards. You also have to worry about buffering of standard I/O. It's often best not to use a mixture of standard I/O and file descriptor I/O on the same stream — standard output in this example. Use one or the other, but not both.

This works:

#include <unistd.h>

int main(void)
{
    char buff1[] = "abc";
    char buff2[] = "\b \b";
    write(STDOUT_FILENO, buff1, sizeof(buff1) - 1);
    sleep(2);
    write(STDOUT_FILENO, buff2, sizeof(buff2) - 1);
    sleep(2);
    write(STDOUT_FILENO, "\n", 1);
    return 0;
}

It shows first (for 2 seconds):

abc

then (for another 2 seconds):

ab

then it exits. The cursor is after c at first, then after b.

like image 119
Jonathan Leffler Avatar answered Dec 01 '25 16:12

Jonathan Leffler


As explained by Jonathan Leffler in the comment, your code needs two modifications:

  • The rubout character understood by the typical terminal (emulator) is '\b' (or 8), not 127.
  • printf() is line-buffered by default when writing to a TTY. This means that you need to call fflush(stdout) between calls to printf() and write(). Without flushing abc will only be printed at program exit, so the deletion sequence will be emitted before the contents it is supposed to delete, which renders it inoperative.
like image 31
user4815162342 Avatar answered Dec 01 '25 16:12

user4815162342



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!