IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Luboš Horký:10.6.2020 9:44

Ahoj, pracuji na takové zkouškové databázi osob. Kde mám vytvořen hlavní objekt COsoba a pod ním další objekty např CUcitel, CCivil atd... Kde pro začátek mám v pod objektech uložené jen 1 max 2 data na víc například katedru, bydliště.

Pro zatím jsem dokázal v databázi vyhledávat podle zadaného jména, jen jednoduchým přetížením operátoru.

Teď se už nějaký den snažím o přetížení operátoru < popřípadě >, myslím si že zde by neměl bát kámen úrazu. Ale snažím se o porovnání jmen a následné uspořádání objektů podle jmen.

Zkoušel jsem bublesort, kde jsem asi špatně používal operátory, protože nefungoval jak bych si představoval.

Také jsem našel funkci sort() v knihovně "algorithm", ale po vymyšlení kódu se této funkci něco nelíbí.

Přikládám kód, kde jsem zkoušel setřídit osoby.

Zkusil jsem: Hlavní kód, není zde vše, maličkosti jsem vynechal a nekopíroval sem celý kód :-) :

#include <iostream>
#include<string>
#include"COsoba.h"
#include "CCivil.h"
#include "CUcitel.h"
#include<algorithm>
#include<vector>

COsoba* osoby[50];      //kvuli funkci prohozeni je definován nad main()

void prohod(int index1, int index2) {
        COsoba* pom = osoby[index1];
        osoby[index1] = osoby[index2];
        osoby[index2] = pom;
}

bool porovnej(COsoba a, COsoba b)       //fuknce pro sort
{
        return a < b;
}

int main()
{
int x = 1;
        printf("Zadej pocet osob : ");
        scanf_s("%d", &x);
        for (int i = 0; i < x; i++)
        {
        int x = Menu(); //funkci na vyvolani menu neprikladam, obycejny "case"
        //zde funkcni kod...
        }

//kod na vyhledani podle jmena
string jmeno;
        printf("Zadej jemno ktere chces najit: ");
        cin >> jmeno; cout << endl;
        printf("pocet osob: %d\n", pocet);
        for (int i = 0; i < x; i++)
        {

                if (*osoby[i] == jmeno) {

                        printf("\nNALEZENO:\n");
                        osoby[i]->VypisData();
                }
        }

vector<COsoba> mujVEKTOR(osoby, osoby + x);
        sort(mujVEKTOR.begin(), mujVEKTOR.end(), porovnej);
        printf("Setrideno: \n");
        for (vector<COsoba>::iterator it = mujVEKTOR.begin(); it != mujVEKTOR.end(); ++it) {
                cout << ' '; *it;
        }
        cout << '\n';


}

kód pro objekt
COsoba.h

#pragma once
#include <string>
#include<iostream>

using namespace std;

class COsoba
{
protected:
        char m_Jmeno[50];
        int m_Vek;

public:
        virtual void ZadejData();
        virtual void VypisData();
        bool operator==(COsoba osoba);
        bool operator==(string jmeno);
        bool operator<(const COsoba &osoba) const;
        //bool operator<(COsoba a);
        COsoba operator+(int cislo);
        //virtual void serad(COsoba* osoba, int n);
        COsoba(void);
        ~COsoba(void);
};

kód pro (taky ne vše, je tam více operátorů, zbytečně kopírovat sem)
COsoba.cpp

void COsoba::ZadejData()
{
        printf("Zadej jmeno: ");
        scanf_s("%s", m_Jmeno, 50);
        //strcpy_s(m_Jmeno, "Pavel");
        printf("Zadej vek: ");
        //m_Vek = 12;
        scanf_s("%d", &m_Vek);
}

void COsoba::VypisData()
{
        printf("Jmeno: %s Vek: %d ", m_Jmeno, m_Vek);
}

bool COsoba::operator<(const COsoba& osoba) const
{
        if (m_Jmeno < osoba.m_Jmeno) return (true);
        else return false;

}

a ještě například pod objekt učitel:
CUcitel.h

#pragma once
#include "COsoba.h"


class CUcitel :
        public COsoba
{
protected:
        char m_Katedra[100];
public:
        void SetKatedra();
        void VypisData();
        void ZadejData();
};

a CUcitel.pp

#include "CUcitel.h"

#include <iostream>

void CUcitel::SetKatedra()
{
        printf("Zadej Katedru: ");
        scanf_s("%s", m_Katedra, 100);
}

void CUcitel::VypisData()
{
        COsoba::VypisData();
        printf("Katedra : %s\n", m_Katedra);
}

void CUcitel::ZadejData()
{
        COsoba::ZadejData();
        SetKatedra();

}

ještě další způsob, který jsem zkoušel : "bubblesort"

void bubbleSort(const int size) {
        for (int i = 0; i < (size - 1); i++) {
                for (int j = (i+1); j < size; j++) {
                        if (*osoby[j] < *osoby[i]) {
                                prohod(i, j);
                        }

                }
        }
}

void prohod(int index1, int index2) {
        COsoba* pom = osoby[index1];
        osoby[index1] = osoby[index2];
        osoby[index2] = pom;
}

int main()
{

bubbleSort(x);  //x je pocet osob

for (int i = 0; i < x; i++)
        {
        osoby[i]->VypisData();
        }
}

Chci docílit: Teď se snažím o pod úkol setřídění podle jmen v této "databázi" a následný výpis setříděné databáze.

Za jakýkoliv popostrčení, jak dál bych byl rád, předem děkuji. :)

Odpovědět
10.6.2020 9:44
Poslední co umírá je naděje.
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:10.6.2020 14:08

Pokud resit databazi, tak se k tomu pouzivaji programy na spravu databaze a tabulek v ni. Sql prikazem obvykle ziskavas uz tabulku pro vypis.
Pro cpp ti moc neporadim, ale urcite bys nasel priklady googlem na sortovani. V JS to funguje tak, ze sortovaci funkci muzes predat funkci pro porovnani. Ukazka:

list = array();
list.sort(); // seradi

list = array();
list[0] = array();
list[0][0] = 5;
// a ted bys byl se sortem uplne v haji, ale...
function cmp(a,b) {return a[0]<=b[0] ? 0 : 1;} // if (radek_a[sloupec_0]<=radek_b[sloupec_0]
list.sort(cmp);

list = array();
list[0] = 'Jenda';
// a ted bys byl se sortem uplne v haji, opet, protoze stringy neporovnava jako stringy, ale jako cisla ...
function cmp(a,b) {return a.length<=b.length ? 0 : (a<=b ? 0 : 1);} // porovna delky stringu a pak porovnava stringy
list.sort(cmp);

list = array();
list[0] = 'Jeníček';
// a dalsi problem, diakritika, to bys musel upravit porovnavaci funkci i o ni, to se mi resit ted nechce

list = array();
list[0] = object();
list[0]['name'] = 'Jenik';
function cmp(a,b) {return a['name']<=b['name'] ? 0 : 1;} // if (radek_a[sloupec_0]<=radek_b[sloupec_0]
list.sort();

Takze, pokud to jde, pouzil bych nativni sort funkci.
Pokud to nejde, tak bych pouzil list-merge sort. Nebo quick sort.
A pokud mas do 100 polozek, tak by byla pouzitelna insert to middle. Ten funguje tak, ze serazene pole rohledavas od stredu, stred pulky, stred ctvrtky...


1.
Kdyz porovnavas jmena, stringy, musis porovnavat delky retezcu, pak hodnoty.
xxx < AAAAAA = lidsky, chces obvykle kratke nahore
AAAAAA < xxx = ale u normalniho sortu rozhodne prvni porovnani znaku a to je x > A
A u hodnot nastava krize v pripade diakritiky. Hodnoty se porovnavaji znak po znaku. Ascii kody znaku jsou v poradi cisla (48), velka pismena (65), mala pismena (97), diakritika (128). Takze pro stringy musis pouzit vlastni tabulku poradi znaku.

Cili, tvuj sort bych predelal nejak takto. (ale pac cecko neumim, tak to musis dotahnout sam)

void sortCompare(*a, *b)
{
return a<=b ? false : true;
}

void sortSwap(*a, *b)
{
tmp = a;
a = b;
b = tmp;
}

void bubbleSort(*array, *cmp, start, end) {
// cili, abys mohl zadavat, kterou cast chces seradit, start, end
// abys to mohl pouzit i pro jinou array
// a abys tam mohl zadavat porovnavaci funkci
        for (int i = start; i < (end - 1); i++) {
                for (int j = (i+1); j < end; j++) {
                        if (cmp(array[i], array[j]) {
                                sortSwap(array[i], array[j]);
                        }

                }
        }
}

2. Data musis drzet dal od funkci, jinak se v tom brzo ztratis a tez zbytecne zatezujes pamet duplikovanim funkci.

class classUcitel :
        public a, b, c;
        public function x() {}
        public function y() {}
};
osoby = array();
osoby[0] = new classUcitel() // ted ti to zabere v pameti nejen a,b,c, ale i x a y

class struUcitel :
        public a, b, c;
};
osoby = array();
osoby[0] = new struUcitel()

// ty funkce preci muzes volat tak, ze jim predas ucitele

class fceUcitel :
{
        function SetKatedra(ucitel, katedra);
        function Vypis(ucitel);
        function Zadej(ucitel, data);
        function VypisUcitele(osoby_list)
{
str = '';
for ( i=0; i<count(osoby_list); i++)
  {str+= "\n" + VypisData(osoby_list[i]);}
print str;
}
};

// a jinak bych to vytvarel nejakym takovym zpusobem
list = array();
list.add(new struUcitel ('jmeno', 'prijmeni'));
list.add(new struUcitel ('jmeno', 'prijmeni'));
list.add(new struUcitel ('jmeno', 'prijmeni'));
Editováno 10.6.2020 14:09
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
10.6.2020 14:08
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Luboš Horký
DarkCoder:10.6.2020 14:59

V C máš implementovanou funkci strcmp() pro lexikografické porovnání dvou řetězců, hlavičkový soubor string.h. Dále máš zde implementovanou funkci qsort() pro třídění pole pomocí algoritmu QuickSort, hlavičkový soubor stdlib.h.

Vytvoř si dynamicky alokované pole celých čísel o velikosti počtu položek databáze naplněné hodnotami představující pozici daného záznamu databáze. Porovnávej klíče databáze a třiď dynamicky alokované pole. Po setřídění dynamicky alokované pole obsahuje hodnoty indexů databáze v pořadí jakém by se nacházely abecedně setříděné řetězce. Pro výpis setříděné databáze procházej postupně dynamicky alokované pole a vypisuj záznam na indexu databáze odpovídající hodnotě v dynamicky alokovaném poli.

Nahoru Odpovědět
10.6.2020 14:59
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na Peter Mlich
Luboš Horký:10.6.2020 16:23

Díky za objasnění sort funkce. Máš pravdu, že při porovnání stringů převádí string na čísla, to není v mém případě úplně vhodné. Takže jsem si vytvořil vlastní funkci na seřazení sice jsem vynechal tvoji "sortCompare" funkci ale přetypoval jsem si funkci pro operator < , kde teď už místo sortu jsem použil porovnání délky jmen a následně jejich písmen zvlášť, jak jsi radil.

Zdá se že podle toho vše funguje.
Občas se porovnání ještě sekne, ale myslím že to bude nějakou maličkostí v kódu.

Jinak díky za poukázání na "insert to middle", o tom jsem zatím neslyšel a rozhodně to zní využitelně!

Jinak, kdyby někdo řešil stejný problém co já dám sem výsledný kód pro to uspořádání objektů ;)
Zde byl kámen úrazu, porovnával jsem špatně řetězce, takhle by to mělo být správně:

bool COsoba::operator<(const COsoba& osoba) const
{
        int delka;
        if (strlen(m_Jmeno) <= strlen(osoba.m_Jmeno))
                delka = strlen(m_Jmeno);
        else
        {
                delka = strlen(osoba.m_Jmeno);
        }
        //urceni kratsiho retezce

        if(m_Jmeno[0] < osoba.m_Jmeno[0]){ return true; }

        if (m_Jmeno[0] > osoba.m_Jmeno[0])
        {
                return false;
        }
        else
        {
                if(m_Jmeno[0]==osoba.m_Jmeno[0])
                for (int k = 0; k < delka; k++)
                        if (m_Jmeno[k] < osoba.m_Jmeno[k])
                        {
                        return true;
                        }
        }

}

a v mainu se použije pouze obyčejný bubble:

for (int i = 0; i < x; i++)
        {
                for (int k = 0; k <x ; k++)
                {
                        if (*osoby[i]<*osoby[k])
                        {
                                //prohod(i, k); --> funkce prohod nefunguje spravne !
                                COsoba* temp;
                                temp = osoby[i];
                                osoby[i] = osoby[k];
                                osoby[k] = temp;
                        }
                }
        }

Ještě jednou díky ! :)

Nahoru Odpovědět
10.6.2020 16:23
Poslední co umírá je naděje.
Avatar
Odpovídá na DarkCoder
Luboš Horký:10.6.2020 16:36

Díky, funkci strcmp() je dobré znát, alespoň si pro příště nemusím tuhle funkci sám tvořit :D

A qsort() taky ulehčí mnoho práce :D

Jen nevím jestli není zbytečné tolik knihoven, ale samozřejmě na to se asi nehraje :)

Nahoru Odpovědět
10.6.2020 16:36
Poslední co umírá je naděje.
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Luboš Horký
DarkCoder:10.6.2020 17:00

Jo, obojí celkem ulehčí dost práce. Ale tak aspoň sis trochu procvičil algoritmizaci, to se vždy hodí. :-D Obě funkce jsou součástí standartních knihoven jazyka C, tak proč toho nevyužít. Jinak překladače jsou optimalizované tak, že vkládají do kódu pouze funkce použité v programu. Nejsem příznivcem toho aby mé programy obsahovaly seznamy includovaných hlavičkových souborů, ale zde to má smysl. Ještě by se Ti mohla hodit funkce bsearch() která provádí binární vyhledávání v setříděném poli, nachází se podobně jako funkce qsort() v hlavičkovém souboru stdlib.h.

Nahoru Odpovědět
10.6.2020 17:00
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 6 zpráv z 6.