3

以前の質問で提案されたように termios を使用していますが、非標準モードで termios を使用しているときにバックスペースを取得する方法があるかどうかを尋ねています。持っていないために termios を使用していますecho私が使用&=ECHOし、&=ICANONこれが私が望む結果である場合、キーが押されて表示されるとすぐにキーボード入力が putchar() に送信されますが、'\b'キーは として表示されますhex。 Enter キーを押すまでテキストが表示されませんが、'\b'機能します。マニュアルを調べましたおよび彼らが「不可能であり、間違いを犯さないでください」と述べた他のいくつかのフォーラム、これは、Ubuntuのターミナルでパスワードを正しく入力しないと、バックスペースして変更できないことを考えると理にかなっています. しかし、私はマニュアルで何も見逃していないことを確認していました.

コードは stdin から入力を取得し、空行を表示しないようにします。

#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <stdio.h>
#define ECHOFLAGS (ECHO)

int setecho(int fd, int onflag);
int first_line(int *ptrc);

int main(void){

struct termios old;
tcgetattr(STDIN_FILENO,&old);


setecho(STDIN_FILENO,0);
    int c;
    while((c = getchar())!= 4) //no end of file in non-canionical match to control D
        first_line(&c);
tcsetattr(STDIN_FILENO,&old);    
return 0;

    }


int setecho(int fd, int onflag){
    int error;
    struct termios term;

    if(tcgetattr(fd, &term) == -1)
        return -1;
    if(onflag){ printf("onflag\n");
        term.c_lflag &= ECHOFLAGS ; // I know the onflag is always set to 0 just 
        term.c_lflag &=ICANON;      // testing at this point
    }
    else{ printf("else\n");
        term.c_lflag &= ECHO;
        term.c_lflag &=ICANON;

    }

    while (((error = tcsetattr(fd, TCSAFLUSH, &term)) ==-1 && (errno == EINTR)))
            return error;
}

int first_line(int *ptrc){
    if (*ptrc != '\n' && *ptrc != '\r'){
            putchar(*ptrc);
        while (*ptrc != '\n'){
            *ptrc = getchar();
            putchar(*ptrc);
            }


    }
    else return 0;

    return 0;
}

ありがとうラクラン

PS私の研究の側面で、Termiosは「標準C」ではないと誰かが言っているのに気づきました。これはシステムに依存しているためですか? (コメントのみ)

4

3 に答える 3

3

それは実装依存です。私のマシンでは、バックスペースを押すと、read() によってバイト 127 が読み取られました。このコードは私のマシンで機能しました。

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

#define MAXBUFSIZE (10000U)
#define DEL (127)

int main(void) {
    char buf[MAXBUFSIZE];
    char c;
    size_t top;
    struct termios curterm;

    tcgetattr(STDIN_FILENO, &curterm);
    curterm.c_lflag &= ~(ICANON| ECHO);
    curterm.c_cc[VTIME] = 0;
    curterm.c_cc[VMIN] = 1;
    tcsetattr(STDIN_FILENO, TCSANOW, &curterm);

    top = 0;
    while (read(STDIN_FILENO, &c, sizeof c) == 1) {
        switch (c) {
            case DEL:
                if (top) {
                    --top;
                    const char delbuf[] = "\b \b";
                    write(STDOUT_FILENO, delbuf, strlen(delbuf));
                }
                break;
            case '\n':
                write(STDOUT_FILENO, &c, sizeof c);
                write(STDOUT_FILENO, buf, top);
                top = 0;
                break;
            default:
                buf[top++] = c;
                write(STDOUT_FILENO, &c, sizeof c);
                break;
         }
    }

    return 0;
}
于 2015-12-02T19:52:52.073 に答える
3

これがどのように機能すると思いますか?入力文字がすぐにプログラムに送信された場合、バックスペース文字を受信するまでに、端末がバックスペースを処理するには遅すぎます。プログラムは前の文字を既に認識しているため、元に戻すことはできません。

たとえば、ユーザーが を押したとしますA。あなたのプログラムはそれを受け取り'A'getchar()処理します。ここでユーザーが押しますbackspace- 端末は何をすべきでしょうか?

したがって、これは、非標準モードでバックスペースを処理できる唯一の場所がプログラム自体であることを意味します。'\b'から文字を受け取ると、getchar()それを特別に処理できます ( を特別に処理するのと同じように'\n')。たとえば、最後に入力された文字をバッファーから削除します。

于 2012-04-23T07:26:59.843 に答える