Рейтинговые книги
Читем онлайн Основы программирования в Linux - Нейл Мэтью

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 78 79 80 81 82 83 84 85 86 ... 200

int database_initialize(const int new_database);

void database_close(void);

/* Две функции для простого извлечения данных */

cdc_entry get_cdc_entry(const char *cd_catalog_ptr);

cdt_entry get_cdt_entry(const char *cd_catalog_ptr, const int track_no);

/* Две функции для добавления данных */

int add_cdc_entry(const cdc_entry entry_to_add);

int add_cdt_entry(const cdt_entry entry_to_add);

/* Две функции для удаления данных */

int del_cdc_entry(const char *cd_catalog_ptr);

int del_cdt_entry(const char *cd_catalog_ptr, const int track_no);

/* Одна функция поиска */

cdc_entry search_cdc_entry(const char *cd_catalog_ptr,

 int *first_call_ptr);

Упражнение 7.15. Файл app_ui.c

Теперь перейдем к пользовательскому интерфейсу. Вам предлагается простая программа, с помощью которой вы сможете обращаться к функциям вашей базы данных. Интерфейс реализуется в отдельном файле.

1. Как обычно, начните с некоторых заголовочных файлов:

#define _XOPEN_SOURCE

#include <stdlib.h>

#include <unistd.h>

#include <stdio.h>

#include <string.h>

#include "cd_data.h"

#define TMP_STRING_LEN 125 /* это число должно быть больше

                              самой длинной строки в структуре базы данных */

2. Опишите пункты вашего меню с помощью typedef. Этот вариант лучше применения констант, заданных в директивах #define, т.к. позволяет компилятору проверить типы переменных, задающих пункт меню.

typedef enum {

 mo_invalid,

 mo_add_cat,

 mo_add_tracks,

 mo_del_cat,

 mo_find_cat,

 mo_list_cat_tracks,

 mo_del_tracks,

 mo_count_entries,

 mo_exit

} menu_options;

3. Теперь введите прототипы локальных функций. Помните о том, что прототипы функций, обеспечивающих реальный доступ к базе данных, включены в файл cd_data.h.

static int command_mode(int argc, char *argv[]);

static void announce(void);

static menu_options show_menu(const cdc_entry *current_cdc);

static int get_confirm(const char *question);

static int enter_new_cat_entry(cdc_entry *entry_to_update);

static void enter_new_track_entries(const cdc_entry* entry_to_add_to);

static void del_cat_entry(const cdc_entry *entry_to_delete);

static void del_track_entries(const cdc_entry *entry_to_delete);

static cdc_entry find_cat(void);

static void list_tracks(const cdc_entry *entry_to_use);

static void count_all_entries(void);

static void display_cdc(const cdc_entry *cdc_to_show);

static void display_cdt(const cdt_entry *cdt_to_show);

static void strip_return(char *string_to_strip);

4. И наконец, вы добрались до функции main. Она начинается с проверки того, что текущий элемент current_cdc_entry, который применяется для сохранения дорожки выбранного в данный момент элемента каталога компакт-дисков, инициализирован. Также проводится грамматический разбор командной строки, выдается оповещение о том, какая программа выполняется, и инициализируется база данных.

void main(int argc, char *argv[]) {

 menu_options current_option;

 cdc_entry current_cdc_entry;

 int command_result;

 memset(&current_cdc_entry, '', sizeof(current_cdc_entry));

if (argc >1) {

  command_result = command_mode(argc, argv);

  exit(command_result);

 }

 announce();

 if (!database_initialize(0)) {

  fprintf(stderr, "Sorry, unable to initialize databasen");

  fprintf(stderr, "To create a new database use %s -in", argv[0]);

  exit(EXIT_FAILURE);

 }

5. Теперь вы готовы обрабатывать ввод пользователя. Вы остаетесь в цикле, запрашивая пункт меню и обрабатывая его до тех пор, пока пользователь не выберет выход. Обратите вниманий на то, что вы передаете структуру current_cdc_entry в функцию show_menu, чтобы разрешить изменять варианты пунктов меню, когда выбран текущий элемент каталога:

 while (current_option != mo_exit) {

  current_option = show_menu(&current_cdc_entry);

  switch(current_option) {

  case mo_add_cat:

   if (enter_new_cat_entry(&current_cdc_entry)) {

    if (!add_cdc_entry(current_cdc_entry)) {

     fprintf(stderr, "Failed to add new entryn");

     memset(&current_cdc_entry, '',

      sizeof(current_cdc_entry));

    }

   }

   break;

  case mo_add_tracks:

   enter_new_track_entries(&current_cdc_entry);

   break;

  case mo_del_cat:

   del_cat_entry(&current_cdc_entry);

   break;

  case mo_find_cat:

   current_cdc_entry = find_cat();

   break;

  case mo_list_cat_tracks:

   list_tracks(&current_cdc_entry);

   break;

  case mo_del_tracks:

   del_track_entries(&current_cdc_entry);

   break;

  case mo_count_entries:

   count_all_entries();

   break;

  case mo_exit:

   break;

  case mo_invalid:

   break;

  default:

   break;

  } /* switch */

 } /* while */

6. Когда цикл в функции main завершится, закройте базу данных и вернитесь в окружение. Функция announce выводит приглашающее предложение:

 database_close();

 exit(EXIT_SUCCESS);

} /* main */

static void announce(void) {

 printf("nnWelcome to the demonstration CD catalog database

  programn");

}

7. Здесь вы реализуете функцию show_menu. Эта функция проверяет, выбран ли текущий элемент каталога, используя первый символ имени в каталоге. Если элемент каталога выбран, становятся доступными дополнительные пункты меню:

static menu_options show_menu(const cdc_entry *cdc_selected) {

 char tmp_str[TMP_STRING_LEN + 1];

 menu_options option_chosen = mo_invalid;

 while (option_chosen == mo_invalid) {

  if (cdc_selected->catalog[0]) {

   printf("nnCurrent entry: ");

   printf("%s, %s, %a, %sn",

    cdc_selected->catalog, cdc_selected->title,

    cdc_selected->type, cdc_selected->artist);

   printf("n");

   printf("1 - add new CDn");

   printf("2 — search for a CDn");

   printf("3 — count the CDs and tracks in the databasen");

   printf("4 — re-enter tracks for current CDn");

   printf("5 - delete this CD, and all its tracksn");

   printf("6 - list tracks for this CDn");

   printf("q — quitn");

   printf("nOption: ");

   fgets(tmp_str, TMP_STRING_LEN, stdin);

   switch(tmp_str[0]) {

   case '1':

    option_chosen = mo_add_cat;

    break;

   case '2':

    option_chosen = mo_find_cat;

    break;

   case '3':

    option_chosen = mo_count_entries;

    break;

   case '4':

    option_chosen = mo_add_tracks;

    break;

   case '5':

    option_chosen = mo_del_cat;

    break;

   case '6':

    option_chosen = mo_list_cat_tracks;

    break;

   case 'q':

    option_chosen = mo_exit;

    break;

   }

  } else {

   printf("nn");

   printf("1 - add new CDn");

   printf("2 - search for a CDn");

   printf("3 — count the CDs and tracks in the databasen");

   printf("q — quitn");

   printf("nOption: ");

   fgets(tmp_str, TMP_STRING_LEN, stdin);

   switch(tmp_str[0]) {

   case '1':

    option_chosen = mo_add_cat;

    break;

   case '2':

    option_chosen = mo_find_cat;

    break;

   case '3':

    option_chosen = mo_count_entries;

    break;

   case 'q':

    option_chosen = mo_exit;

    break;

   }

  }

 } /* while */

 return(option_chosen);

}

Примечание

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

8. В программе есть несколько участков, в которых хотелось бы спросить пользователя о том, уверен ли он в своем запросе. Вместо того чтобы вставлять в эти места программный код, задающий вопрос, поместим его в отдельную функцию get_confirm:

static int get_confirm(const char *question) {

 char tmp_str[TMP_STRING_LEN + 1];

 printf("%s", question);

 fgets(tmp_str, TMP_STRING_LEN, stdin);

 if (tmp_str[0] == 'Y' || tmp_str[0] = 'y') {

  return(1);

 }

 return(0);

}

9. Функция enter_new_cat_entry позволяет вводить новый элемент каталога. Вам не нужно сохранять перевод строки, который возвращает функция fgets, поэтому отбросьте его:

static int enter_new_cat_entry(cdc_entry *entry_to_update) {

 cdc_entry new_entry;

 char tmp_str[TMP_STRING_LEN + 1];

 memset(&new_entry, '', sizeof(new_entry));

 printf("Enter catalog entry: ");

 (void)fgets(tmp_str, TMP_STRING_LEN, stdin);

 strip_return(tmp_str);

 strncpy(new_entry.catalog, tmp_str, CAT_CAT_LEN - 1);

 printf("Enter title: ");

 (void)fgets(tmp_str, TMP_STRING_LEN, stdin);

 strip_return(tmp_str);

 strncpy(new_entry.title, tmp_str, CAT_TITLE_LEN - 1);

 printf("Enter type: ");

 (void)fgets(tmp_str, TMP_STRING_LEN, stdin);

 strip_return(tmp_str);

1 ... 78 79 80 81 82 83 84 85 86 ... 200
На этой странице вы можете бесплатно читать книгу Основы программирования в Linux - Нейл Мэтью бесплатно.
Похожие на Основы программирования в Linux - Нейл Мэтью книги

Оставить комментарий