Ввод символов в массивы в C- продолжение - PullRequest
2 голосов
/ 26 июня 2009

Это дополнительный вопрос к предыдущему вопросу, который я задавал о вычислении прямой руки ... не совсем то же самое ... Это метод чтения карт - он работает, но есть ли лучший способ сделать это это с помощью консольного ввода в C ...

void read_cards(int num_in_rank[], int num_in_suit[])
{
  bool card_exists[NUM_RANKS][NUM_SUITS];
  char ch, rank_ch, suit_ch;
  int rank, suit;
  bool bad_card;
  int cards_read = 0;

  for (rank = 0; rank < NUM_RANKS; rank++) {
    num_in_rank[rank] = 0;
    for (suit = 0; suit < NUM_SUITS; suit++)
      card_exists[rank][suit] = false;
  }

  for (suit = 0; suit < NUM_SUITS; suit++)
    num_in_suit[suit] = 0;

  while (cards_read < NUM_CARDS) {
    bad_card = false;

    printf("Enter a card: ");

    rank_ch = getchar();
    switch (rank_ch) {
      case '0':           exit(EXIT_SUCCESS);
      case '2':           rank = 0; break;
      case '3':           rank = 1; break;
      case '4':           rank = 2; break;
      case '5':           rank = 3; break;
      case '6':           rank = 4; break;
      case '7':           rank = 5; break;
      case '8':           rank = 6; break;
      case '9':           rank = 7; break;
      case 't': case 'T': rank = 8; break;
      case 'j': case 'J': rank = 9; break;
      case 'q': case 'Q': rank = 10; break;
      case 'k': case 'K': rank = 11; break;
      case 'a': case 'A': rank = 12; break;
      default:            bad_card = true;
    }

    suit_ch = getchar();
    switch (suit_ch) {
      case 'c': case 'C': suit = 0; break;
      case 'd': case 'D': suit = 1; break;
      case 'h': case 'H': suit = 2; break;
      case 's': case 'S': suit = 3; break;
      default:            bad_card = true;
    }

    while ((ch = getchar()) != '\n')
      if (ch != ' ') bad_card = true;

    if (bad_card)
      printf("Bad card; ignored.\n");
    else if (card_exists[rank][suit])
      printf("Duplicate card; ignored.\n");
    else {
      num_in_rank[rank]++;
      num_in_suit[suit]++;
      card_exists[rank][suit] = true;
      cards_read++;
    }
  }
}

Я знаю, что оператор case может иметь несколько оптимизаций, т.е. используя таппер; лучшее представление значений карты и т. д. Код отражает C99 ...

Ответы [ 4 ]

1 голос
/ 26 июня 2009

Вместо того, чтобы использовать getchar (), я бы рассмотрел использование scanf ("% s", str) - http://www.cplusplus.com/reference/clibrary/cstdio/scanf. Затем можно сохранить результаты в массиве символов, выполнить цикл по массиву и сравнить символы в соответствующие шестнадцатеричные или десятичные значения на диаграмме ascii http://www.s4a.us/support/images/ascii_chart.gif.

int rank = 0;
int suite = 'c';
char[3] buff; // be careful of overflow
printf ("Enter the rank and suite: ");
scanf ("%s",buff); 

for(int i=0; i<2; i++)
{
    // compare elements of buff to those in the ascii chart
}
1 голос
/ 26 июня 2009

Код выглядит хорошо для меня. Это на самом деле довольно хорошо сделано и читаемо на мой взгляд.

Похоже, вы спрашиваете об оптимизации - не беспокойтесь об оптимизации, пока вы не уверены, что она вам нужна, иначе это просто сделает ваш код менее разборчивым и более подверженным ошибкам. В частности, эта функция будет тратить более 99,99% времени на выполнение, просто ожидая ввода текста пользователем, поэтому ее не нужно оптимизировать.

Я не думаю, что обязательно использовать неудачу для записи как прописных, так и строчных букв в операторе switch, особенно с таким небольшим количеством случаев, как у вас. Это просто немного больше печатать.

Если на самом деле есть проблема с этим кодом, и он не компилируется или не выполняет то, что должен, пожалуйста, опишите проблему.

Редактировать: Единственное, что вы можете изменить, это избавиться от явных падежей для рангов 0-9 и вместо этого объединить их все в один падежный случай с телом:

rank = rank_ch - '0';

Это довольно распространенная идиома C для преобразования числа, хранящегося в виде символа, в целое число, поэтому оно должно быть читаемым для других программистов, которые его читают.

0 голосов
/ 27 июня 2009

Код выглядит нормально для меня, поэтому у меня есть только незначительные предложения:

  • Запрашивать у пользователя костюм после того, как он вошел в ранг, просто чтобы действительно было понятно, что он должен делать.

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

  • Учитывая, что вы ожидаете от пользователя только 2 символа, зачем ждать \ n или каких-либо символов? Просто продолжайте, как только 2 символа введены.

  • Чисто, чтобы улучшить читабельность, используйте перечисления для костюмов, а не чисел. Если это для покера (да и вообще многих других карточных игр, хотя и не бридж), порядок мастей в любом случае не имеет значения.

  • Я согласен с другими комментариями по поводу преобразования символов в перечисления (rank = (rank_ch - '0') - 2). Я бы не стал беспокоиться о таппере в таком ограниченном случае.

0 голосов
/ 26 июня 2009

Зависит от того, для чего вы его используете и как вы хотите вводить данные. Если вы хотите вводить по одной карточке за раз, вы можете придерживаться своего метода (или методов, если вы хотите сделать его проще для чтения) или использовать другой способ, например, получает. Если вы хотите читать в руках, вы можете разделить пробелами или запятыми пользовательские карточки ввода. Затем просто прочитайте строку и подтвердите ввод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...