Когда я пытаюсь сделать новую строку, он не вставляется должным образом - PullRequest
0 голосов
/ 04 марта 2020

При запуске моей программы, когда я пытаюсь ввести новую строку, выполнив printf("\n"), она не работает должным образом и просто добавляет тонну пробелов

Мой код компилятора:

gcc code.c -o code

компилятор ничего не выводит (это успешно).

Запуск:

./code

Мой код (код. c) [РЕДАКТИРОВАТЬ: я обновил код, чтобы отразить предложения / ответы, которые мне дали другие]:

#include <stdio.h>
#include "kbhit.h"
#include "kbhit.c"

char def_map[137] = "\
# # # # # # # #\r\n\
# # # # # # # #\r\n\
# # # # # # # #\r\n\
# # # # # # # #\r\n\
# # # # # # # #\r\n\
# # # # # # # #\r\n\
# # # # # # # #\r\n\
# # # # # # # #\r\n\
\n";

char map[137];

int pos[2] = {0,0};

void reset_map() {for (int i=0;i<137;i++) {map[i] = def_map[i];};};

int update(){
    reset_map();

    map[pos[0]*2+pos[1]*17] = '@';

    printf("%s\r\n",map);

    return 0;
}

int move(char dir){
    if (dir == 'u') {
        pos[1] -= 1;
    } else if (dir == 'd') {
        pos[1] += 1;
    } else if (dir == 'l') {
        pos[0] -= 1;
    } else if (dir == 'r') {
        pos[0] += 1;
    };

    printf("%d,%d\r\n",pos[0],pos[1]);
    update();
    return 1;
}

int main() {
    reset_map();

    /*printf("\nHi there! I'd like to know your name. Actually, you COULD do something like Minecraft or TESTER or something like that. But not more than 50 characters. That's too much. I tried it, and I got:\n\n\
*** stack smashing detected ***: <unknown> terminated\n\
Aborted (core dumped)\n\n\
Name: ");
    char a[50];
    scanf("%s",a);
    printf("Hi, %s! This is all meaningless, so you won't see much\n",a);*/

    printf("%s\r\n",map);

    while (1) {
        while(!kbhit()){};

        int c = fgetc(stdin);

        if (c == 'q') {break;};

        switch (c) {
            case 'w':
                move('u');
                break;
            case 'a':
                move('l');
                break;
            case 's':
                move('d');
                break;
            case 'd':
                move('r');
                break;
        }
    };

    printf("\r\n");
    close_keyboard();
    return 0;
}


кбит:

#include <stdio.h>
#include "kbhit.h"
#include <termios.h>
#include <unistd.h>   // for read()

static struct termios initial_settings, new_settings;
static int peek_character = -1;

void init_keyboard()
{
    tcgetattr(0,&initial_settings);
    new_settings = initial_settings;
    new_settings.c_lflag &= ~ICANON;
    new_settings.c_lflag &= ~ECHO;
    new_settings.c_lflag &= ~ISIG;
    new_settings.c_cc[VMIN] = 1;
    new_settings.c_cc[VTIME] = 0;
    tcsetattr(0, TCSANOW, &new_settings);
}

void close_keyboard()
{
    tcsetattr(0, TCSANOW, &initial_settings);
}

int kbhit()
{
unsigned char ch;
int nread;

    if (peek_character != -1) return 1;
    new_settings.c_cc[VMIN]=0;
    tcsetattr(0, TCSANOW, &new_settings);
    nread = read(0,&ch,1);
    new_settings.c_cc[VMIN]=1;
    tcsetattr(0, TCSANOW, &new_settings);
    if(nread == 1)
    {
        peek_character = ch;
        return 1;
    }
    return 0;
}

int readch()
{
char ch;

    if(peek_character != -1)
    {
        ch = peek_character;
        peek_character = -1;
        return ch;
    }
    read(0,&ch,1);
    return ch;
}

Вывод:

# # # # # # # #
# # # # # # # #
# # # # # # # #
# # # # # # # #
# # # # # # # #
# # # # # # # #
# # # # # # # #
# # # # # # # #


[w key twice]0,1
   # # # # # # # #
                  @ # # # # # # #
                                 # # # # # # # #
                                                # # # # # # # #
                                                               # # # # # # # #
                                                                              # # # # # # # #
          # # # # # # # #
                         # # # # # # # #


                                        [q]user@localhost:/path/to/dir$ [return]user@localhost:/path/to/dir$ [return]user@localhost:/path/to/dir$ 


Я попытался использовать терминатор вместо gnome-терминала и возникла такая же проблема

1 Ответ

0 голосов
/ 04 марта 2020

Вы не показываете код для kbhit, но его, скорее всего, проблема в том, что он переводит терминал в нестандартный режим (возможно, ~ ONLCR) и не восстанавливает его.

Убедитесь, что любой код, который изменяет режим терминала с помощью tcgetattr / tcsetattr, сохраняет исходный режим и восстанавливает его после того, как это будет сделано ...


Проблема заключается в том, что вы никогда не звоните init_keyboard , поэтому new_settings никогда не инициализируется с текущими настройками терминала - это означает, что когда вы вызываете kbhit, это повреждает настройки вывода. Кроме того, вы должны вызывать функцию readch, чтобы прочитать нажатие клавиши вместо fgetc.

Вам нужно позвонить init_keyboard перед тем, как вызвать kbhit или readch, и позвонить close_keyboard вперед перед вызовом любой функции stdio, которая читает из stdin. Между init_keyboard и close_keyboard вы должны использовать only kbhit и readch для чтения ввода и никогда не использовать функции stdio на stdin.

...