Премини към съдържанието
Форумът в приложение

По-лесно сърфиране. Научи повече.

Kaldata.com - Форуми

Приложение на форума на цял екран с push известия, значки и други.

За да инсталирате това приложение на iOS и iPadOS
  1. Докоснете Иконата за споделяне в Safari
  2. Превъртете менюто и докоснете Добавяне към началния екран.
  3. Докоснете Добавяне в горния десен ъгъл.
За да инсталирате това приложение на Android
  1. Докоснете менюто с 3 точки (⋮) в горния десен ъгъл на браузъра.
  2. Докоснете Добавяне към началния екран или Инсталиране на приложение.
  3. Потвърдете, като докоснете Инсталиране.

Добре дошли!

Добре дошли в нашите форуми, пълни с полезна информация. Имате проблем с компютъра или телефона си? Публикувайте нова тема и ще намерите решение на всичките си проблеми. Общувайте свободно и открийте безброй нови приятели.

Моля, регистрирайте се за да публикувате тема и да получите пълен достъп до всички функции.

 

C++ задача

Featured Replies

Да се състави програма за нуждите на производствена организация, която съхранява в масив следните данни за работниците:
-    име;
-    ЕГН;
-    размер на дневното заплащане;
-    брой на отработени дни през месеца;
и извършва следните операции, избирани от меню:
-    добавя към масива данните на нов работник;
-    извежда всички въведени данни;
-    извежда имената на мъжете с най-малко със заработка между 300 и 500 лв;
-    създава нов масив с имената и за жените със заработка над 300 лв, родени през посочен месец.

моят код:

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;

class Employee {
private:
    string name;
    string EGN;
    float payment;
    int workingdays;
public:
    void setData();
    void display();
    string getName();
    float getpayment();
    int getWorkingdays();
    int getPol();
};


string Employee::getName() {
    return name;
}

float Employee::getpayment() {
    return payment;
}

int Employee::getWorkingdays() {
    return workingdays;
}

// Член - функция за намиране пола
int Employee::getPol() {
    char B[2];;
    strncpy(b, EGN + 8, 1); b[1] = '\0';
    return atoi(b) % 2;
}

void Employee::setData() {
    cin.ignore();
    cout << "Въведи име: "; getline(cin, name);
    cout << "Въведи ЕГН: "; getline(cin, EGN);
    cout << "Въведи дневно заплащане: "; cin >> payment;
    cout << "Въведи брой отработени дни през месеца: "; cin >> workingdays;
}

void Employee::display() {
    cout << "Име: " << name << endl;
    cout << "ЕГН: " << EGN << endl;
    cout << "Дневно заплащане: " << payment << endl;
    cout << "Брой отработени дни: " << workingdays << endl;
}

int main() {
    system("chcp 1251");
    Employee employees[20];
    int countST = 0;
    char codeOp;
    do {
        cout << "1 - добавя данни за нов работник " << endl;
        cout << "2 - извежда всички въведени данни " << endl;
        cout << "3 - извежда имената на мъжете с най-малко със заработка между 300 и 500 лв " << endl;
        cout << "4 - създава нов масив с имената и за жените със заработка над 300 лв, родени през посочен месец. " << endl;
        cout << "Посочете операция или 0 за край: " << endl;
        cin >> codeOp;
        switch (codeOp) {
        case'0':
            break;
        case'1': employees[countST++].setData();
            break;
        case'2':cout << "Списък на всички работници: " << endl;
            for (int i = 0; i < countST; i++) {
                employees[i].display();
            }
            break;
        case'3':
            break;
        default: cout << "Error! " << endl;
            break;
        }
    } while (codeOp != 0);
}

Как да намеря пола от ЕГН и да изведа имената на мъжете и отделно на жените?

1. В програмния код е дефиниран масив от класове с фиксирана дължина. Това е проблем. Би следвало дължината на масива да е определена чрез USER INPUT, запазен в променлива, която се използва за дължина на масива от класове. Или да се използва VECTOR, който позволява във всеки един момент дължината му да бъде променена. С VECTOR обаче се работи една идея по-тегаво.
2. Предпоследната цифра на ЕГН-то е четна за мъже и нечетна за жени. Необходимо ти е просто да добавиш един nested IF във FOR цикъла.
AKO се дели на 2 без остатък - МЪЖ -> направи това. Ако не се дели на 2 без остатък - ЖЕНА -> направи това.
3. Не е обслужен варианта на ЕГН на човек роден след 2000г. или преди 1900г. Докато 1900г. са изключения вече, то има много родени след 2000г., които са работещи.
4. Като сме започнали, хубаво е да се прави проверка на ЕГН-то за валидност при въвеждането му. Никъде не е написано в заданието, но е добра идея и ще даде бонус.

  • Автор
преди 4 минути, jtaggerx написа:

1. В програмния код е дефиниран масив от класове с фиксирана дължина. Това е проблем. Би следвало дължината на масива да е определена чрез USER INPUT, запазен в променлива, която се използва за дължина на масива от класове. Или да се използва VECTOR, който позволява във всеки един момент дължината му да бъде променена. С VECTOR обаче се работи една идея по-тегаво.
2. Предпоследната цифра на ЕГН-то е четна за мъже и нечетна за жени. Необходимо ти е просто да добавиш един nested IF във FOR цикъла.
AKO се дели на 2 без остатък - МЪЖ -> направи това. Ако не се дели на 2 без остатък - ЖЕНА -> направи това.
3. Не е обслужен варианта на ЕГН на човек роден след 2000г. или преди 1900г. Докато 1900г. са изключения вече, то има много родени след 2000г., които са работещи.

Там е проблема че функцията getPol не работи за намиране на четно или нечетно число за пола

преди 38 минути, DeathHour написа:

Там е проблема че функцията getPol не работи за намиране на четно или нечетно число за пола

Броенето започва от 0. ЕГН е 10 цифри. Следователно от 0 до 9. Трябва ти 8 знак от стринга. 
Проверяваш дали се дели на 2 без остатък. Ако да - то мъж, ако не - то жена.
Какъв е проблема да се напише нещо такова:

char pol = EGN[8];
int gpol = pol - '0';
IF(gpol % 2 ==0)
{
МЪЖ;
}
ELSE
{
ЖЕНА;
}

И никога не декларирай без да инициализираш. Че в дадени случаи можеш да останеш изненадан, че това което ти си мислил,
че ще се случи е коренно различно от това, което се случва.
И най-добре прави проверка дали има 10 знака въведени за ЕГН, че всичко отива у рЯката ако не са 10!

  • Автор
преди 34 минути, jtaggerx написа:

Броенето започва от 0. ЕГН е 10 цифри. Следователно от 0 до 9. Трябва ти 8 знак от стринга. 
Проверяваш дали се дели на 2 без остатък. Ако да - то мъж, ако не - то жена.
Какъв е проблема да се напише нещо такова:

char pol = EGN[8];
int gpol = pol - '0';
IF(gpol % 2 ==0)
{
МЪЖ;
}
ELSE
{
ЖЕНА;
}

И никога не декларирай без да инициализираш. Че в дадени случаи можеш да останеш изненадан, че това което ти си мислил,
че ще се случи е коренно различно от това, което се случва.
И най-добре прави проверка дали има 10 знака въведени за ЕГН, че всичко отива у рЯката ако не са 10!


 

case'3':for (int i = 0; i < countST; i++) {
			if (employees[i].getPol() == 0 && 300 <= employees[i].getpayment() <= 500) {
				cout << "Име: " << employees[i].getName() << endl;
			}
		}
			break;

Това би трябвало да извежда имената на мъжете с дневно заплащане между 300 и 500, но извежда на жените.

преди 23 минути, цър-вул написа:

Защо не е int?

Задаваш въпроси с очевидни отговори. Има ЕГН-та, започващи с 0 и 00. Ако е INT, то тези цифрички ще бъдат хапнати.
За типа INT 0011 и 11 e едно и също. Но за ЕГН това не е едно и също

  • Автор
преди 10 минути, jtaggerx написа:

Задаваш въпроси с очевидни отговори. Има ЕГН-та, започващи с 0 и 00. Ако е INT, то тези цифрички ще бъдат хапнати.
За типа INT 0011 и 11 e едно и също. Но за ЕГН това не е едно и също

Да попитам как да изкарам имената на жените родени през посочен месец?

Трябва да имам променливи за ден, месец и година?

  • Автор

Как трябва да се срявняват трета и четвъртата цифра от егн-то за да мога да изкарам егн-та родени по посочен месец?

месеца е (EGN[2]-'0')%2*10+EGN[3]-'0'

Забележка. Горното важи за стринговете при C, не съм сигурен дали важеше и за начина по който се дефинира типа string при C++

  

преди 2 часа, DeathHour написа:

Това би трябвало да извежда имената на мъжете с дневно заплащане между 300 и 500, но извежда на жените.

По някаква причина въобще не иска да се компилира тази функция с strncpy. 
Казах кой е нормалният човешки вариант. И с него всичко трябва да работи.
Не ми е ясно защо е въобще усложняването с strcpy, слагането на терминиращ знак, че после обръщането с atoi и търсене на остатък.
Имаме 1 знак да вземем, слагаме го в char, от него вадим 48 за кодовата таблица и ето го нашият int.

    char z = EGN[8];
    int h = z - 48;
    if( h%2==0)
    {return 0;}
    else
    {return 1;}

За месеца е малко повече играчка. След 1999 се прибавя 40, а преди 1900 се прибавя 20.

Това бих го направиш с IF, като проверявам годината в кой диапазон е и правя съответните калкулации. 
А, да - можеш да си спестиш IF-а и директно да return-неш стойността, защото тя ще е или 0 или 1.
Да, но само в този случай. 
Та, ако 2-3 са по-големи от 12 и по-големи от 40, то след 2000г, ако са по-големи от 12, но по-малки от 40, то преди 1900, ако са между 1 и 12, то между 1900 и 1999.
Имаме точно 3IF-a и един ELSE за обслужване на изключения/exceptions/
За ден нищо не ти трябва, по месеца намираш диапазона на годината и самия месец, после интерпретираш годината спрямо диапазона. 

преди 2 часа, ined написа:

месеца е (EGN[2]-'0')%2*10+EGN[3]-'0'

Забележка. Горното важи за стринговете при C, не съм сигурен дали важеше и за начина по който се дефинира типа string при C++

Има вариант с различно разписване. Взимат се позиците на EGN за месец, конкатенират се и се използва atoi.
След това отново математическите операции.
Може да се използва и strncpy, който лично аз не харесвам, а може да се използва и substr.

преди 6 часа, DeathHour написа:

    strncpy(b, EGN + 8, 1); b[1] = '\0';
    return atoi(b) % 2;

Сега си видях грешката относно проблема с компилирането. Четох strcpy, а всъщност си написал strncpy. 
strncpy е по парадигмата на C. В C++ имаме substr. Разписването на substr е доста по-четливо като цяло. 

  • Автор
преди 10 часа, jtaggerx написа:

Има вариант с различно разписване. Взимат се позиците на EGN за месец, конкатенират се и се използва atoi.
След това отново математическите операции.
Може да се използва и strncpy, който лично аз не харесвам, а може да се използва и substr.

Сега си видях грешката относно проблема с компилирането. Четох strcpy, а всъщност си написал strncpy. 
strncpy е по парадигмата на C. В C++ имаме substr. Разписването на substr е доста по-четливо като цяло. 

Не ми е ясно как трябва да намеря егн по зададен месец. След като превърна EGN[2] и EGN[3] в int какво следва?

преди 5 часа, DeathHour написа:

Не ми е ясно как трябва да намеря егн по зададен месец. След като превърна EGN[2] и EGN[3] в int какво следва?

Сравняваш го. Ако int-ът е по-малък от 13, то приемаш стойността на int-a директно за месец, а годината ти е между 1900 и 1999. Ако е между 21 и 32, то вадиш от int-a 20, а годината ти е преди 1900. Ако е между 41 и 52, то годината е между 2000 и 2099, тогава от int-a вадиш 40 и получаваш месеца. Месецът е 3 и 4 цифра отляво надясно, а в масива(стринга) ще е 2 и 3, защото броенето в C масивите започва от 0. 

И... ELSE-ът ти ще е за обработване на грешки/изкключения. Ако int-ът е по-малък от 1 или по-голям от 52, ЕГН-то е грешно въведено(неправилно)

Ако трябва да бъда честен, стига да го позволява задачата, бих добавил един int за месец на раждане още при въвеждане в класа, като преобразувам ЕГН-то и бутвам месеца в него int с функция за преобразуване. Защото после в програмния код ще се работи само с int-ове без допълнителни преобразувания.  Същото и за пола. 

И да добавя защо. N*2 int-a за стойност мъж/жена и месец, но конвертиране само веднъж. Баланс между памет и процесорно време. Ако търсиш мъж, после жена, после възраст ще повтаряш конвертирането много повече, съответно повече процесорно време. Но паметта отдавна не е тясно място, не сме в 640К памет и 40-50int-a не са съществени. И програмният код след това ще се опрости. 

  • Автор
преди 1 час, jtaggerx написа:

Сравняваш го. Ако int-ът е по-малък от 13, то приемаш стойността на int-a директно за месец, а годината ти е между 1900 и 1999. Ако е между 21 и 32, то вадиш от int-a 20, а годината ти е преди 1900. Ако е между 41 и 52, то годината е между 2000 и 2099, тогава от int-a вадиш 40 и получаваш месеца. Месецът е 3 и 4 цифра отляво надясно, а в масива(стринга) ще е 2 и 3, защото броенето в C масивите започва от 0. 

И... ELSE-ът ти ще е за обработване на грешки/изкключения. Ако int-ът е по-малък от 1 или по-голям от 52, ЕГН-то е грешно въведено(неправилно)

Ако трябва да бъда честен, стига да го позволява задачата, бих добавил един int за месец на раждане още при въвеждане в класа, като преобразувам ЕГН-то и бутвам месеца в него int с функция за преобразуване. Защото после в програмния код ще се работи само с int-ове без допълнителни преобразувания.  Същото и за пола. 

#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;

class Employee {
private:
	string name;
	string EGN;
	float payment;
	int workingdays;
public:
	void setData();
	void display();
	string getName();
	float getpayment();
	int getWorkingdays();
	bool getPol();
	bool getMonth();
};


string Employee::getName() {
	return name;
}

float Employee::getpayment() {
	return payment;
}

int Employee::getWorkingdays() {
	return workingdays;
}

bool Employee::getMonth() {
	char m = EGN[2];
	char n = EGN[3];
	int month = EGN[2] - '0' + EGN[3] - '0';
	if (month < 13)
	{
		return month;
	} else if (21 < month < 32) 
	{
		int n = month - 20;
		return n;
	} else if (41 < month < 52){
		int t = month - 40;
		return t;
	}
	else
	{
		cout << "Въведено грешно ЕГН: " << endl;
	}
	
 }

// Член - функция за намиране пола
bool Employee::getPol() {
	char pol = EGN[8];
	int gpol = pol - '0';
	return gpol % 2 == 0;
}

void Employee::setData() {
	cin.ignore();
	cout << "Въведи име: "; getline(cin, name);
	cout << "Въведи ЕГН: "; getline(cin, EGN);
	cout << "Въведи дневно заплащане: "; cin >> payment;
	cout << "Въведи брой отработени дни през месеца: "; cin >> workingdays;
}

void Employee::display() {
	cout << "Име: " << name << endl;
	cout << "ЕГН: " << EGN << endl;
	cout << "Дневно заплащане: " << payment << endl;
	cout << "Брой отработени дни: " << workingdays << endl;
}

int main() {
	system("chcp 1251");
	Employee employees[20];
	int countST = 0;
	string month;
	char codeOp;
	do {
		cout << "1 - добавя данни за нов работник " << endl;
		cout << "2 - извежда всички въведени данни " << endl;
		cout << "3 - извежда имената на мъжете с най-малко със заработка между 300 и 500 лв " << endl;
		cout << "4 - създава нов масив с имената и за жените със заработка над 300 лв, родени през посочен месец. " << endl;
		cout << "Посочете операция или 0 за край: " << endl;
		cin >> codeOp;
		switch (codeOp) {
		case'0':
			break;
		case'1': employees[countST++].setData();
			break;
		case'2':cout << "Списък на всички работници: " << endl;
			for (int i = 0; i < countST; i++) {
				employees[i].display();
			}
			break;
		case'3':for (int i = 0; i < countST; i++) {
			if (employees[i].getPol() && 300 <= employees[i].getpayment() <= 500) {
				cout << "Име: " << employees[i].getName() << endl;
				cout << "Заплащане: " << employees[i].getpayment() << endl;
			}
		}
			 break;
		case'4':
			cin.ignore();
			cout << "Имената на жените със заработка над 300лв." << endl;
			for (int i = 0; i < countST; i++) {
				cout << "Задай месец: "; getline(cin, month);
				if (employees[i].getMonth() && employees[i].getpayment() >= 300)
				{
					if (employees[i].getPol() != 0)
					{
						cout << "Име: " << employees[i].getName() << endl;
					}
					
				}
			}
			break;

		default: cout << "Error! " << endl;
			break;
		}
	} while (codeOp != 0);
}

Направих функция  за превръщането на EGN[2] и EGN[3] в int

bool Employee::getMonth() {
	char m = EGN[2];
	char n = EGN[3];
	int month = EGN[2] - '0' + EGN[3] - '0';
	if (month < 13)
	{
		return month;
	} else if (21 < month < 32) 
	{
		int n = month - 20;
		return n;
	} else if (41 < month < 52){
		int t = month - 40;
		return t;
	}
	else
	{
		cout << "Въведено грешно ЕГН: " << endl;
	}
	
 }

В main кода не ми изкарва имената на жените над 300лв заработка по зададен месец. Също в main имам string month.

case'4':
			cin.ignore();
			cout << "Имената на жените със заработка над 300лв." << endl;
			for (int i = 0; i < countST; i++) {
				cout << "Задай месец: "; getline(cin, month);
				if (employees[i].getMonth() && employees[i].getpayment() >= 300)
				{
					if (employees[i].getPol() != 0)
					{
						cout << "Име: " << employees[i].getName() << endl;
					}
					
				}
			}
			break;

 

преди 10 часа, DeathHour написа:

аправих функция  за превръщането на EGN[2] и EGN[3] 

В main кода не ми изкарва имената на жените над 300лв заработка по зададен месец. Също в main имам string month.

В C и C++ не можеш да използваш операторите за сравнение по начина, по който си ги използвал!
Ако напишеш 
5 > x > 1, то компилаторът разбира (5 > x) > 1, оттам това което ти си написал е логически неправилно.. 
Затова и не ти работи функцията, освен в първия случай с едно сравнение.
За да не обяснявам повече, ето линк
Two comparison operators in c++ like python - Stack Overflow


Правилният начин да извършиш проверката за интервала е:
month > 20 && month<33. Когато имаш оператор по-голямо или по-малко, то числото с което сравняваш трябва да е по-голямо от максималната ти стойност.
Можеш да използваш и >= или <= ако държиш да използваш точните стойности.
Та, ако ще сравняваш число да е по-голямо от друго и по-малко от трето, следва да използваш логическият оператор &&, който значи Логическо И
По-долу съм разписал частично функцията ти. Направил съм да връща 90 при грешка. Направи го да връща стойност, която не е възможна при правилно ЕГН и след това проверявай дали върнатата стойност не е такава. Да върнеш нещо с cout не е правилно, защото извеждаш съобщение, но де факто нищо не връщаш и не можеш да използваш за сравнение или други действия. 
Ето разписана примерна функция, смятам че ще се справиш по този пример.

#include <iostream>
#include <string>

using namespace std;
string EGN = "1031111111";
string EGN2 = "1061111111";
int f1(string AR)
{
	string m = AR.substr(2, 2);
	cout<<"Checking the contents of the substring: "<<m<<"\n" ;
	int month = atoi(m.c_str());
	cout<<"Checking the value of the month: "<<month<<"\n" ;
	if (month < 13)
	{
		return month;
	}
	else if ( month>20 && month < 33) 
	{
		int n = month - 20;
		return n;
	} 
	else if (month>40 && month < 53)
	{
		int t = month - 40;
		return t;
	}
	else
	{
		return 90;
	}
}

int main()
{
   int monthcalc=f1(EGN2);
   if(monthcalc==90)
   {
       cout<<"Error! Incorrectly entered EGN! "<<endl;
   }
   else
   {
       cout<<"Calculated from EGN month is: "<<monthcalc<<endl;
       
   }
}

И това лично аз го чета като логически неправилно.

преди 10 часа, DeathHour написа:
	char m = EGN[2];
	char n = EGN[3];
	int month = EGN[2] - '0' + EGN[3] - '0';

Тук ти слагаш в int-а стойностите на EGN[2] + EGN[3]
T.e при 33, ти слагаш 3+3=6 в int-а. Вместо да сложиш 33, за да извършиш правилните калкулации.
Това би било правилно, ако на char[3] сложиш EGN[2] на позиция 0, EGN[3] на позиция 1, като се налага и да терминираш на позиция 2
а след това да използваш atoi, за да го обърнеш в месец в int.

Char към Int чрез вадене на 48 или '0' може да се използва изключително, ако имаш 1 символ. Тогава всъщност чрез ваденето на 0 вадиш от ASCII таблицата изместването на символа за дадена цифра и получаваш самата цифра. 
Има разлика между char и char[2]. Едното 1 ASCII символ(1 символ от ACSII таблицата), а другото е масив от символи! Все е char, ама едното е знак, другото по-скоро е еквивалентно на string в C++

Виждам, че опитваш и имаш желание да се справиш сам, но внимателно гледай за типовете данни, че това са грешки, които лесно се допускат, но за сметка на това може да бъдат много коварни!

Substr съм използвал, защото мога - има го в C++ и защото strncpy не го долюбвам някак. Първи параметър на substr е отместване/брои се от 0 - отляво надясно/, вторият параметър е колко символа от стринга да вземе. Има и други начини за разписване, но това е най-лесно и просто. 
И тия cout-ове в f1 съм ги вкарал само с цел да видиш как работи и как преобразува. С цел дебъг, не са никак нужни. 
А, да - atoi не може да се използва на тип стринг, освен ако не се заобиколи това с .c_str()
basic_string c_str function in C++ STL - GeeksforGeeks

atoi(m.c_str())

Добавете отговор

Можете да публикувате отговор сега и да се регистрирате по-късно. Ако имате регистрация, влезте в профила си за да публикувате от него.

Гост
Публикацията ви съдържа термини, които не допускаме! Моля, редактирайте съдържанието си и премахнете подчертаните думи по-долу. Ако замените букви от думата със звездички или друго, за да заобиколите това предупреждение, профилът ви ще бъде блокиран и наказан!
Напишете отговор в тази тема...

Разглеждащи това в момента 0

  • Няма регистрирани потребители разглеждащи тази страница.

Дарение

  • Подкрепи съществуването на форума - направи дарение
    25%
    Дарени 252.69 EUR от нужните 1,000.00 EUR

Бюлетин

Получавайте известие, когато има важна промяна или новина свързана с форума.

Профил

Навигация

Търсене

Търсене

Конфигуриране на push известия в браузъра

Chrome (Android)
  1. Докоснете иконата на катинар до адресната лента.
  2. Докоснете Разрешения → Известия.
  3. Променете предпочитанията си.
Chrome (Desktop)
  1. Кликнете върху иконата на катинар в адресната лента.
  2. Изберете Настройки на сайта.
  3. Намерете Известия и коригирайте предпочитанията си.