skip to Main Content

I intend to develop a command line tool by C in the CentOS, with the following code:

// client.c

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

#include <unistd.h>
#include <termios.h>

int main(int argc, char *argv[])
{
    char command[128];

    while (1)
    {
        memset(command, 0, 128);
        printf("cli > ");
        if (fgets(command, 128, stdin) != NULL)
        {
            if (strcmp(command, "exitn") == 0)
                break;
            if (strcmp(command, "n") == 0)
                continue;
            printf("do something ... %s", command);
        }
    }

    return 0;
}

The program can works, but it doesn’t execute the way I expect it to when I press the arrow keys.

I have finished typing a simple SQL and now the cursor stays after the semicolon.

[root@olap tests]# gcc client.c 
[root@olap tests]# ./a.out 
cli > selectt * from table_001;

But I misspelled the first keyword, it should be select, not selectt.
I am now pressing the left arrow key(←) to try to fix this mistake.
But the cursor didn’t move properly as I expected, and it turned into the following.

[root@olap tests]# gcc client.c 
[root@olap tests]# ./a.out 
cli > selectt * from table_001;^[[D^[[D^[[D^[[D^[[D^[[D^[[D

How should I modify the program to solve this problem?

I hope get help from people who are good at C development.

Thank you all

2

Answers


  1. You might want to try the ncurses library with getch

    This sample code demonstrates how you can detect arrow keys and have a CLI prompt:

    #include <string.h>
    #include <ncurses.h>
    
    int main(int argc, char *argv[])
    {
      int ch,i;
      char command[128];
    
      initscr();
      clear();
      noecho();
      cbreak();
      keypad(stdscr, true);
    
      while (1) {
          printw("cli> ");
          for (i=0;;i++) {
              ch=getch();
                
              if (ch==KEY_UP||ch==KEY_LEFT||ch==KEY_RIGHT||ch==KEY_DOWN) {
                  /* printw("arrow keys pressed!");
                  command[i]='';
                  break; */
                  i--;
              }
              else if (ch=='n') {
                  if (i>0)
                      printw("n");
                  command[i]='';
                  break;
              }
              else {
                  command[i]=ch;
                  printw("%c",ch);
              }
          }
          if (strcmp(command, "exit") == 0)
              break;
          else
              printw("%sn", command);
            
        }
        endwin();
    
        return 0;
    }
    
    Login or Signup to reply.
  2. Consider using the readline library, you can find it here. It supports arrow keys, a input history and input of any length (if configured).

    char *input = readline("cli >");
    if (input)
    {
        if (strcmp(command, "exitn") == 0)
        ...
        free(input);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search