Кадндидат-студентски изпит по информатика на C++

С++ решаваня на задачи по информатика, от кандидатстудентски изпити

Изпит по информатика в ПУ, 13 юли 2010 г., вариант 1

leave a comment »

Решение на С++ на задача 1, дадена на кандидатстудентския изпит в ПУ на 13 юли 2010г.

Условие:

Да се състави компютърна програма за обработване на резултатите от представяне на участниците в телевизионното предаване „България търси талант”. Броят на хората, които са допуснати до последния етап е ограничен до 500. За целта:

  1. За всеки участник да се въведе следната информация:
    • име, презиме и фамилия (един знаков низ, не по-дълъг от 45 знака);
    • 10 цифрен код. Първите 3 цифри са пореден номер на участник. Четвъртата
      цифра от него е код на областта (1 – София, 2 – Пловдив, 3 – Варна, 4 – Бургас, 5 – Русе,
      6 – Благоевград). Третата двойка цифри от кода обозначават деня, четвъртата – месеца, а петата – годината на раждане. Например код 1232030692 означава, че участник с пореден номер 123 е от Пловдив, и е роден на 03 юни 1992 г.
    • вид талант, с който се представя (знаков низ, не по-дълъг от 20 знака);
    • брой точки от вота на зрителите (цяло число);
  2. Да се изведе списък на всички участници, подредени по име в азбучен ред, като за всеки участник се извежда: име, инициал на презимето, фамилия, пореден номер, област, вид талант, брой точки и дата на раждане. Полетата да бъдат разделени със запетая и един интервал. Например:
    Богдана В. Петрова, 123, Пловдив, пеене, 30 000, 03.06.92.
  3. Да се изведе списък на всички участници от София, родени след 1990 г., подреден по азбучен ред на вида талант. Участниците с еднакъв талант да бъдат подредени във низходящ ред на брой точки.
  4. Да се въведе информация за три области, като се контролира броят на участниците да не надхвърля 500. За всяка от тях да се изведат справките от точки 2 и 3, да се намери и изведе на екрана най-големият брой точки на участник и неговото име. Да се пресметне и отпечата средната възраст на участник във всяка от областите.

Решение на C++:

/*
 ============================================================================
 Name        : pu_2010_2.cpp
 Author      : Ivan Stoyanov
 Version     : 1.0
 Copyright   : Stoqnoff
 Description : Решнение на задача 1 на вариант 1 от кандидатстудентски изпит по
               информатика в Пловдивски университет даван на 13 юли 2010 г.
 ============================================================================
 */
#include<iostream>
#include<cstring>
#include<cmath>

using namespace std;

// Константи с кодовете на областите
const unsigned short OBL_SOFIA       = 1;
const unsigned short OBL_PLOVDIV     = 2;
const unsigned short OBL_VARNA       = 3;
const unsigned short OBL_BURGAS      = 4;
const unsigned short OBL_RUSE        = 5;
const unsigned short OBL_BLAGOEVGRAD = 6;

// Константи за формата да датата
const short unsigned int YMD_FORMAT = 1; // yy.mm.dd
const short unsigned int DMY_FORMAT = 2; // dd.mm.yy


// Константи указващи кода на функцията за сравнения
const short unsigned int CMP_BY_NAMES = 1;
const short unsigned int CMP_BY_TYPE_AND_PTS = 2;

// Помощни функции

/* намира поредния номер от кода */
int getNumberFromCode(char code[]);
/* намира областта от кода (може да се ползва и наименование admArea) */
char * getOblastFromCode(char code[], char oblast[]);
/* намира датата на раждане от кода */
char * getBirdDateFromCode(char code[], char date[], int format);
/* Преобразува  имената до такива с инициали и ги връща,
   като резултат от функцията и във променливата returnNames
 */
char * getNameWithInitials(char names[], char returnNames[]);
/* Намира годоините (предполга, че няма участник роден от 1900 до 1920 г.)
   Формата на входните дати е YMD_FORMAT (yy.mm.dd)
*/
int getYears(char date1[], char date2[]);



// Структура описваща участник-талант
struct Talant {
	// Имената на участника
	char names[46];
	// Код на участника
	char code[11];
	// Вид на таланата
	char type[21];
	// Брой точки
	unsigned int points;
};

/* Въвежда данните за талант */
void inputTalant(Talant &talant);
/* Извежда данните за талант */
void displayTalant(Talant talant);
/* Извежда данните за талант */
short int cmpTalantBirdYear(Talant talant, int year);


// Структура описваща списък с таланти
struct TalantsList {
	int count;
	Talant talants[500];
};

/* Инициализира списъкът с таланти */
void initTalantsList(TalantsList &list);
/* Добавя талант към списъка */
void addTalantToTalantsList(TalantsList &list, Talant talant);
/* Въвежда списъка с таланти */
void inputTalantsList(TalantsList &list);
/* Извежда списъка с таланти */
void displayTalantsList(TalantsList list);
/* Намира подсписък от таланти по критериите от т. 3 */
TalantsList searchTalantsSubList(TalantsList list);
/* Сортира списъка по зададена функция за сравнение */
void sortTalantsList(TalantsList &list, unsigned short cmpFunc);
/* Намира и извежда таланта с най-много точки */
void searchAndDisplayMaxPointsTalant(TalantsList &list);
/* Намира средната възраст на талантите */
int getAvgTalantAges(TalantsList &list);

/* Функция за сравняване по име */
int cmp_by_names(Talant talant1,Talant talant2);
/* Функция за сравянване по вид на таланта и брой точки */
int cmp_by_type_and_pts(Talant talant1,Talant talant2);



// Главна функция на програмата
int main()
{
	TalantsList talants;

	for(int i=1; i<=3; i++) {

		std::cout << " Oblast " << i << std::endl;
		std::cout << "--------------------------" << std::endl;

		initTalantsList(talants);

		// Въвеждане на талантите
		inputTalantsList(talants);

		// Сортиране на талантите
		sortTalantsList(talants, CMP_BY_NAMES);
		// Извеждане на списъка на талантите
		std::cout << "All talants: \n";
		displayTalantsList(talants);
		std::cout << std::endl;

		// Търси талантите по задаените критерии от т.3
		TalantsList searchedTalants;
		searchedTalants = searchTalantsSubList(talants);
		sortTalantsList(searchedTalants, CMP_BY_TYPE_AND_PTS);
		std::cout << "Founded talants from Sofia born after 1990: \n";
		displayTalantsList(searchedTalants);
		std::cout << std::endl;

		// Намира и извежда таланта с най-много точки
		searchAndDisplayMaxPointsTalant(talants);
		std::cout << std::endl;

		int avgAges = getAvgTalantAges(talants);
		std::cout << "Average ages: " << avgAges << std::endl;

		std::cout << std::endl;
	}

	return 0;
}



/* намира поредния номер от кода */
int getNumberFromCode(char code[])
{
	return 100*(code[0]-'0') + 10*(code[1]-'0')+code[2]-'0';
}

/* намира областта от кода */
char *getOblastFromCode(char code[], char oblast[])
{
	switch(code[3]-'0') {
		case OBL_SOFIA       :
			strcpy(oblast, "Sofia"); break;
		case OBL_PLOVDIV     :
			strcpy(oblast, "Plovdiv"); break;
		case OBL_VARNA       :
			strcpy(oblast, "Varna"); break;
		case OBL_BURGAS      :
			strcpy(oblast, "Burgas"); break;
		case OBL_RUSE        :
			strcpy(oblast, "Ruse"); break;
		case OBL_BLAGOEVGRAD :
			strcpy(oblast, "Blagoevgrad"); break;
	}

	return oblast;
}

/* намира датата на раждане от кода */
char * getBirdDateFromCode(char code[], char date[], int format)
{
	unsigned short int positions[3] = {4,6,8};
	if( YMD_FORMAT==format ){
		positions[0] = 8;
		positions[1] = 6;
		positions[2] = 4;
	}

	char *p=(char *)date;
	unsigned short int pos;
	for(int i=0; i<3; i++){
		pos = positions[i];
		*p++=code[pos];
		*p++=code[pos+1];
		*p++='.';
	}
	*p='\0';

	return date;
}

/* Преобразува  имената до такива с инициали и ги връща,
   като резултат от функцията и във променливата returnNames
   Предполага се, че имената са въведени коректно - 3 имена с 1 по интервал.
 */
char * getNameWithInitials(char names[], char returnNames[])
{
	strcpy(returnNames, "");
	char * s1 = (char *) names;
	char * s2 = (char *) returnNames;

	// Копира 1-то име (и интервала)
	while( ' ' != *s1 ) {
		if(!*s1) {
			*s2 = '\0';
			return returnNames;
		}
		*s2++=*s1++;
	}

	// Копира интервала
	*s2++=*s1++;

	// Копира инициала на второто име
	*s2++ = *s1++;
	*s2++ = '.';

	// Прескача 2-то име (без интервала)
	while( ' ' != *++s1 ) {
		if(!*s1) {
			*s2 = '\0';
			return returnNames;
		}
	}

	// Копира интервала и 3-то име
	while(*s1) *s2++=*s1++;
	*s2 = '\0';

	return returnNames;
}

/* Намира годоините (предполга, че няма участник роден от 1900 до 1920 г.)
   Формата на входните дати е YMD_FORMAT (yy.mm.dd)
*/
int getYears(char date1[], char date2[])
{
	int y1, y2, age;
	y1 = 10*(date1[0]-'0') + date1[1]-'0';
	y2 = 10*(date2[0]-'0') + date2[1]-'0';

	if(y1<20) y1+=2000;
	else y1+=1900;

	if(y2<20) y2+=2000;
	else y2+=1900;

	age = y2-y1;

	// Декларира 2 низови указателя
	char *p1, *p2;
	p1 = (char *)date1 + 3; // началото на низа се насочва към месеца
	p2 = (char *)date2 + 3; // началото на низа се насочва към месеца

	if( strcmp(p1,p2) > 0 ) {
		age--;
	}
	else {
		p1+=3; // началото на низа се насочва към деня
		p2+=3; // началото на низа се насочва към деня
		if(strcmp(p1,p2) > 0) age--;
	}

	return age;
}



/* Въвежда данните за талант */
void inputTalant(Talant &talant)
{
	std::cout << "Input names: ";
	std::cin.getline(talant.names, 46);

	std::cout << "Input code: ";
	std::cin.getline(talant.code, 11);

	std::cout << "Input type: ";
	std::cin.getline(talant.type, 21);

	std::cout << "Input points: ";
	std::cin >> talant.points;
	std::cin.get();
}

/* Извежда данните за талант */
void displayTalant(Talant talant)
{
	char buff[255];
	std::cout << getNameWithInitials(talant.names, buff) << ", ";
	std::cout << getNumberFromCode(talant.code)          << ", ";
	std::cout << getOblastFromCode(talant.code, buff)    << ", ";
	std::cout << talant.type					   		 << ", ";
	std::cout << talant.points					   		 << ", ";
	std::cout << getBirdDateFromCode(talant.code, buff, DMY_FORMAT);
	std::cout << std::endl;
}

/* Сравнява рожденната дата на талант с дадена година */
short int cmpTalantBirdYear(Talant talant, int year=1990)
{
	int talantYear;
	talantYear = 10*(talant.code[8]-'0') + talant.code[9]-'0';

	if(talantYear<20) talantYear+=2000;
	else talantYear+=1900;

	if(talantYear==year) return 0;
	else if( talantYear<year ) return -1;
	return 1;
}


/* Инициализира списъкът с таланти */
void initTalantsList(TalantsList &list)
{
	list.count=0;
}

/* Добавя талант към списъка */
void addTalantToTalantsList(TalantsList &list, Talant talant)
{
	list.talants[list.count++]=talant;
}

/* Въвежда списъка с таланти */
void inputTalantsList(TalantsList &list)
{
	int cntTalants;

	do{
		std::cout << "Input talants count: ";
		std::cin >> cntTalants;

		if( cntTalants>0 && cntTalants <=500) break;

		std::cout << "Talants count muss be in [1, 500]!" << std::endl;
	}
	while(true);

	std::cin.get();

	Talant talant;
	for(int i=0; i<cntTalants; i++) {

		std::cout << "Input talant " << (i+1) << std::endl;
		inputTalant(talant);
		addTalantToTalantsList(list, talant);
		std::cout << std::endl;
	}
}

/* Извежда списъка с таланти */
void displayTalantsList(TalantsList list)
{
	for(int i=0; i<list.count; i++) {
		displayTalant(list.talants[i]);
	}
	std::cout << std::endl;
}

/* Намира подсписък от таланти по критериите от т. 3 */
TalantsList searchTalantsSubList(TalantsList list)
{
	TalantsList searchList;
	initTalantsList(searchList);

	for(int i=0; i<list.count; i++) {
		if( cmpTalantBirdYear(list.talants[i], 1990) > 0 && OBL_SOFIA == list.talants[i].code[3]){
			addTalantToTalantsList(searchList, list.talants[i]);
		}
	}

	return searchList;
}

/* Сортира списъка по зададена функция за сравнение */
void sortTalantsList(TalantsList &list, unsigned short cmpFunc=CMP_BY_NAMES)
{
    Talant tmpTalant;
    int pos, cmp;
    for(int i=0; i<list.count-1; i++) {
        pos = i;
        for(int j=i+1; j<list.count; j++) {

        	switch(cmpFunc){
        		case CMP_BY_NAMES :
        			cmp = cmp_by_names(list.talants[j], list.talants[pos]);
        			break;
        		case CMP_BY_TYPE_AND_PTS :
        			cmp = cmp_by_type_and_pts(list.talants[j], list.talants[pos]);
        			break;
        		default :
        			cmp=0;
        			break;
        	}

           	if( cmp < 0 ){ 	pos = j; }
        }

        if( pos != i ) {
            tmpTalant = list.talants[i];
            list.talants[i] = list.talants[pos];
            list.talants[pos] = tmpTalant;
        }
    }
}

/* Намира и извежда таланта с най-много точки */
void searchAndDisplayMaxPointsTalant(TalantsList &list)
{
	if( 0 == list.count ) return;

	int maxIndex=0, maxPoints=0;
	for(int i=0; i<list.count; i++){
		if( list.talants[i].points > maxPoints ){
			maxPoints = list.talants[i].points;
			maxIndex  = i;
		}
	}

	std::cout << "Maximum points: " << std::endl;
	std::cout << list.talants[maxIndex].points << ", "
			  << list.talants[maxIndex].names << std::endl;
}

/* Намира средната възраст на талантите */
int getAvgTalantAges(TalantsList &list)
{
	long unsigned int sumAges=0, cntAges=0;
	char buff[20];

	for(int i=0; i<list.count; i++) {

		// Намира рожденната дата и я запомня в буфера
		getBirdDateFromCode(list.talants[i].code, buff, YMD_FORMAT);

		if( cmpTalantBirdYear(list.talants[i], 1990) > 0 ){
			sumAges+= getYears(buff, "10.07.13");
			cntAges++;
		}
	}

	// Намира средните години, като прави закръгляне
	double dblAvg = (double)sumAges/cntAges;
	dblAvg*=10;
	int intAvg = floor(dblAvg);
	if( intAvg%10 >= 5 ) intAvg+=10;
	return intAvg/10;
}

/* Функция за сравняване по име */
int cmp_by_names(Talant talant1,Talant talant2)
{
	return strcmp(talant1.names, talant2.names);
}

/* Функция за сравянване по вид на таланта и брой точки */
int cmp_by_type_and_pts(Talant talant1,Talant talant2)
{
	int cmp;
	cmp = strcmp(talant1.type, talant2.type);
	if( 0 == cmp ){
		if( talant1.points < talant2.points ) return -1;
		else if( talant1.points > talant2.points ) return 1;
		else return 0;
	}

	return cmp;
}

Written by Stoyanoff

24/10/2012 в 16:49

Вашият коментар

Попълнете полетата по-долу или кликнете върху икона, за да влезете:

WordPress.com лого

В момента коментирате, използвайки вашия профил WordPress.com. Излизане /  Промяна )

Google photo

В момента коментирате, използвайки вашия профил Google. Излизане /  Промяна )

Twitter picture

В момента коментирате, използвайки вашия профил Twitter. Излизане /  Промяна )

Facebook photo

В момента коментирате, използвайки вашия профил Facebook. Излизане /  Промяна )

Connecting to %s

%d блогъра харесват това: