Ncurses在光标后显示不需要的文本

时间:2014-04-30 03:01:28

标签: c ncurses

我昨天问了一个问题,你们非常乐于助人。之后出现了另一个问题,这次是关于ncurses的问题。每当我移动箭头(<)时,光标后弹出不需要的文本。 Image of ncurses output

现在的箭头位于p右侧的第一列。似乎我按下的任何键都会在光标后显示出来。我在Cygwin运行该程序,如果这有所作为。

代码:

    #include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <ncurses/ncurses.h>

#define MAXWORDS 100
#define WORDLEN 11
#define DEBUG 0   // set to 0 to disable debug output

#define ARROW '<'
#define BLANK ' '

//PROTOTYPES
int readWords(char *wl[MAXWORDS], char* filename); // reads words from the file into wl and trims the whitespace off of the end
void trimws(char* s); //modifies s to trim white space off the right side
void printWords(char* words[20][5], int wordCount, int rows, int columns);
void draw_character(int x, int y, char use);
void read_dir(int* time, int* b_down, int* b_up, int* b_left, int * b_right, int* dir_down, int* dir_up, int* dir_left, int* dir_right);
void printSentence(char* sentence[MAXWORDS], int position);

struct arrowlocation{
    int row;
    int column;
}arrowloc;

int main(int argc, char* argv[]) {
    char* wordlist[MAXWORDS];
    char* sentence[MAXWORDS];
    char space[]=" \0";
    int wordCount;
    int i=0,j=0,k=0;
    int columns=5, rows;
    int row=0,column=16; //initial position for '<'
    int prevrow, prevcolumn;
    int time, b_down, b_up, b_left, b_right, dir_down, dir_up, dir_left, dir_right;
    int position=0;
    wordCount = readWords(wordlist, argv[1]);

    struct arrowlocation arrowloc;
    arrowloc.row=0;
    arrowloc.column=0;

    //DEBUGGING
    if (DEBUG) {
        printf("Read %d words from %s \n",wordCount, argv[1]);
        for (i = 0; i< wordCount; i++) {
            printf("%s,", wordlist[i]);
        }
        printf("\n\n");
    }

    //Calculates number of rows needed
    if ((((double)wordCount)/columns)>((double)(wordCount/columns))){
        rows=(wordCount/5)+1;
    }
    else{
        rows=(wordCount/5);
    }

    char* words[rows][columns];

    //Converts the list of words to a 2D array table
    for(i=0; i<rows; i++){
        for(j=0; j<columns; j++){
            if (k==wordCount){
                break;
            }
            words[i][j]=wordlist[k];
            k++;
        }
    }

    //Starts ncurses screen
    initscr();
    refresh();


    printWords(words, wordCount, rows, columns);
    refresh();

    draw_character(row, column, ARROW);

    int c=0;
    do{
        refresh();
        c = wgetch(stdscr);

        refresh();
        switch(c){
            case 66:
                //move the arrow down one
                if((arrowloc.row)<20){
                    draw_character(row, column, BLANK);
                    row=row+1;
                    arrowloc.row=arrowloc.row+1;
                    draw_character(row, column, ARROW);

                    //mvprintw(27, 0, "arrow loc; row:%d column:%d",arrowloc.row, arrowloc.column);
                    refresh();
                }
                break;
            case 65:
                //move the arrow up one
                if((arrowloc.row)>0){
                    draw_character(row, column, BLANK);
                    row=row-1;
                    arrowloc.row=arrowloc.row-1;
                    draw_character(row, column, ARROW);

                    //mvprintw(27, 0, "arrow loc; row:%d column:%d",arrowloc.row, arrowloc.column);
                    refresh();
                }
                break;
            case 68:
                //move the arrow left one
                if((arrowloc.column)>0){
                    draw_character(row, column, BLANK);
                    column=column-15;
                    draw_character(row, column, ARROW);

                    arrowloc.column--;
                    //mvprintw(27, 0, "arrow loc; row:%d column:%d",arrowloc.row, arrowloc.column);
                }
                break;
            case 67:
                //move the arrow right one
                if((arrowloc.column)<5){
                    draw_character(row, column, BLANK);
                    column=column+15;
                    draw_character(row, column, ARROW);

                    arrowloc.column++;
                    //mvprintw(27, 0, "arrow loc; row:%d column:%d",arrowloc.row, arrowloc.column);
                }
                break;
            case 113:
                //Left button adds word to sentence without space at end
                //if (b_left==1){
                    sentence[position]=words[arrowloc.row][arrowloc.column];
                    position++;
                    printSentence(sentence, position);
                //}
                break;
            case 119:
                //Up button adds word to sentence with a space at the end
                //if (b_up==1){
                    sentence[position]=words[arrowloc.row][arrowloc.column];
                    position++;
                    sentence[position]=&space[0];
                    position++;
                    printSentence(sentence, position);
                //}
                break;
            case 101:
            //Down button acts as a backspace
            //else if (b_down==1){
                position--;
                printSentence(sentence, position);
            //}
                break;
            default:
                //mvprintw(24, 0, "Charcter pressed is = %3d , c, c);
                refresh();
                break;
        }



    } while(1);


    endwin();

}

void printSentence(char* sentence[MAXWORDS], int position){
    int i=0, x=0;
    //clrtoeol();
    for(i=0; i<position; i++){
        mvprintw(22, x, "%s", sentence[i]);
        //mvprintw(23, x, "%d", i);
        x+=strlen(sentence[i]);
    }
    refresh();

}

void printWords(char* words[20][5], int wordCount, int rows, int columns){
    int k=0, i=0, j=0;
    clear();
    for(i=0; i<rows; i++){
        for(j=0; j<columns; j++){
            if (k<wordCount){
                printw("%15s", words[i][j]);
                k++;
            }
        }
        printw("\n");
    }
    refresh();
}   

void draw_character(int x, int y, char use){
    mvaddch(x,y,use);
    refresh();
}

void read_dir(int* time, int* b_down, int* b_up, int* b_left, int * b_right, int* dir_down, int* dir_up, int* dir_left, int* dir_right) {
    int dummy;
    scanf("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d,", time, b_down, b_up, b_left, b_right, dummy, dummy, dir_down, dir_up, dir_left, dir_right, dummy, dummy);
}

void trimws(char* s) {
    int len = strlen(s) ;
    int x;
    if (len ==0) return;
    x = len-1;
    while (isspace(s[x]) && (x>=0)) {
        s[x] = '\0';
        x--;
    }
}

int readWords(char* wl[MAXWORDS], char* filename) {
    int numread =0;
    char line[WORDLEN];
    char *p;
    FILE* fp = fopen(filename,"r");
    while (!feof(fp)) {
        p  =fgets(line, WORDLEN, fp);
        if (!feof(fp) && p !=NULL) {
            trimws(line);
            wl[numread] = (char *)  malloc(strlen(line)+1);
            strcpy(wl[numread], line);
            numread++;
            }
        } 
    fclose(fp);
    return numread; 
}

如果您希望自行编译并试用,则需要此文本文件http://pastebin.com/xk0MmkEm您可能需要将机箱结构中的数字替换为机器上的数字才能使其正常工作。

运行它只是./program.exe wordslist.txt

1 个答案:

答案 0 :(得分:2)

您的终端定义似乎是正确的,因为<ESC>[B CygWin的向下光标转义序列,并且在运行代码时,它 实际移动光标。

然而,这些转义序列也出现的事实意味着它们来自某个地方,结果它们来自哪里是等式的输入侧,而不是输出方。

当您按下向下箭头时,转义序列首先回显到屏幕,然后输入操作,将光标移动到正确的位置,然后输出<字符。

所以你需要在initscr()电话后立即关闭关闭,并使用:

initscr();
noecho();   // This line added.
refresh();

这将阻止输入被回显。

现在你可能在某些时候依赖于回声被完成(例如,对于常规字符)但我发现通常更好地完全断开输入和输出并在程序本身中进行映射。这样,您可以根据需要使映射变得简单或复杂。

换句话说,如果有人输入e,请确保关闭回声并自行输出e,而不是依靠回声为您执行此操作。