Приветствую вас! Вы находитесь на сайте Fance.Ru. Наш сайт посвящен тематике Система uCoz, PhotoShop, Counter-Strike 1.6, Counter-Strike: Source, а также Игры для PC. Вы можете скачать обсолютно любой файл, который вам понравиться. На нашем сайте вы можете найти все что нужно для создания сайта, его дизайна и не только. На нашем сайте установлен оригинальный дизайн и расположение блоков и модулей где вы без труда найдете что искали. И не забываем про активный форум где вам всегда помогут если у вас возникнут вопросы. В мини чате только краткое общение, обсуждение и помощь идет на форуме, где созданы для этого разделы. Дерзайте ;)
17.05.2024, 05:22
kuz0n
kuz0n (Пользователи)
  • Репутация: 2
  • Файлы: 53
viva-dom
viva-dom (Пользователи)
  • Репутация: 0
  • Файлы: 0
olimp-stoy
olimp-stoy (Пользователи)
  • Репутация: 0
  • Файлы: 0
Главная » Статьи » Программирование » С++

Исправленная программа управления базой данных сотрудников
В первой версии этой программы были при жесткой проверке обнаружены серьезные баги:
1. в функции выбора профессии при вводе вместо числового значения символа, программа зацикливалась (бесконечное колличество раз совершала одну и ту же операцию)
2. не могла правильно определить совпадение профессии при отличиях в регистрах букв("бухгалтер" и "Бухгалтер" были для нее совершенно разными словами)
 
_______________

1. Первая проблемма не составила для меня какого-нибудь затруднения. Я решил ее за несколько минут. Для этого мне просто понадобилось немного изменить функцию change_oklad.
Вот новая реализация этой функции:

void change_oklad(Employer sotrudnik[], const int& counter)
{
 if(proverka(counter))
 {
  char ans;

  do
  {
   string por;
   int number;
   double newoklad;

   vivod_vseh(sotrudnik, counter);

   cout << endl << "Введите порядковый номер сотрудника: ";
   cin  >> por;
   number = atoi(&char(por[0]));

   // Защита от дурака
   while((number > (counter)) || number <= 0)
   {
    cout << endl << "Ошибка!"
      << endl << "На предприятии нет такого колличества сотрудников!"
      << endl << "Введите еще раз: ";
    cin  >> por;
    number = atoi(&char(por[0]));
   }

   cout << "Введите новый размер оклада сотрудника: ";
   cin  >> newoklad;
  
   // Защита от дурака
   while(newoklad < 0)
   {
    cout << endl << "Ошибка!"
     << endl << "Оклад сотрудника не может составлять сумму, ниже нуля"
     << endl << "Введите еще раз: ";
    cin  >> newoklad;
   }

   sotrudnik[number - 1].new_oklad(newoklad);
   cout << endl << sotrudnik[number - 1] << endl;

   ans = get_ans();
  }while(ans != 'n' && ans != 'N');
 }
}

Основное отличие состоит в том, что пользователь теперь вроизводит ввод данных не в числовую переменную непосредственно, а в переменную типа string. Затем программа берет первый символ из этой строки (а нумерация списка не может быть выше 4-х элементов, следовательно большее колличество символов пользователь вряд-ли будет сознательно вводить) и преобразует его в числовое значение при помощи функции atoi(*char ). Нужно заметить, что передается именно адрес символа, поскольку изначально функция предназначена для работы с символьными массивами. Аналогичный код я вставил и в систему защиты от дурака.
Этих мер было достаточно, чтобы решить проблему

2. Вторая проблема оказалась не столько сложной, сколько кропотливой. Дело в том, что для правильного сравнения двух переменных типа string, нужно, чтобы у них были одинаковые регистры букв (все буквы либо большие заглавные, либо обычные маленькие). В С++ есть стандартная функция подобного преобразования, однако, она работает только для латинских символов. Мне пришлось составлять собственную функцию, которую я назвал melkie_literi. И здесь я столкнулся с основной проблемой.
Дело в том, что любой символ, хранящийся в ячейке памяти (переменная типа char) имеет численное значение. Этот "индекс" используется при выводе символа на экран по таблице символов. В кодировках DOS и Windows используется различная индексация русских букв, однако индексация латинских символов одинакова.
Я составил простенький алгоритм, чтобы получить эту таблицу и на ее основе разработать способ преобразования русских символов. Я основывался на том, что тип char занимает в памяти 1 байт, следовательно, он может иметь значения от 0 до 255. В принципе, мои догадки оказались верными, однако они имели обратный характер, в прямом смысле этого слова.
Вот, что я получил:

  0     @ 64    А 128   └ 192
☺ 1     A 65    Б 129   ┴ 193
☻ 2     B 66    В 130   ┬ 194
♥ 3     C 67    Г 131   ├ 195
♦ 4     D 68    Д 132   ─ 196
♣ 5     E 69    Е 133   ┼ 197
♠ 6     F 70    Ж 134   ╞ 198
  7     G 71    З 135   ╟ 199
  8     H 72    И 136   ╚ 200
  9     I 73    Й 137   ╔ 201
 10     J 74    К 138   ╩ 202
♂ 11    K 75    Л 139   ╦ 203
♀ 12    L 76    М 140   ╠ 204
 13     M 77    Н 141   ═ 205
♫ 14    N 78    О 142   ╬ 206
☼ 15    O 79    П 143   ╧ 207
► 16    P 80    Р 144   ╨ 208
◄ 17    Q 81    С 145   ╤ 209
↕ 18    R 82    Т 146   ╥ 210
‼ 19    S 83    У 147   ╙ 211
¶ 20    T 84    Ф 148   ╘ 212
§ 21    U 85    Х 149   ╒ 213
▬ 22    V 86    Ц 150   ╓ 214
↨ 23    W 87    Ч 151   ╫ 215
↑ 24    X 88    Ш 152   ╪ 216
↓ 25    Y 89    Щ 153   ┘ 217
→ 26    Z 90    Ъ 154   ┌ 218
← 27    [ 91    Ы 155   █ 219
∟ 28    \ 92    Ь 156   ▄ 220
↔ 29    ] 93    Э 157   ▌ 221
▲ 30    ^ 94    Ю 158   ▐ 222
▼ 31    _ 95    Я 159   ▀ 223
  32    ` 96    а 160   р 224
! 33    a 97    б 161   с 225
" 34    b 98    в 162   т 226
# 35    c 99    г 163   у 227
$ 36    d 100   д 164   ф 228
% 37    e 101   е 165   х 229
& 38    f 102   ж 166   ц 230
' 39    g 103   з 167   ч 231
( 40    h 104   и 168   ш 232
) 41    i 105   й 169   щ 233
* 42    j 106   к 170   ъ 234
+ 43    k 107   л 171   ы 235
, 44    l 108   м 172   ь 236
- 45    m 109   н 173   э 237
. 46    n 110   о 174   ю 238
/ 47    o 111   п 175   я 239
0 48    p 112   ░ 176   Ё 240
1 49    q 113   ▒ 177   ё 241
2 50    r 114   ▓ 178   Є 242
3 51    s 115   │ 179   є 243
4 52    t 116   ┤ 180   Ї 244
5 53    u 117   ╡ 181   ї 245
6 54    v 118   ╢ 182   Ў 246
7 55    w 119   ╖ 183   ў 247
8 56    x 120   ╕ 184   ° 248
9 57    y 121   ╣ 185   ∙ 249
: 58    z 122   ║ 186   · 250
; 59    { 123   ╗ 187   √ 251
< 60    | 124   ╝ 188   № 252
= 61    } 125   ╜ 189   ¤ 253
> 62    ~ 126   ╛ 190   ■ 254
? 63    ⌂ 127   ┐ 191     255  

В этой таблице отображены символы и соответствующие им значения индексов. Здесь я встретил первую проблему. Латинские символы идут подряд, т.е. их порядок ничем не прерывается. Это значет, что абсолютно любой английский символ можно преобразовать в большой или маленький, посто прибав или отняв определенное значение. С кириллицей все оказалось не так просто! Дело в том, что после маленькой буквы 'п'идет куча какой-то херни, и только через 49 символов ряд русских символов продолжается.
Хорошо... я составил по этой таблице алгоритм, который разбивал весь диапазон значений на три:
1) А-П
2) Р-Я
3) все остальное
Но когда я его скомпилировал, он не работал, падла(!!!)

Причиной оказалось то, что вся эта таблица хранится в отрицательных значениях! (Хотел бы я посмотреть в глаза тому дебилу, который придумал сделать это именно так!) У символа "А" был индекс -128 вместо 128, а символ "Я" имел индекс -17 вместо 239 (ну бля дибилы так токо могли сделать).

Я пол часа поломал голову над новой проблемой, чуть-чуть преобразовал изначальный алгоритм и получил вот что:

string Employer::melkie_literi(string insert)
{
 for(int i = 0; i < insert.length(); i++)
 {
  int temp = insert[i];
  if(temp <= -97 && temp >= -128)
  {
   if (temp >= -112)
   {
    insert[i] = char(temp + 80);
   }
   else
   {
    insert[i] = char(temp + 32);
   }
  }
 }

 return insert;
}

Как вы догадались, функцию melkie_literi я зафигачил в класс Employer, причем в закрытую часть private, поскольку она используется только внутри класса. Следовательно, я изменил и сам класс. Вот его новое определение:

class Employer
{
public:
 Employer();
 // Конструктор по умолчанию

 ~Employer(){};
 // Деструктор

 bool find_prof(const string& prof);
 // Сравнивает название переменных prof и Job, элемента
 // клaссa Employer. При совпадении возвращает true,
 // в обратном случае - false.

 void new_oklad(const double& newoklad);
 // Функция меняющая значение Oklad в классе Employer


 friend istream& operator >> (istream& ins, Employer& human);
 // Перегруженный оператор вывода для класса Employer

 friend ostream& operator << (ostream& outs, const Employer& human);
 // Перегруженная функция вывода для класса Employer

private:
 string Surname; // Фамилия
 string Name; // Имя
 string Job;  // Профессия
 double Oklad; // Оклад
 double Stavka; // Ставка

 string melkie_literi(string insert);
 // Функция, которая заменяет все заглавные русские
 // буквы в строке типа string на незаглавные и
 // возвращает преобразованную строку, типа string.
};

Алгоритм отлично работал, и единственное, что мне оставалось доделать - преобразовать под новый код функцию find_prof. Вот она (кстати, тоже принадлежит классу Employer:

bool Employer::find_prof(const string& prof)
{
 string prof_m = melkie_literi(prof);
 string Job_m  = melkie_literi(Job);
 if(prof_m == Job_m)
  return true;
 else
  return false;
}

функция сравнивает не исходные string'и, а преобразованные, у которых одинаковый регистр всех букв.

Преобразованный код программы можно скачать тут:
Скомпилированную программу можно скачать тут:
Обсуждение на форуме:

С уважением, ваш A.Kuznetsov

Категория: С++ | Добавил: kuz0n (25.10.2007) | Автор: A.Kuznetsov E W
Просмотров: 4451 | Комментарии: 3 | Рейтинг: 0.0/0
Всего комментариев: 3
class="overflow">
Мини-чат
Наши партнеры

Статистика
Онлайн всего: 1
Гостей: 1
Пользователей: 0
Всего: 53 +0 новых
Никого нету
Посетители за сегодня ()