Студопедия — ВНИМАНИЕ. При заполнении массива из файла обязательно контролируйте выход за границы масси и при необходимости выдавайте предупреждающее сообщение
Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

ВНИМАНИЕ. При заполнении массива из файла обязательно контролируйте выход за границы масси и при необходимости выдавайте предупреждающее сообщение






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

 

Кстати, можно записать эту проверку и так:

 

while (fin.getline(buf, l_buf) & & i < l_dbase) { ... i++; } if (i > = l_dbase) { cout < < " Слишком длинный файл "; return 1; }

 

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

 

Цикл поиска сотрудников по фамилии организован как бесконечный (оператор 9) с принудительным выходом (оператор И). Некоторые специалисты считают, что такой способ является плохим стилем, и для выхода из цикла следует определить переменную-флаг, но нам кажется иначе.

 

Впрочем, в данном случае выход из цикла действительно организован не лучшим образом, поскольку пользователь вынужден для окончания работы с программой ввести слово end в нижнем регистре. Более удобным был бы выход из цикла по нажатию, например, клавиши Esc. К сожалению, в рамках стандарта это сделать невозможно, однако в большинстве библиотек есть функции типа getch и kbhit, позволяющие анализировать нажатие клавиш. В общем случае, несомненно, следует выбирать интерфейс, наиболее удобный для пользователя, поскольку именно для него и пишутся все без исключения программы.

 

В операторе 12 определяется переменная-флаг not_found для того, чтобы после окончания цикла поиска было известно, завершился ли он успешно. Обратите внимание на имя переменной: его следует выбирать таким образом, чтобы по нему было ясно, какое значение является истинным. Как видите, в этом случае оператор

 

if (not_found) cout < < " Такого сотрудника нет " < < endl;

 

хорошо понятен без дополнительных комментариев.

 

В операторе 13 организуется цикл просмотра массива структур (просматриваются только заполненные при вводе элементы). Проверка совпадения фамилии сотрудника производится в два этапа. В операторе 14 с помощью функции strstr поиска подстроки определяется, содержится ли в поле базы паше искомая последовательность букв, а в операторе 15 проверяется, есть ли непосредственно после фамилии пробел (если пробела нет, то искомая фамилия является частью другой, и эта строка нам не подходит). Такая простая проверка возможна из-за условия задачи, по которому фамилия должна начинаться с первой позиции каждой строки.

 

Когда вы дойдете до отладки этой части программы, то, вполне возможно, столкнетесь с непонятной на первый взгляд проблемой: программа не может найти запись с заданной фамилией. Впрочем, этот эффект проявляется, только если вы работаете в среде Windows и только на фамилиях, записанных в базе на русском языке; стоит только перейти на латиницу, как все начинает работать нормально. Здесь есть одна тонкость, связанная с разной кодировкой букв русского алфавита (кириллицы) в операционных системах MS DOS и Windows, о чем уже говорилось на первом семинаре.

 

Напомним, что если вы работаете в интегрированной среде Visual C++ в режиме консольных приложений, то весь ввод-вывод осуществляется в кодировке ASCII. Поэтому поведение данной программы будет различным в зависимости от кодировки текста в файле dbase.txt, а последняя определяется тем, в каком текстовом редакторе вы создавали этот файл.

 

Допустим, что вы использовали один из редакторов под MS DOS, к примеру Dos Navigator или Far. В этом случае кодировка в файле и в окне вывода одна и та же и программа работает нормально. Но если вы заполнили файл dbase.txt в редакторе NotePad или WordPad (кодировка ANSI), то программа не будет работать с русскоязычными фамилиями.

 

Если материал первого семинара еще не окончательно улетучился из вашей памяти, то вы знаете, что в таких случаях надо использовать функцию OemToChar(), переводящую символы из кодировки ASCII в кодировку ANSI для введенной с консоли фамилии (переменная name). Для этого достаточно раскомментировать оператор 10 в нашей программе. Аналогично, для нормального вывода текста в консольное окно необходимо обратное преобразование с помощью функции CharToOem() — раскомментируйте оператор 16. Применение указанных функций требует подключения заголовочного файла < windows. h> (раскомментируйте оператор 0).

 

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

Продолжим анализ программы. Мы остановились на том, что алгоритм составлен в предположении, что фамилия начинается с первой позиции записи в базе данных. Измените программу так, чтобы это ограничение можно было снять. Для этого придется проверить, стоит ли перед фамилией пробел в том случае, если она не начинается с первой позиции. Аналогичная проблема рассматривалась на предыдущем семинаре (задача 5.2). Внесите в тестовый пример изменения, необходимые для тестирования этой части программы.

 

Проверка переменной n_man в операторе 17 необходима для того, чтобы в случае, если пользователь не введет ни одной фамилии, совпадающей с фамилией в базе, не выполнялось деление на 0.

 

Крупным недостатком нашей программы является то, что вводить фамилию сотрудника требуется именно в том регистре, в котором она присутствует в базе. Для преодоления этого недостатка необходимо перед сравнением фамилий переводить все символы в один регистр. Для символов латинского алфавита в библиотеке есть функции tolower(c) и toupper(c), переводящие переданный им символ с в нижний и верхний регистр соответственно, аналогичные функции для символов русского алфавита придется написать самостоятельно.

 

Если в базе есть несколько сотрудников с одной и той же фамилией, программа выдаст сведения обо всех.

 

А теперь давайте рассмотрим вариант записи этой же программы с помощью библиотечных функций ввода-вывода:

 

#include < stdio.h> #include < string.h> // #include < windows.h> // 0 int main () { const int l_name < < 30; // 1 struct Man { int birth_year; char name[l_name + 1]; float pay; }; const int l_dbase = 100; Man dbase[l_dbase]; char name[l_name + 1]; FILE *fin; if ((fin = fopen(" dbase.txt", " r")) == NULL){ puts(" Ошибка открытия файла\n"); return 1; } int i = 0; while (! feof(fin)) { fgets(dbase[i].name, l_name, fin); fscanf(fin, " %i%f\n", & dbase[i].birth_year, & dbase[i].pay); // 2 i++; if (i > 1 dbase) { puts(" Слишком длинный файл\n"); return 1; } } int n_record = i, n_man = 0; float mean_pay = 0; while (true) { puts(" Введите фамилию или нажмите Enter для окончания: "); gets (name); if (strlen(name) == 0)break; // 3 // OemToChar(name. Name); // 4 bool not_found = true; for (i = 0; i < n_record; i++) { if (strstr(dbase[i].name. name)) if (dbase[i].name[strlen(name)] == ' ') { strcpy(name, dbase[i].name); // CharToOem(name. name); printf(" %30s%5i%10.2f\n". name, dbase[i].birth_year, dbase[i].pay); n_man++; mean_pay += dbase[i].pay; not_found = false; } } if (not_found) puts(" Такого сотрудника нет\n"); } if (n_man > 0) printf(" Средний оклад: %10.2f\n", mean_pay / n_man); return 0; }

 

Из всех именованных констант осталась одна, задающая длину поля фамилии (l_name, оператор 1). Все остальные константы определять нет смысла, потому что ввод осуществляется не через буферную переменную, а непосредственно в поля структуры с помощью функции чтения строки fgets и форматного ввода fscant (оператор 2). Эта функция сама выполняет действия по преобразованию подстроки в число, которые мы явным образом задавали в предыдущей программе.

 

Как и в предыдущей версии, программу необходимо «настроить» на ожидаемую кодировку символов. Если вы работаете в среде Visual C++ и готовите текстовый файл dbase.txt с помощью Windows-ориентированного текстового редактора, то раскомментируйте операторы 4 и 5 для преобразования символов из кодировки ASCII в кодировку ANSI и обратно, а также оператор 0 для подключения заголовочного файла < windows.h>.

 

Мы упростили выход из цикла ввода запросов, теперь для завершения цикла достаточно нажать клавишу Enter (оператор 3). Для вывода сведений о сотруднике мы использовали функцию printf (оператор 6). Как видите, иногда старые добрые функции могут сделать программу более простой и наглядной! Это происходит, когда при вводе и выводе требуется форматирование разнотипных данных.

 







Дата добавления: 2014-11-10; просмотров: 737. Нарушение авторских прав; Мы поможем в написании вашей работы!



Функция спроса населения на данный товар Функция спроса населения на данный товар: Qd=7-Р. Функция предложения: Qs= -5+2Р,где...

Аальтернативная стоимость. Кривая производственных возможностей В экономике Буридании есть 100 ед. труда с производительностью 4 м ткани или 2 кг мяса...

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

Расчетные и графические задания Равновесный объем - это объем, определяемый равенством спроса и предложения...

Этапы творческого процесса в изобразительной деятельности По мнению многих авторов, возникновение творческого начала в детской художественной практике носит такой же поэтапный характер, как и процесс творчества у мастеров искусства...

Тема 5. Анализ количественного и качественного состава персонала Персонал является одним из важнейших факторов в организации. Его состояние и эффективное использование прямо влияет на конечные результаты хозяйственной деятельности организации.

Билет №7 (1 вопрос) Язык как средство общения и форма существования национальной культуры. Русский литературный язык как нормированная и обработанная форма общенародного языка Важнейшая функция языка - коммуникативная функция, т.е. функция общения Язык представлен в двух своих разновидностях...

Ваготомия. Дренирующие операции Ваготомия – денервация зон желудка, секретирующих соляную кислоту, путем пересечения блуждающих нервов или их ветвей...

Билиодигестивные анастомозы Показания для наложения билиодигестивных анастомозов: 1. нарушения проходимости терминального отдела холедоха при доброкачественной патологии (стенозы и стриктуры холедоха) 2. опухоли большого дуоденального сосочка...

Сосудистый шов (ручной Карреля, механический шов). Операции при ранениях крупных сосудов 1912 г., Каррель – впервые предложил методику сосудистого шва. Сосудистый шов применяется для восстановления магистрального кровотока при лечении...

Studopedia.info - Студопедия - 2014-2024 год . (0.008 сек.) русская версия | украинская версия