zoukankan      html  css  js  c++  java
  • 实现一个简单的行编辑器(优化)

    0.目录

    1.前言

    2.使用方向键来实现光标左右移动

    3.按两下ESC键退出程序

    4.移动光标到行首

    5.移动光标到行尾

    6.总代码

    1.前言

    之前已经写过一篇文章了:实现一个简单的行编辑器
    实现的功能有:
    1.按下大小写字母或者数字的时候,显示在屏幕上
    2.可以使用退格键来删除前一个字符
    3.可以使用Del键来删除一行
    4.使用'['键来实现光标左移
    5.使用']'键来实现光标右移

    但是还是有很多不完善的地方。本篇文章修改以及添加了以下功能:
    1.使用方向键'←'键来实现光标左移
    2.使用方向键'→'键来实现光标右移
    3.按两下ESC键退出程序
    4.使用'['键来实现移动光标到行首
    5.使用']'键来实现移动光标到行尾

    并且在之前的文章中,采用的是putchar('');实现光标左移,使用输出当前字符实现光标右移。
    在这篇文章中,将更改这种方法。

    2.使用方向键来实现光标左右移动

    在之前的文章中提到过。方向键其实是一次性输入了三个字符才组成的。
    以下是对应关系:
    上:0x1b 0x5b 0x41
    下:0x1b 0x5b 0x42
    左:0x1b 0x5b 0x44
    右:0x1b 0x5b 0x43
    Del键:0x1b 0x5b 0x33 0x7e
    其中,0x41、0x42、0x43、0x44分别就是大写字母A、B、C、D。
    在本篇文章中不实现上和下的功能。

    //连续输出三个字符实现左移光标
    putchar(0x1b);
    putchar(0x5b);
    putchar(0x44);
    //连续输出三个字符实现右移光标
    putchar(0x1b);
    putchar(0x5b);
    putchar(0x43);
    

    在while循环中实现:

    else if ( c == 0x1b )
    {
        c=getchar();
        if ( c == 0x5b )
        {
            c=getchar();
            if ( c == 0x44 && p )
            {
                //连续输出三个字符实现左移光标
                putchar(0x1b);
                putchar(0x5b);
                putchar(0x44);
                p--;
            }
            else if ( c == 0x43 && p < len )
            {
                //连续输出三个字符实现右移光标
                putchar(0x1b);
                putchar(0x5b);
                putchar(0x43);
                p++;
            }
            else continue;
        }
        else continue;
    }
    

    这里使用了一个叫做状态机的概念。
    有兴趣的可以去找找相关的资料了解一下。

    3.按两下ESC键退出程序

    只需要在上面的程序中加入一段代码就行了。
    顺便将Del键也改一下:

    else if ( c == 0x1b )
    {
        c=getchar();
        if ( c == 0x5b )
        {
            c=getchar();
            if ( c == 0x44 && p )
            {
                //连续输出三个字符实现左移光标
                putchar(0x1b);
                putchar(0x5b);
                putchar(0x44);
                p--;
            }
            else if ( c == 0x43 && p < len )
            {
                //连续输出三个字符实现右移光标
                putchar(0x1b);
                putchar(0x5b);
                putchar(0x43);
                p++;
            }
            else if ( c == 0x33 )
            {
                c=getchar();
                if ( c == 0x7e )
                {
                    //删除键(Del):删除整行(user input delete)
                    //1.从光标处移动到结尾
                    while( ++p <= len )
                        putchar(' ');
                    //2.从结尾往前依次退格
                    while( --p )
                        fun_backspace();
                    //3.len置0
                    len = 0;
                }
                else continue;
            }
            else continue;
        }
        else if ( c == 0x1b )
        {
            //按了两次ESC键,退出程序
            break;
        }
        else continue;
    }
    

    4.移动光标到行首

    使用'['键来实现移动光标到行首

    else if ( c == '[' && p )
    {
        //使用'['移动光标到行首
        while( p-- )
            fun_left();
        p = 0;
    }
    

    5.移动光标到行尾

    使用']'键来实现移动光标到行尾

    else if ( c == ']' && p < len )
    {
        //使用']'移动光标到行尾
        while( p++ < len )
            fun_right();
        p = len;
    }
    

    6.总代码

    /* 设计完成一个行编辑器
     * 能够接受用户输入,能倒退删除,插入,移动光标等
     */
    #include   <stdio.h>
    #include   <termios.h>
    
    #define oops(s, x) { perror(s); exit(x); }
    
    void fun_set(struct termios *info, char set);//设置回显位,设置缓冲
    void fun_backspace();//实现退格功能
    void fun_left();//实现光标左移
    void fun_right();//实现光标右移
    
    int main()
    {
        int c;
        int i, j;
    
        struct termios info;
        fun_set( &info, 0 );//关掉回显位,关掉缓冲
        
        char str[30];//保存输出的字符
        int p = 0;//当前位置
        int len = 0;//总长度
    
        while( ( c=getchar() ) != EOF )
        {
            if( isalnum(c) )
            {
                //isalnum()函数:如果c是一个数字或字母返回非0值,否则为0
                //user input a letter or a number
                //1.将当前位置之后的值依次后移
                j = ++len;
                while( j-- > p )
                    str[j] = str[j-1];
                str[p] = c;
                j = len - p - 1;//光标要移动的距离
                //2.从当前位置开始重新输出数组
                while( p < len )
                    putchar(str[p++]);
                //3.将光标移动到之前的位置
                while( j-- > 0 && p-- )
                    fun_left();
            }
            else if( c == 0x7f && p )
            {
                //退格键(user input a backspace)
                j = len - p;//光标要移动的距离
                //1.将当前位置之后的值依次前移
                putchar('');
                while( p < len )
                {
                    str[p-1] = str[p];
                    putchar(str[p]);
                    p++;
                }
                //2.将最后一个元素删除
                putchar(' ');
                putchar('');
                len--;
                p--;
                //3.将光标移动到之前的位置
                while( j-- > 0 && p-- )
                    fun_left();
            }
            else if ( c == 0x1b )
            {
                c=getchar();
                if ( c == 0x5b )
                {
                    c=getchar();
                    if ( c == 0x44 && p )
                    {
                        //连续输出三个字符实现左移光标
                        fun_left();
                        p--;
                    }
                    else if ( c == 0x43 && p < len )
                    {
                        //连续输出三个字符实现右移光标
                        fun_right();
                        p++;
                    }
                    else if ( c == 0x33 )
                    {
                        c=getchar();
                        if ( c == 0x7e )
                        {
                            //删除键(Del):删除整行(user input delete)
                            //1.从光标处移动到结尾
                            while( ++p <= len )
                                putchar(' ');
                            //2.从结尾往前依次退格
                            while( --p )
                                fun_backspace();
                            //3.len置0
                            len = 0;
                        }
                        else continue;
                    }
                    else continue;
                }
                else if ( c == 0x1b )
                {
                    //按了两次ESC键,退出程序
                    break;
                }
                else continue;
            }
            else if ( c == '[' && p )
            {
                //使用'['移动光标到行首
                while( p-- )
                    fun_left();
                p = 0;
            }
            else if ( c == ']' && p < len )
            {
                //使用']'移动光标到行尾
                while( p++ < len )
                    fun_right();
                p = len;
            }
        }
    
        fun_set( &info, 1 );//打开回显位,打开缓冲
    }
    
    void fun_set(struct termios *info, char set)
    {
        if ( tcgetattr(0, info) == -1 )          /* get attribs   */
            oops("tcgettattr", 1);
        /*set为1,打开回显位,打开缓冲;set为0,关掉回显位,关掉缓冲*/
        if( set )
        {
            (*info).c_lflag |= ECHO;    /* turn on bit   */
            (*info).c_lflag &= ICANON;  /* turn on bit   */
        }
        else
        {
            (*info).c_lflag &= ~ECHO;   /* turn off bit   */
            (*info).c_lflag &= ~ICANON; /* turn off bit   */
        }
        if ( tcsetattr(0, TCSANOW, info) == -1 ) /* set attribs    */
            oops("tcsetattr",2);
    }
    
    void fun_backspace()
    {
        putchar('');
        putchar(' ');
        putchar('');
    }
    
    void fun_left()
    {
        putchar(0x1b);
        putchar(0x5b);
        putchar(0x44);
    }
    
    void fun_right()
    {
        putchar(0x1b);
        putchar(0x5b);
        putchar(0x43);
    }
    
    
  • 相关阅读:
    css清除浮动
    对象遍历
    vue 小工具
    数据库优化-聚合索引
    mysql修改唯一索引
    输出带pre的调试信息
    mysql的group by优化跟limit优化
    地址联动数据抓取
    php7新特新
    linux同步系统时间
  • 原文地址:https://www.cnblogs.com/PyLearn/p/8035039.html
Copyright © 2011-2022 走看看