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

Управление базой данных

Управление базой данных

В этом разделе описаны функции пополнения или обновления базы данных компакт-дисков. Функции add_record, update_cd и remove_cd вызываются из функции main.

Добавление записей

1. Добавьте сведения о новом компакт-диске в базу данных.

void add_record {
 char catalog_number[MAX_STRING];
 char cd_title[MAX_STRING];
 char cd_type[MAX_STRING];
 char cd_artist[MAX_STRING];
 char cd_entry[MAX_STRING];
 int screenrow = MESSAGE_LINE;
 int screencol = 10;
 clear_all_screen();
 mvprintw(screenrow, screencol, "Enter new CD details");
 screenrow += 2;
 mvprintw(screenrow, screencol, "Catalog Number: " );
 get_string(catalog_number);
 screenrow++;
 mvprintw(screenrow, screencol, " CD Title: ");
 get_string(cd_title);
 screenrow++;
 mvprintw(screenrow, screencol, " CD Type: ");
 get_string(cd_type);
 screenrow++;
 mvprintw(screenrow, screencol, " Artist: ");
 get_string(cd_artist);
 screenrow++;
 mvprintw(PROMPT_LINE-2, 5, "About to add this new entry:");
 sprintf(cd_entry, "%s, %s, %s, %s",
  catalog_number, cd_title, cd_type, cd_artist);
 mvprintw(PROMPT_LINE, 5, "%s", cd_entry);
 refresh();
 move(PROMPT_LINE, 0);
 if (get_confirm()) {
  insert_title(cd_entry);
  strcpy(current_cd, cd_title);
  strcpy(current_cat, catalog_number);
 }
}

2. Функция get_string приглашает к вводу и считывает строку из текущей позиции экрана. Она также удаляет завершающую новую пустую строку:

void get_string(char* string) {
 int len;
 wgetnstr(stdscr, string, MAX_STRING);
 len = strlen(string);
 if (len > 0 && string[len - 1] == 'n') string[len - 1] = '';
}

3. Функция get_confirm запрашивает и считывает пользовательское подтверждение. Она читает введенную пользователем строку и проверяет, первый символ — Y или у. Если она обнаруживает другой символ, то не дает подтверждения.

int get_confirm() {
 int confirmed = 0;
 char first_char;
 mvprintw(Q_LINE, 5, "Are you sure? ");
 clrtoeol();
 refresh();
 cbreak();
 first_char = getch();
 if (first_char == 'Y' || first_char == 'y') {
  confirmed = 1;
 }
 nocbreak();
 if (!confirmed) {
  mvprintw(Q_LINE, 1, " Cancelled");
  clrtoeol();
  refresh();
  sleep(1);
 }
 return confirmed;
}

4. Последней рассмотрим функцию insert_title. Она вставляет в базу данных компакт-дисков заголовок, добавляя строку с заголовком в конец файла заголовков:

void insert_title(char* cdtitle) {
 FILE *fp = fopen(title_file, "a");
 if (!fp) {
  mvprintw(ERROR_LINE, 0, "cannot open CD titles database");
 } else {
  fprintf(fp, "%sn", cdtitle);
  fclose(fp);
 }
}

Обновление записей

1. Продолжим рассмотрение других управляющих функций, вызываемых из функции main. Следующая из них — функция update_cd. Эта функция использует обведенное рамкой вложенное окно с прокруткой и нуждается в нескольких константах, которые объявляются как глобальные, поскольку они позже потребуются функции list_tracks.

#define BOXED_LINES  11
#define BOXED_ROWS   60
#define BOX_LINE_POS 8
#define BOX_ROW_POS  2

2. Функция update_cd позволяет пользователю заново ввести сведения о дорожках текущего компакт-диска. Удалив предыдущие записи о дорожках, она приглашает ввести новую информацию.

void update_cd() {
 FILE *tracks_fp;
 char track_name[MAX_STRING];
 int len;
 int track = 1;
 int screen_line = 1;
 WINDOW *box_window_ptr;
 WINDOW *sub_window_ptr;
 clear_all_screen();
 mvprintw(PROMPT_LINE, 0, "Re-entering tracks for CD. ");
 if (!get_confirm())

return;

 move(PROMP_TLINE, 0);
 clrtoeol();
 remove_tracks();
 mvprintw(MESSAGE_LINE, 0, "Enter a blank line to finish");
 tracks_fp = fopen(tracks_file, "a");

Примечание

Листинг будет продолжен через минуту; мы хотим сделать краткую паузу, чтобы обратить ваше внимание на ввод данных в обрамленное окно с прокруткой. Хитрость заключается в формировании вложенного окна, рисовании рамки по его краю и создании внутри этого окна нового вложенного окна с прокруткой.

 box_window_ptr = subwin(stdscr, BOXED_LINES + 2, BOXED_ROWS + 2,
  BOX_LINE_POS - 1, BOX_ROW_POS - 1);
 if (!box_window_ptr) return;
 box(box_window_ptr, ACS_VLINE, ACS_HLINE);
 sub_window_ptr = subwin(stdscr, BOXED_LINES, BOXED_ROWS,
  BOX_LINE_POS, BOX_ROW_POS);
 if (!sub_window_ptr) return;
 scrollok(sub_window_ptr, TRUE);
 werase(sub_window_ptr);
 touchwin(stdscr);
 do {
  mvwprintw(sub_window_ptr, screen_line++, BOX_ROW_POS + 2,
   "Track %d: ", track);
  clrtoeol();
  refresh();
  wgetnstr(sub_window_ptr, track_name, MAX_STRING);
  len = strlen(track_name);
  if (len > 0 && track_name[len - 1] = 'n')
   track_name[len - 1] = '';
  if (*track_name)
   fprintf(tracks_fp, "%s, %d, %sn", current_cat, track, track_name);
  track++;
  if (screen_line > BOXED__LINES - 1) {
   /* время начать прокрутку */
   scroll(sub_window_ptr);
   screen_line--;
  }
 } while (*track_name);
 delwin(sub_window_ptr);
 fclose(tracks_fp);
}

Удаление записей

1. remove_cd — последняя функция, вызываемая из функции main.

void remove_cd() {
 FILE *titles_fp, *temp_fp;
 char entry[MAX_ENTRY];
 int cat_length;
 if (current_cd[0] == '') return;
 clear_all_screen();
 mvprintw(PROMPT_LINE, 0, "About to remove CD %s: %s. ", current_cat, current_cd);
 if (!get_confirm())
  return;
 cat_length = strlen(current_cat);
 /* Файл заголовков копируется во временный, игнорируя данный CD */
 titles_fp = fopen(title_file, "r");
 temp_fp = fopen(temp_flie, "w");
 while(fgets(entry, MAX_ENTRY, titles_fp)) {
  /* Сравнивает номер в каталоге и копирует элемент, если не
     найдено совпадение */
  if (strncmp(current_cat, entry, cat_length) != 0)
   fputs(entry, temp_fp);
 }
 fclose(titles_fp);
 fclose(temp_fp);
 /* Удаляет файл заголовков и переименовывает временный файл */
 unlink(title_file);
 rename(temp_file, title_file);
 /* Теперь делает то же самое для файла дорожек */
 remove_tracks();
 /* Устанавливает 'None' для текущего CD */
 current_cd[0] = '';
}

2. Теперь вам только нужен программный код функции remove_tracks, удаляющей дорожки текущего компакт-диска. Она вызывается двумя функциями — update_cd и remove_cd.

void remove_tracks() {
 FILE *tracks_fp, *temp_fp;
 char entry[MAX_ENTRY];
 int cat_length;
 if (current_cd[0] == '') return;
 cat_length = strlen(current_cat);
 tracks_fp = fopen(tracks_file, "r");
 if (tracks_fp == (FILE *)NULL) return;
 temp_fp = fopen(temp_file, "w");
 while (fgets(entry, MAX_ENTRY, tracks_fp)) {
  /* Сравнивает номер в каталоге и копирует элемент, если не
     найдено совпадение */
  if (strncmp(current_cat, entry, cat_length) != 0)
   fputs(entry, temp_fp);
 }
 fclose(tracks_fp);
 fclose(temp_fp);
 /* Удаляет файл дорожек и переименовывает временный файл */
 unlink(tracks_file);
 rename(temp_file, tracks_file);
}

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


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