C - 使用 getchar() 只读取一个字符

C - Reading just one character with getchar()

我在使用 getchar() 时遇到了一些问题,特别是我有一个 char,它在 while 循环中获取从 getchar() 返回的值,但我只想获取第一个 char,如果我插入一个较长的字符串(如 "aaawssdawa"),我仍然只想要第一个字符。相反,我的代码处理整个字符串。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#define ROWS 20
#define COLUMNS 65

char grid[ROWS][COLUMNS];
int score = 0;
void fillGridInitializer();
void printGrid();
void start();
void printScore();
void printAll();
int main(int argc, char *argv[]) {
  start();
  return 0;
}
void start() {
  char movement;
  int riga = 0, colonna = 0;
  fillGridInitializer();
  grid[riga][colonna] = '#';
  system("clear");
  printAll();
  while (1) {
    movement = getchar();
    switch (movement) {
    case 'w':
      if ((riga - 1) >= 0) {
        grid[riga][colonna] = '-';
        riga = riga - 1;
      }
      break;
    case 's':
      if ((riga + 1) < ROWS) {
        grid[riga][colonna] = '-';
        riga = riga + 1;
      }
      break;
    case 'a':
      if ((colonna - 1) >= 0) {
        grid[riga][colonna] = '-';
        colonna = (colonna - 1) % COLUMNS;
      }
      break;
    case 'd':
      if ((colonna + 1) < COLUMNS) {
        grid[riga][colonna] = '-';
        colonna = (colonna + 1) % COLUMNS;
      }
      break;
    default:
      break;
    }
    if (movement == 'p') {
      printf("+++++Game Over+++++\n\n");
      break;
    }
    system("clear");
    grid[riga][colonna] = '#';
    printAll();
  }
}

void printAll() {
  printScore();
  printGrid();
}
void fillGridInitializer() {
  int i = 0, j = 0;
  for (i = 0; i < ROWS; i++) {
    for (j = 0; j < COLUMNS; j++) {
      grid[i][j] = '-';
    }
  }
}
void printScore() { printf("\t SCORE: %d\n", score); }
void printGrid() {
  int i = 0, j = 0;
  for (i = 0; i < ROWS; i++) {
    printf("\t");
    for (j = 0; j < COLUMNS; j++) {
      printf("%c", grid[i][j]);
    }
    printf("\n");
  }
}

处理完第一个字符后,循环调用 getchar(),直到得到换行符或 EOF。

此外,getchar() returns int,你应该相应地声明变量,这样你就可以正确地与EOF进行比较。

void start() {
  int movement;
  int riga = 0, colonna = 0;
  fillGridInitializer();
  grid[riga][colonna] = '#';
  system("clear");
  printAll();
  while (1) {
    movement = getchar();
    if (movement == EOF) {
        break;
    }
    switch (movement) {
    case 'w':
      if ((riga - 1) >= 0) {
        grid[riga][colonna] = '-';
        riga = riga - 1;
      }
      break;
    case 's':
      if ((riga + 1) < ROWS) {
        grid[riga][colonna] = '-';
        riga = riga + 1;
      }
      break;
    case 'a':
      if ((colonna - 1) >= 0) {
        grid[riga][colonna] = '-';
        colonna = (colonna - 1) % COLUMNS;
      }
      break;
    case 'd':
      if ((colonna + 1) < COLUMNS) {
        grid[riga][colonna] = '-';
        colonna = (colonna + 1) % COLUMNS;
      }
      break;
    default:
      break;
    }
    if (movement == 'p') {
      printf("+++++Game Over+++++\n\n");
      break;
    }
    int ch;
    while ((ch = getchar()) != '\n' && ch != EOF) {} # ignore the rest of the line
    if (ch == EOF) {
        break;
    }
    system("clear");
    grid[riga][colonna] = '#';
    printAll();
  }
}

假设您只想读取一个字符并丢弃同一行中的所有其他内容,您可以执行以下操作:

只读一行,只保存第一个字符。

但是,你不应该使用它,因为它容易受到缓冲区溢出的影响(阅读它后面的内容)。

char read(){
    char buf[BUF_SIZE];
    gets(buf);
    return buf[0];
}

但是您不应该使用 gets,因为可能会出现缓冲区溢出。

为了防止这种情况发生,您可以使用 fgets(参见 this):

char read(){
    char buf[BUF_SIZE];
    fgets(buf,BUF_SIZE,stdin);
    return buf[0];
}

在这两种情况下,BUF_SIZE 是定义字符串最大长度的常量。第二个例子是缓冲区溢出保护的,但只有当行在缓冲区结束之前结束时它才会起作用。您可以多次调用 fgets 来绕过这个问题:

char read(){
    char buf[BUF_SIZE];
    do{
        fgets(buf, BUF_SIZE,stdin);
    }while(buf[strlen(buf)]!='\n');
    return buf[0];
}

注意最后一个方法需要<string.h>.

集成到你的代码中,它会是这样的:

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

#define ROWS 20
#define COLUMNS 65
#define BUF_SIZE 255

char grid[ROWS][COLUMNS];
int score = 0;
void fillGridInitializer();
void printGrid();
void start();
void printScore();
void printAll();
int main(int argc, char *argv[]) {
  start();
  return 0;
}
void start() {
  char movement;
  int riga = 0, colonna = 0;
  fillGridInitializer();
  grid[riga][colonna] = '#';
  system("clear");
  printAll();
  while (1) {
    movement = read();
    switch (movement) {
    case 'w':
      if ((riga - 1) >= 0) {
        grid[riga][colonna] = '-';
        riga = riga - 1;
      }
      break;
    case 's':
      if ((riga + 1) < ROWS) {
        grid[riga][colonna] = '-';
        riga = riga + 1;
      }
      break;
    case 'a':
      if ((colonna - 1) >= 0) {
        grid[riga][colonna] = '-';
        colonna = (colonna - 1) % COLUMNS;
      }
      break;
    case 'd':
      if ((colonna + 1) < COLUMNS) {
        grid[riga][colonna] = '-';
        colonna = (colonna + 1) % COLUMNS;
      }
      break;
    default:
      break;
    }
    if (movement == 'p') {
      printf("+++++Game Over+++++\n\n");
      break;
    }
    system("clear");
    grid[riga][colonna] = '#';
    printAll();
  }
}

void printAll() {
  printScore();
  printGrid();
}
void fillGridInitializer() {
  int i = 0, j = 0;
  for (i = 0; i < ROWS; i++) {
    for (j = 0; j < COLUMNS; j++) {
      grid[i][j] = '-';
    }
  }
}
void printScore() { printf("\t SCORE: %d\n", score); }
void printGrid() {
  int i = 0, j = 0;
  for (i = 0; i < ROWS; i++) {
    printf("\t");
    for (j = 0; j < COLUMNS; j++) {
      printf("%c", grid[i][j]);
    }
    printf("\n");
  }
}
char read(){
    char buf[BUF_SIZE];
    do{
        fgets(buf, BUF_SIZE,stdin);
    }while(buf[strlen(buf)]!='\n');
    return buf[0];
}