Запросы к базе данных компакт-дисков
⇐ ПредыдущаяСтр 9 из 9 Теперь рассмотрим функции для доступа к данным, которые для упрощения доступа хранятся в паре простых файлов как поля, разделенные запятыми. 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 = '\0'; title = found + 1; /* Стирает следующую запятую в элементе, укорачивая его только до заголовка */ if (found == strstr(title, ", ")) { *found = '\0'; /* Теперь проверяет, есть ли совпадающая строка */ 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] = '\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] == '\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 Listing\n"); /* Записывает сведения о дорожке на панель */ 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 Резюме В этой главе вы изучили библиотеку curses. Она предлагает текстовым программам удобный способ управления экраном и считывания данных с клавиатуры. Хотя библиотека curses не обеспечивает такого уровня управления, как общий терминальный интерфейс (GTI) и прямой доступ к структуре terminfo , ею гораздо легче пользоваться. Если вы пишете полноэкранное текстовое приложение, стоит рассмотреть возможность применения в нем библиотеки curses для управления экраном и чтения данных с клавиатуры.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|