Книга: Основы программирования в Linux

Запросы к базе данных компакт-дисков

Запросы к базе данных компакт-дисков

Теперь рассмотрим функции для доступа к данным, которые для упрощения доступа хранятся в паре простых файлов как поля, разделенные запятыми.

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

void count_cds() {
 FILE *titles_fp, *tracks_fp;
 char entry[MAX_ENTRY];
 int titles = 0;
 int tracks = 0;
 titles_fp = fopen(title_file, "r");
 if (titles_fp) {
  while (fgets(entry, MAX_ENTRY, titles_fp))
   titles++;
  fclose(titles_fp);
 }
 tracks_fp = fopen(tracks_file, "r");
 if (tracks_fp) {
  while (fgets(entry, MAX_ENTRY, tracks_fp))
   tracks++;
  fclose(tracks_fp);
 }
 mvprintw(ERROR_LINE, 0,
  "Database contains %d titles, with a total of %d tracks.", titles, tracks);
 get_return();
}

2. Вы потеряли аннотацию к вашему любимому компакт-диску? Не волнуйтесь! Если вы аккуратно ввели подробную информацию в базу данных, теперь можно найти перечень дорожек с помощью функции find_cd. Она предлагает ввести подстроку, совпадение с которой нужно искать в базе данных, и устанавливает в глобальную переменную current_cd заголовок найденного компакт-диска.

void find_cd() {
 char match[MAX_STRING], entry[MAX_ENTRY];
 FILE *titles_fp;
 int count = 0;
 char *found, *title, *catalog;
 mvprintw(Q_LINE, 0, "Enter a string to search for in CD titles: ");
 get_string(match);
 titles_fp = fopen(title_file, "r");
 if (titles_fp) {
  while (fgets(entry, MAX_ENTRY, titles_fp)) {
   /* Пропускает прежний номер в каталоге */
   catalog = entry;
   if (found == strstr(catalog, ", ")) {
    *found = '';
    title = found + 1;
    /* Стирает следующую запятую в элементе, укорачивая его
       только до заголовка */
    if (found == strstr(title, ", ")) {
     *found = '';
     /* Теперь проверяет, есть ли совпадающая строка */
     if (found == strstr(title, match)) {
      count++;
      strcpy(current_cd, title);
      strcpy(current_cat, catalog);
     }
    }
   }
  }
  fclose(titles_fp);
 }
 if (count != 1) {
  if (count == 0) {
   mvprintw(ERROR_LINE, 0, "Sorry, no matching CD found. ");
  }
  if (count > 1) {
   mvprintw(ERROR_LINE, 0,
    "Sorry, match is ambiguous: CDs found. ", count);
  }
  current_cd[0] = '';
  get_return();
 }
}

Хотя переменная catalog указывает на массив, больший чем current_cat, и могла бы переписать память, проверка в функции fgets препятствует этому.

3. Вам также нужно иметь возможность перечислить на экране дорожки выбранного компакт-диска. Для вложенных окон можно использовать директивы #define, применявшиеся в функции update_cd в предыдущем разделе.

void list_tracks() {
 FILE *tracks_fp;
 char entry[MAX_ENTRY];
 int cat_length;
 int lines_op = 0;
 WINDOW *track_pad_ptr;
 int tracks = 0;
 int key;
 int first_line = 0;
 if (current_cd[0] == '') {
  mvprintw(ERROR_LINE, 0, "You must select a CD first. ");
  get_return();
  return;
 }
 clear_all_screen();
 cat_length = strlen(current_cat);
 /* Сначала считает количество дорожек у текущего CD */
 tracks_fp = fopen(tracks_file, "r");
 if (!tracks_fp) return;
 while (fgets(entry, MAX_ENTRY, tracks_fp)) {
  if (strncmp(current_cat, entry, cat_length) == 0) tracks++;
 }
 fclose(tracks_fp);
 /* Создает новую панель, гарантируя, что даже при наличии одной
    дорожки панель достаточна большая, поэтому последующий вызов
    prefresh() всегда будет допустим. */
 track_pad_ptr = newpad(tracks + 1 + ВОХЕD_LINES, BOXED_ROWS + 1);
 if (!track_pad_ptr) return;
 tracks_fp = fopen(tracks_file, "r");
 if (!tracks_fp) return;
 mvprintw(4, 0, "CD Track Listingn");
 /* Записывает сведения о дорожке на панель */
 while (fgets(entry, MAX_ENTRY, tracks_fp)) {
  /* Сравнивает номер каталога и оставшийся вывод элемента */
  if (strncmp(current_cat, entry, cat_length) == 0) {
   mvwprintw(track_pad_ptr, lines_op++, 0, "%s", entry + cat_length + 1);
  }
 }
 fclose(tracks_fp);
 if (lines_op > BOXED_LINES) {
  mvprintw(MESSAGE_LINE, 0,
   "Cursor keys to scroll, RETURN or q to exit");
 } else {
  mvprintw(MESSAGE_LINE, 0, "RETURN or q to exit");
 }
 wrefresh(stdscr);
 keypad(stdscr, TRUE);
 cbreak();
 noecho();
 key = 0;
 while (key != "q" && key != KEY_ENTER && key != 'n') {
  if (key == KEY_UP) {
   if (first_line > 0) first_line--;
  }
  if (key == KEY_DOWN) {
   if (first_line + BOXED_LINES + 1 < tracks) first_line++;
  }
  /* Теперь рисует соответствующую часть панели на экране */
  prefresh(track_pad_ptr, first_line, 0, BOX_LINE_POS, BOX_ROW_POS,
   BOX_LINE_POS + BOXED_LINES, BOX_ROW_POS + BOXED_ROWS);
  key = getch();
 }
 delwin(track_pad_ptr);
 keypad(stdsсr, FALSE);
 nocbreak();
 echo();
}

4. В последних двух функциях вызывается функция get_return, которая приглашает к вводу и считывает символ возврата каретки, игнорируя другие символы.

void get_return() {
 int ch;
 mvprintw(23, 0, "is", " Press return ");
 refresh();
 while ((ch = getchar()) != 'n' && ch != EOF);
}

Если вы выполните эту программу, то увидите на экране нечто похожее на рис. 6.10.


Рис. 6.10 

Оглавление книги


Генерация: 1.681. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз