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

Шрифт:

-
+

Интервал:

-
+

Закладка:

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

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

 strip_return(tmp_str);

 strncpy(new_entry.type, tmp_str, CAT_TYPE_LEN - 1);

 printf("Enter artist: ");

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

 strip_return(tmp_str);

 strncpy(new_entry.artist, tmp_str, CAT_ARTIST_LEN - 1);

 printf("nNew catalog entry entry is :-n");

 display_cdc(&new_entry);

 if (get_confirm("Add this entry ? ")) {

  memcpy(entry_to_update, &new_entry, sizeof(new_entry));

  return(1);

 }

 return(0);

}

Примечание

Обратите внимание на то, что вы не применяете функцию gets, поскольку нет способа проверить переполнение буфера. Всегда избегайте применения функции gets! 

10. Теперь вы переходите к функции enter_new_track_entries для ввода информации о дорожке. Эта функция немного сложнее функции ввода элемента каталога, поскольку вы разрешаете существующему элементу-дорожке оставаться неизменным:

static void enter_new_track_entries(const cdc_entry *entry_to_add_to) {

 cdt_entry new_track, existing_track;

 char tmp_str[TMP_STRING_LEN + 1];

 int track_no = 1;

 if (entry_to_add_to->catalog[0] == '') return;

 printf("nUpdating tracks for %sn", entry_to_add_to->catalog);

 printf("Press return to leave existing description unchanged, n");

 printf(" a single d to delete this and remaining tracks, n");

 printf(" or new track descriptionn");

 while(1) {

11. Сначала вы должны проверить, существует ли уже дорожка с текущим номером дорожки. В зависимости от результатов проверки меняется строка приглашения:

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

  existing_track = get_cdt_entry(entry_to_add_to->catalog,

   track_no);

  if (existing_track.catalog[0]) {

   printf("tTrack %d: %sn", track_no,

    existing_track.track_txt);

   printf("tNew text: ");

  } else {

   printf("tTrack %d description: ", track_no);

  }

  fgets(tmp_str, TMP_STRING_LEN, stdin);

  strip_return(tmp_str);

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

  if (strlen(tmp_str) == 0) {

   if (existing_track.catalog[0] == '') {

    /* Нет в наличии элемента, поэтому вставка завершается */

    break;

   } else {

    /* Оставляем существующий элемент,

       переходам к следующей дорожке */

    track_no++;

    continue;

   }

  }

13. Если пользователь введет единичный символ d, это приведет к удалению текущей дорожки и дорожек с большими номерами. Функция del_cdt_entry вернет false, если не сможет найти дорожку, которую следует удалить:

  if ((strlen(tmp_str) == 1) && tmp_str[0] == 'd') { /* Удаляет эту и оставшиеся дорожки */

   while (del_cdt_entry(entry_to_add_to->catalog, track_no)) {

    track_no++;

   }

   break;

  }

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

  strncpy(new_track. track_txt, tmp_str, TRACK_TTEXT_LEN - 1);

  strcpy(new_track.catalog, entry_to_add_to->catalog);

  new_track.track_no = track_no;

  if (!add_cdt_entry(new_track)) {

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

   break;

  }

  track_no++;

 } /* while */

}

15. Функция del_cat_entry удаляет элемент каталога. Никогда не разрешайте хранить дорожки для несуществующего элемента каталога.

static void del_cat_entry(const cdc_entry *entry_to_delete) {

 int track_no = 1;

 int delete_ok;

 display_cdc(entry_to_delete);

 if (get_confirm("Delete this entry and all it's tracks? ")) {

  do {

   delete_ok = del_cdt_entry(entry_to_delete->catalog, track_no);

   track_no++;

  } while(delete_ok);

  if (!del_cdc_entry(entry_to_delete->catalog)) {

   fprintf(stderr, "Failed to delete entryn");

  }

 }

}

16. Следующая функция — утилита для удаления всех дорожек элемента каталога:

static void del_track_entries(const cdc_entry *entry_to_delete) {

 int track_no = 1;

 int delete_ok;

 display_cdc(entry_to_delete);

 if (get_confirm("Delete tracks for this entry? ")) {

  do {

   delete_ok = del_cdt_entry(entry_to_delete->catalog, track_no);

   track_no++;

  } while(delete_ok);

 }

}

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

static cdc_entry find_cat(void) {

 cdc_entry item_found;

 char tmp_str[TMP_STRING_LEN + 1];

 int first_call = 1;

 int any_entry_found = 0;

 int string ok;

 int entry_selected = 0;

 do {

  string_ok = 1;

  printf("Enter string to search for in catalog entry: ");

  fgets(tmp_str, TMP_STRING_LEN, stdin);

  strip_return(tmp_str);

  if (strlen(tmp_str) > CAT_CAT_LEN) {

   fprintf(stderr, "Sorry, string too long, maximum %d

    charactersn", CAT_CAT_LEN);

   string_ok = 0;

  }

 } while (!string_ok);

 while (!entry_selected) {

  item_found = search_cdc_entry(tmp_str, &firstcall);

  if (item_found.catalog[0] != '') {

   any_entry_found = 1;

   printf("n");

   display_cdc(&item_found);

   if (get_confirm("This entry? ")) {

    entry_selected = 1;

   }

  } else {

   if (any_entry_found) printf("Sorry, no more matches foundn");

   else printf("Sorry, nothing foundn");

   break;

  }

 }

 return(item_found);

}

18. Функция list_tracks — утилита, которая выводит все дорожки для заданного элемента каталога:

static void list_tracks(const cdc_entry *entry_to_use) {

 int track_no = 1;

 cdt_entry entry_found;

 display_cdc(entry_to_use);

 printf("nTracksn");

 do {

  entry_found = get_cdt_entry(entry_to_use->catalog, track_no);

  if (entry_found.catalog[0]) {

   display_cdt(&entry_found);

   track_no++;

  }

 } while(entry_found.catalog[0]);

 (void)get_confirm("Press return");

} /* list_tracks */

19. Функция count_all_entries подсчитывает все дорожки:

static void count_all_entries(void) {

 int cd_entries_found = 0;

 int track_entries_found = 0;

 cdc_entry cdc_found;

 cdt_entry cdt_found;

 int track_no = 1;

 int first_time = 1;

 char *search_string = "";

 do {

  cdc_found = search_cdc_entry(search_string, &first_time);

  if (cdc_found.catalog[0]) {

   cd_entries_found++;

   track_no = 1;

   do {

    cdt_found = get_cdt_entry(cdc_found.catalog, track_no);

    if (cdt_found.catalog[0]) {

     track_entries_found++;

     track_no++;

    }

   } while (cdt_found.catalog[0]);

  }

 } while (cdc_found.catalog[0]);

 printf("Found %d CDs, with a total of %d tracksn",

  cd_entries_found, track_entries_found);

 (void)get_confirm("Press return");

}

20. Теперь у вас есть утилита display_cdc для вывода элемента каталога:

static void display_cdc(const cdc_entry *cdc_to_show) {

 printf("Catalog: %sn", cdc_to_show->catalog);

 printf("ttitle: %sn", cdc_to_show->title);

 printf("ttype: %sn", cdc_to_show->type);

 printf("tartist: %sn", cdc_to_show->artist);

}

и утилита display_cdt для отображения элемента-дорожки:

static void display_cdt(const cdt_entry *cdt_to_show) {

 printf("%d: %sn", cdt_to_show->track_no,

  cdt_to_show->track_txt);

}

21. Служебная функция strip_return удаляет завершающий строку символ перевода строки. Помните о том, что Linux, как и UNIX, использует один символ перевода строки для обозначения конца строки.

static void strip_return(char *string_to_strip) {

 int len;

 len = strlen(string_to_strip);

 if (string_to_strip[len - 1] == 'n')

 string_to_strip[len - 1] = '';

}

22. Функция command_mode предназначена для синтаксического анализа аргументов командной строки. Функция getopt — хороший способ убедиться в том, что ваша программа принимает аргументы, соответствующие стандартным соглашениям, принятым в системе Linux.

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

 int c;

 int result = EXIT_SUCCESS;

 char *prog_name = argv[0];

 /* Эти внешние переменные используются функцией getopt */

 extern char *optarg;

 extern optind, opterr, optopt;

 while ((c = getopt(argc, argv, ":i")) != -1) {

  switch(c) {

  case 'i':

   if (!database_initialize(1)) {

    result = EXIT_FAILURE;

    fprintf(stderr, "Failed to initialize databasen");

   }

   break;

  case ':':

  case '?':

  default:

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

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