Студопедия

Главная страница Случайная страница

КАТЕГОРИИ:

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






Листинг 9.1






 

#include < fstream.h>

#include < string.h>

#include < stdlib.h> //#include < windows.h> //0

int main()

const int l name = 30, l year = 5, l pay = 10,

l buf = l name + l pay; //1

 

struct Man //2

{

int birth year;

char name[l name + 1];

float pay;

};

const int l dbase = 100;

Man dbase [l dbase]; //3

 

char buf[l buf + 1]; //4

char name[l name + 1]; //5

 

ifstream fin(" dbase.txt", //6 ios:: in|ios:: nocreate);

if (! fin)

{

cout < < " Ошибка открытия файла";

return 1;

}

 

int i = 0;

while(fin.getline(buf.l buf)) //7

{

if (i > = 1 dbase)

{

cout < < " Слишком длинный файл";

return 1;

}

strncpy(dbase[i].name.buf.l name);

dbase[i].name[l name] = '\0';

dbase[i].birth year = atoi(& buf[l name]);

dbase[i].pay = atof(& buf[l name + l year]);

i++;

}

int n record = i.n man = 0; //8

float mean pay = 0;

 

while(true) //9

{

cout < < " Введите фамилию или слово end": cin > > name;

//DemToChar(name, name); //10

if(strcmp(name. " end") == 0)break; //11

bool not found = true; //12

for (i = 0; i < n record; i++) //13

{

 

if (strstr(dbase[i]. name. name)) //14

if (dbase[i]. name[strlen(name)] == '')//15

{

strcpy(name. dbase[i]. name);

// CharToOem(name.name); //16

cout < < name < < dbase[i].birth year < < '' < < dbase[i].pay < < endl;

n man++; mean_pay += dbase[i].pay;

not found = false;

}

}

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

}

if (n man > 0) cout < < " Средний оклад: " < < mean pay/ n man < < endl; //17

 

return 0;

}

 

В операторе 1 заданы име­нованные константы, в которых хранится формат входного файла, то есть длина каждого из полей записи (строки файла). Такой подход позволяет при необходи­мости легко вносить в программу изменения. Длина буфера, в который будет считываться каждая строка файла, вычисляется как сумма длин указанных полей. В операторе 2 определяется структура Man для хранения сведений об одном сотруд­нике. Длина поля, в котором будет находиться фамилия, задана с учетом заверша­ющего нуль-символа. В операторе 3 определяется массив структур dbase для хра­нения всей базы. Его размерность также задается именованной константой. В операторах 4 и 5 задаются промежуточные переменные: буфер buf для ввода стро­ки из файла и строка name для фамилии запрашиваемого сотрудника. В операторе 6 выполняется открытие файла dbase. txt для чтения. Предполагается, что этот файл находится в том же каталоге, что и текст программы, иначе следует указать полный путь. Входной файл следует создать в любом текстовом редакторе до первого запуска программы в соответствии с форматом, заданным в условии задачи. Файл для целей тестирования должен состоять из нескольких строк, при­чем необходимо предусмотреть случай, когда одна фамилия является частью дру­гой (например, Иванов и Ивановский). Не забудьте проверить, выдается ли диаг­ностическое сообщение, если файл не найден.

Цикл 7 выполняет построчное считывание из файла в строку buf и заполнение оче­редного элемента массива dbase. Счетчик 1 хранит индекс первого свободного эле­мента массива. Для формирования полей структуры используются функции ко­пирования строк strncpy, преобразования из строки в целое число atoi и преобразования из строки в вещественное число atof. Обратите внимание на то, что завершающий нуль-символ в поле фамилии заносится «вручную», поскольку функция strncpy делает это только в случае, если строка-источник короче строки-приемника. В функцию atoi передается адрес начала подстроки, в которой находится год рождения. При каждом проходе цикла выполняется проверка, не превышает ли считанное количество строк размерность массива. При тестиро­вании программы в этот цикл следует добавить контрольный вывод на экран счи­танной строки, а также сформированных полей структуры. Для проверки выдачи диагностического сообщения следует временно задать константу ljjbase равной, а затем меньшей фактического количества строк в файле.

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

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

 

while(fin.getline(buf.l buf)& & i < l dbase)

{

-

i++;

}

if (i > = l dbase)

{

cout < < " Слишком длинный файл";

return 1;

}

 

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

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

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

 

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

 

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

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

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

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

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

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

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

 


Поделиться с друзьями:

mylektsii.su - Мои Лекции - 2015-2024 год. (0.008 сек.)Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав Пожаловаться на материал