LINUXSOFT.cz Přeskoč levou lištu

ARCHIV



   

> Diskuze: Poradna System na triedenie udajov v C

System na triedenie udajov v C
(link)
11.11.2010 17:22
presto

Dobry den,

Prosim Vas potreboval by som poradit ako zrealizovat system na triedenie udajov, ktory musi obsahovat:
1. Načítanie údajov zo súboru do dynamického poľa v cykle
2. Možnosť zmeny existujúcej položky poľa v tvare štruktúry resp. jej členov
3. Možnosť triedenia štruktúr podľa konkrétnej položky
4. Možnosť vyhľadávania podľa konkrétnej položky
5. Uloženie zmenených dát do súboru

Nacitat udaje do dnamickeho pola zo suboru v cykle viem, taksito ulozit zmenene data do suboru, moznosti 2,3,4 nie su mi az tak jasne. Bol by niekto ochotny mi pomoct? Dakujem.
Zatial mam:

[code]
#include <stdio.h>
#include <stdlib.h>

int main()
{

int n, i;
FILE *f1,*f2;
float *pole_hodnot;

pole_hodnot = (float*)malloc(n * sizeof(float));
if(pole_hodnot == NULL)
{
printf("Nedostatok pamatoveho priestoru.\n");
return -1;
}
if ((f1 = fopen("file1.txt", "r"))!= NULL
{

for(i = 0; i < n; i++)
{
fscanf(f1, "%f", &pole_hodnot[i]);
}


return 0;
}
[/code]

PS: mam predstavu co su to struktury typedef struct {polozky}; , ale neviem ako to presne realizovat a bol by som rad, ak by mi to niekto skuseny predviedol priamo na tomto priklade.

EDIT:
viem, ze napr.
[code]typedef struct priklad{
int cislo;
char znak;
} Spriklad; [/code]

vytvori strukturu s dvomi polozkami cislom a slovom o 9 znakoch a pouzije sa:
[code]Spriklad premenna;
premenna.cislo = 10;
premenna.znak = 'a';[/code]

Ale potrebujem jednoducho nejaky odrazovy bod, najlepsie cely priklad nejakeho navrhnuteho vlastneho systemu na triedenie udajov, ktory musi obsahovat to co je popisane v hornych bodoch. Takym stylom ako to je napr v Ucebnici jazyka C od Herouta, no tam som presiel celu kapitolu, ale stale neviem ako konkretne zrealizovat tie body, ktore som popisoval vyssie...Uz som uplne zmeteny...

Re: System na triedenie udajov v C
(link)
25.11.2010 22:33
Vladimir Mindl
Bydliště: Praha

Dobrý den,

myslím, že bych Vám mohl trochu pomoci. Chtěl jsem si tu Vaši ulohu jen tak cvičně vyřešit. Kdyz se podivam na Vas kod, vidim, ze jste si zaalokoval pole hodnot typu float a do nej nacitate zrejme nejake hodnoty, ktere by mely byt ve vasem vstupnim souboru. Ale tam by tedy musely byt same hodnoty typu float. Zalezi samozrejme na dohode programu s usporadanim vstupniho souboru, takze musite mit nejdrive jasno v tom, jaka data chcete ze souboru nacitat a take na tom, jak tyto data budete mit ulozena v souboru a posleze v programu. Jestlize bude mit Vas vstupni soubor ulozena data typu float na jednom radku napr. takto:

1.radek souboru: 1.25 4.48 9.56 11.48 16.53
2.radek souboru: 18.48 19.56 22.48 65.73

bude nejlepsi cist data zpusobem, pro jaky jste si vytvoril svuj kod a formatem fscanf, ktery prebira vzdy jednu hodnotu typu float.

- Ale vy se zminujete, ze chcete cist data do struktury ktera obsahuje cislo a znak a pokud spravne predpokladam budete chtit tech struktur naplnit vice, nejlepe pole techto struktur. V tom pripade ale nemuzete alokovat pole hodnot typu float ale pole struktur typu cislo + znak. Z Vaseho vykladu vyplyva, ze jste si zrejme neprecetl jeste ucebnici jazyka C druhy dil od p. Herouta. Rozhodne Vas timto nekritizuji, protoze ja osobne mel po precteni prvniho dilu pocit, ze jsem super programator a ze vse ostatni uz cist nemusim ;o). Takze v UJC 2 urcite najdete nejen zpusob, jak cist data do pole struktur ale i funkce pro trideni a vyhledavani. Take pokud v teto chvili nemate UJC 2 na dosah, najdete vyklad
v serialu napr. na www.builder.cz ale samozrejme i zde a to v serialu pana Nemce zde na Linuxsoftu. Urcite si prectete kapitoly 22 a 27.

- Take z Vaseho dotazu vyplyva, ze zrejme neumite moc vyhledavat na internetu. Vetsina veci je na netu v Aj (nektere bohuzel jen v japonstine:). Ale i kdyz zadate do Googlu napr. neco jako 'Cteni souboru + C' nebo 'Cteni dat + struktury + C', dostanete i par ceskych odkazu. Pro programatorskou praxi je vsak bohuzel anglictina (aspon na urovni cteni textu) nevyhnutelna. Takze kdyz zadate do Googlu napr. 'How to read file in C' nebo 'Fill array of structures from a file + C' nebo 'sorting structs + C', budete mit spoustu vzoroveho kodu po ruce. Navic trideni a vyhledavani podle konkretni polozky struktury je mozne snadno realizovat pomoci f-ci qsort (quick sort) a (bsearch), coz jsou take ucebnicove priklady (Zadate do googlu qsort nebo bsearch).

- Ale abych se vratil k Vasemu konkretnimu prikladu, vyresil jsem si nejprve sam pro sebe zpusob cteni pomoci fscanf. Je i mne trochu nejasne zadavani formatovaciho retezce pro fscanf ale pro konkretni zpusoby se da najit na netu mnoho moznosti. Pouzil jsem v zakladu tento zpusob cteni a ukladani dat ze souboru pomoci fscanf nalezeny na www.linuxforums.org

int main(void)
{
FILE *myfile_in;
int int_result;
int myint;

char label [80];


int_result=fscanf(stdin,"%s %d",label,&myint);

myfile_in = fopen("zamestnanci_in.txt","r");

printf("fscanf() has read %d items\n",int_result);
printf("label is \"%s\"\n",label);
printf("myint is %d\n",myint);

fclose(myfile_in);

return 0;

} /* main() */

- Pokud budete nacitat vice polozek z nejakeho souboru, musite mit jasno v tom, jak budou v souboru tyto hodnoty ulozeny a tomu prizpusobit formatovaci retezec cteni z 'fscanf'. Takze napr. pro cteni ze souboru zamestnanci_in.txt, ktery bude vypadat takto (s polozkami jmeno, plat oddelenymi tabelatorem):

fred 5485
jano 6978
miro 7492
andy 30000
rony 35000
mara 11925
vlado 10486
valda 19484
janka 16456
hana 40000

- bude fungovat nize uvedeny kod. Zde uz prikladam hotovy programek i s tridicimi a vyhledavacimi f-cemi, ktery je ale pokud mi to pan Nemec - autor serialu o C/C++ zde na linuxsoftu odpusti - sloucenim a malym prizpusobenim kodu jeho dvou kapitol (snad krome cteni z file):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Velikost pole */
#define POCET 10

typedef struct {
unsigned plat;
char jmeno[64];
} Zamestnanec;

/* Porovnávací funkce, parametry jsou ukazatele na ukazatele na
porovnávané typy Zamestnanec. */
int cmp(const void *a, const void *b) {

/* Parametry musíme nejprve přetypovat z void * na Zamestnanec **, potom
dereferencovat na Zamestnanec *, operátorem -> získat mzdu a teprve
potom porovnat. */
if ( (*((Zamestnanec **) a))->plat < /* jmeno */
(*((Zamestnanec **) b))->plat ) { /* plat */
/* První prvek je menší. */
return -1;
}

if ( (*((Zamestnanec **) a))->plat >
(*((Zamestnanec **) b))->plat ) {
/* První prvek je větší. */
return 1;
}

/* Ani menší ani větší. V úplném uspořádání zbývá jedině rovnost. */
return 0;
}

/* trideni polozek podle jmena - lexikograficky */

int cmp1(const void *a, const void *b) {

Zamestnanec *ia = (Zamestnanec *)a;
Zamestnanec *ib = (Zamestnanec *)b;

if (strcmp(ia->jmeno, ib->jmeno) < 0) {
return -1;
}

if (strcmp(ia->jmeno, ib->jmeno) > 0) {
return 1;
}

if (strcmp(ia->jmeno, ib->jmeno) == 0) {
return 0;
}
}

int main(void)
{
FILE *myfile_in;
FILE *myfile_out;

Zamestnanec * pole[POCET];

int int_result;
int myint;
int i;

char label [80];
myfile_in = fopen("zamestnanci_in.txt","r");
myfile_out = fopen("zamestnanci_out.txt", "w");

for (i = 0; i < POCET; i++) {

int_result=fscanf(myfile_in,"%s %d\n",label,&myint);

printf("fscanf() has read %d items\n",int_result);
printf("label is \"%s\"\n",label);
printf("myint is %d\n",myint);

Zamestnanec *pz;

pz = (Zamestnanec *) malloc(sizeof(Zamestnanec));

if (!pz) {
/* Ve skutečných programech takhle opatrný nejsem, ale tohle je
výuka... */
int j;
fputs("Málo paměti!\n", stderr);
for (j = 0; j < i; j++) {
free(pole[j]);
}
return 1;
}
pz->plat = myint;
// strncpy(pz->jmeno, label, 1);
sprintf(pz->jmeno, "%s", label);
pole[i] = pz;
}

/* Výpis nesetříděného pole */
puts("\nNesetříděno:");
for (i = 0; i < POCET; i++) {
printf("jméno: %s, plat:%u\n", pole[i]->jmeno, pole[i]->plat);
}

/* Vlastní třídění */
qsort((void *) pole, POCET, sizeof(Zamestnanec *), cmp); /* trideni podle platu */

/* Výpis setříděného pole */
puts("\n\nSetříděno podle platu:");
for (i = 0; i < POCET; i++) {
printf("jméno: %s, plat:%u\n", pole[i]->jmeno, pole[i]->plat);
}

/* zapis setrideneho pole do vystupniho file */
fprintf(myfile_out, "\nSetříděno podle platu:\n\n");
for (i = 0; i < POCET; i++) {
fprintf(myfile_out, "jméno: %s, plat:%u\n", pole[i]->jmeno, pole[i]->plat);
}

Zamestnanec z, *pz, **ppz;
z.plat = 30000;
pz = &z;

/*
Návratová hodnota bsearch je ukazatel na prvek pole tedy ukazatel
na ukazatel na Zamestnanec. Musíme ji přetypovat z void *
na Zamestnanec **, ověřit, zda není NULL, dereferencí získat jednoduchý
ukazatel na Zamestnanec a teprve potom operátorem -> přistupovat
k položkám. Rovněž pozor na první vstupní parametr. Nejde zadat &z,
tedy Zamestnanec *. Je třeba stejný typ, jako je ukzatel na prvek pole,
tedy Zamestnanec **.

Práce s ukazateli dělá občas problémy i zkušeným programátorům v C.
*/
ppz = (Zamestnanec **) bsearch(&pz, pole, POCET, sizeof(Zamestnanec *),
cmp);
if (!ppz) {
printf("\nPlat přesně %u nemá nikdo.\n", z.plat);
fprintf(myfile_out, "\nPlat přesně %u nemá nikdo.\n", z.plat);
} else {
printf("\nPlat přesně %u má %s a možná ještě někdo další.\n", z.plat,
(*ppz)->jmeno);
fprintf(myfile_out, "\nPlat přesně %u má %s a možná ještě někdo další.\n", z.plat,
(*ppz)->jmeno);
}

qsort((void *) pole, POCET, sizeof(Zamestnanec *), cmp1); /* trideni podle jmena */

puts("\n\nSetříděno podle jmena:");
for (i = 0; i < POCET; i++) {
printf("jméno: %s, plat:%u\n", pole[i]->jmeno, pole[i]->plat);
}

fprintf(myfile_out, "\nSetříděno podle jmena:\n\n");
for (i = 0; i < POCET; i++) {
fprintf(myfile_out, "jméno: %s, plat:%u\n", pole[i]->jmeno, pole[i]->plat);
}

/* Dealokace */
for (i = 0; i < POCET; i++) {
free(pole[i]);
}
/* Odřádkování na závěr */
puts("");

fclose(myfile_in);
fclose(myfile_out);

return 0;

}

- Vystup:

fscanf() has read 2 items
label is "fred"
myint is 5485
fscanf() has read 2 items
label is "jano"
myint is 6978
fscanf() has read 2 items
label is "miro"
myint is 7492
fscanf() has read 2 items
label is "andy"
myint is 30000
fscanf() has read 2 items
label is "rony"
myint is 35000
fscanf() has read 2 items
label is "mara"
myint is 11925
fscanf() has read 2 items
label is "vlado"
myint is 10486
fscanf() has read 2 items
label is "valda"
myint is 19484
fscanf() has read 2 items
label is "janka"
myint is 16456
fscanf() has read 2 items
label is "hana"
myint is 40000

Nesetříděno:
jméno: fred, plat:5485
jméno: jano, plat:6978
jméno: miro, plat:7492
jméno: andy, plat:30000
jméno: rony, plat:35000
jméno: mara, plat:11925
jméno: vlado, plat:10486
jméno: valda, plat:19484
jméno: janka, plat:16456
jméno: hana, plat:40000


Setříděno podle platu:
jméno: fred, plat:5485
jméno: jano, plat:6978
jméno: miro, plat:7492
jméno: vlado, plat:10486
jméno: mara, plat:11925
jméno: janka, plat:16456
jméno: valda, plat:19484
jméno: andy, plat:30000
jméno: rony, plat:35000
jméno: hana, plat:40000

Plat přesně 30000 má andy a možná ještě někdo další.


Setříděno podle jmena:
jméno: fred, plat:5485
jméno: miro, plat:7492
jméno: jano, plat:6978
jméno: mara, plat:11925
jméno: vlado, plat:10486
jméno: valda, plat:19484
jméno: rony, plat:35000
jméno: hana, plat:40000
jméno: andy, plat:30000
jméno: janka, plat:16456

- Nechci se vsak odchylit od Vaseho prani, aby program fungoval pro Vas typ struktury, tedy strukturu pro cteni znaku a cisel. Vim, ze jeden znak se da ze souboru precist pomoci f-ce 'fgetc()' ale nemam s tim moc zkusenosti. Mam zatim jen zpusob, ktery funguje pro strukturu, kde se jeden znak bere take jako retezec char a tento zpusob funguje i s f-ci 'fscanf' nasledujicim zpusobem, ktery si take muzete spustit:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Velikost pole */
#define POCET 10

typedef struct { // priklad
int cislo;
char znak[2];
} Spriklad;

int main(void)
{
FILE *myfile_in;
Spriklad * pole[POCET];

int int_result;
int myint;
int i;

myfile_in = fopen("znaky_cisla_in.txt","r");

char label[2];

for (i = 0; i < POCET; i++) {

int_result=fscanf(myfile_in,"%s %d", label, &myint);

printf("fscanf() has read %d items\n",int_result);
printf("label is \"%s\"\n",label);
printf("myint is %d\n",myint);

Spriklad *ps;

ps = (Spriklad *) malloc(sizeof(Spriklad));

if (!ps) {
/* Ve skutečných programech takhle opatrný nejsem, ale tohle je
výuka... */
int j;
fputs("Málo paměti!\n", stderr);
for (j = 0; j < i; j++) {
free(pole[j]);
}
return 1;
}
ps->cislo = myint;
sprintf(ps->znak, "%s", label);
pole[i] = ps;
}

/* Výpis nesetříděného pole */
puts("\nNesetříděno:");
for (i = 0; i < POCET; i++) {
printf("znak: %s, cislo:%u\n", pole[i]->znak, pole[i]->cislo);
}

fclose(myfile_in);

return 0;

} /* main() */

- Tridit a vyhledavat muzete analogicky jako jsem nastinil v prikladu se zamestnanci.

- Vstupni soubor vypada takto:

a 10
b 20
c 30
d 40
e 50
f 60
g 70
h 80
i 90
j 100

- Vystup programu:

fscanf() has read 2 items
label is "a"
myint is 10
fscanf() has read 2 items
label is "b"
myint is 20
fscanf() has read 2 items
label is "c"
myint is 30
fscanf() has read 2 items
label is "d"
myint is 40
fscanf() has read 2 items
label is "e"
myint is 50
fscanf() has read 2 items
label is "f"
myint is 60
fscanf() has read 2 items
label is "g"
myint is 70
fscanf() has read 2 items
label is "h"
myint is 80
fscanf() has read 2 items
label is "i"
myint is 90
fscanf() has read 2 items
label is "j"
myint is 100

Nesetříděno:
znak: a, cislo:10
znak: b, cislo:20
znak: c, cislo:30
znak: d, cislo:40
znak: e, cislo:50
znak: f, cislo:60
znak: g, cislo:70
znak: h, cislo:80
znak: i, cislo:90
znak: j, cislo:100

- Tak doufam, ze toto pro Vas bude dostatecnym "odrazovym mustkem" a ze Vas to podpori v dalsim studiu jazyka C, pripadne C++. Preji mnoho programatorskych uspechu a pevnou vuli v boji s kompilatorem.

Vladimir Mindl

Re: System na triedenie udajov v C
(link)
25.11.2010 22:49
Vladimir Mindl
Bydliště: Praha

Dobrý den,

myslím, že bych Vám mohl trochu pomoci. Chtěl jsem si tu Vaši ulohu jen tak cvičně vyřešit. Když se podívám na Váš kód, vidím, že jste si zaalokoval pole hodnot typu float a do něj načítáte zřejmě nějaké hodnoty, ktere by měly být ve vašem vstupním souboru. Ale tam by tedy musely být samé hodnoty typu float. Záleží samozřejmě na dohodě programu s uspořádáním vstupního souboru, takže musíte mít nejdříve jasno v tom, jaká data chcete ze souboru načítat a také na tom, jak tyto data budete mít uložena v souboru a posléze v programu. Jestliže bude mít Váš vstupní soubor uložena data typu float na jednom řádku např. takto:

1.radek souboru: 1.25 4.48 9.56 11.48 16.53
2.radek souboru: 18.48 19.56 22.48 65.73

bude nejlepší číst data zpusobem, pro jaky jste si vytvoril svuj kod a formatem fscanf, ktery prebira vzdy jednu hodnotu typu float.

- Ale vy se zminujete, ze chcete cist data do struktury ktera obsahuje číslo a znak a pokud správně předpokládám, budete chtit těch struktur naplnit více, nejlépe pole těchto struktur. V tom případě ale nemůžete alokovat pole hodnot typu float ale pole struktur typu čislo + znak. Z Vašeho výkladu vyplývá, že jste si zřejmě nepřečetl ještě učebnici jazyka C druhy dil od p. Herouta. Rozhodně Vás tímto nekritizuji, protože já osobně měl po přečtení prvniho dilu pocit, že jsem super programator a
že vše ostatní už číst nemusím ;o). Takže v UJC 2 určitě najdete nejen způsob, jak číst data do pole struktur ale i funkce pro třídění a vyhledávání. Také pokud v teto chvili nemate UJC 2 na dosah, najdete vyklad v serialu např. na www.builder.cz ale samozrejme i zde na Linuxsoftu a to v seriálu pana Nemce o C/C++. Určitě si přečtěte kapitoly 22 a 27.

- Také z Vašeho dotazu vyplývá, že zřejmě moc nehledáte pomoc na internetu. Většina věcí je na netu v Aj (některé bohužel jen v japonštině:). Ale i když zadáte do Googlu např. něco jako 'Cteni souboru + C' nebo 'Cteni dat + struktury + C', dostanete i pár českých odkazů. Pro programátorskou praxi je však bohužel angličtina (aspon na ůrovni čtení textu) nevyhnutelná. Takže když zadáte do Googlu např. 'How to read file in C' nebo 'Fill array of structures from a file + C' nebo 'sorting structs + C', budete mít spoustu vzoroveho kódu po ruce. Navíc třídění a vyhledávání podle konkretni polozky struktury je v C možné snadno realizovat pomoci f-ci qsort (quick sort) a (bsearch), což jsou take učebnicové příklady (Zadáte do googlu qsort nebo bsearch).

- Ale abych se vratil k Vasemu konkretnimu prikladu, vyresil jsem si nejprve sam pro sebe zpusob cteni pomoci fscanf. Je i mne trochu nejasne zadavani formatovaciho retezce pro fscanf ale pro konkretni zpusoby se da najit na netu mnoho moznosti. Pouzil jsem v zakladu tento zpusob cteni a ukladani dat ze souboru pomoci fscanf nalezeny na www.linuxforums.org

int main(void)
{
FILE *myfile_in;
int int_result;
int myint;

char label [80];


int_result=fscanf(stdin,"%s %d",label,&myint);

myfile_in = fopen("zamestnanci_in.txt","r");

printf("fscanf() has read %d items\n",int_result);
printf("label is \"%s\"\n",label);
printf("myint is %d\n",myint);

fclose(myfile_in);

return 0;

} /* main() */

- Pokud budete nacitat vice polozek z nejakeho souboru, musite mit jasno v tom, jak budou v souboru tyto hodnoty ulozeny a tomu prizpusobit formatovaci retezec cteni z 'fscanf'. Takze napr. pro cteni ze souboru zamestnanci_in.txt, ktery bude vypadat takto (s polozkami jmeno, plat oddelenymi tabelatorem):

fred 5485
jano 6978
miro 7492
andy 30000
rony 35000
mara 11925
vlado 10486
valda 19484
janka 16456
hana 40000

- bude fungovat nize uvedeny kod. Zde uz prikladam hotovy programek i s tridicimi a vyhledavacimi f-cemi, ktery je ale pokud mi to pan Nemec - autor serialu o C/C++ zde na linuxsoftu odpusti - sloucenim a malym prizpusobenim kodu jeho dvou kapitol (snad krome cteni z file):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Velikost pole */
#define POCET 10

typedef struct {
unsigned plat;
char jmeno[64];
} Zamestnanec;

/* Porovnávací funkce, parametry jsou ukazatele na ukazatele na
porovnávané typy Zamestnanec. */
int cmp(const void *a, const void *b) {

/* Parametry musíme nejprve přetypovat z void * na Zamestnanec **, potom
dereferencovat na Zamestnanec *, operátorem -> získat mzdu a teprve
potom porovnat. */
if ( (*((Zamestnanec **) a))->plat < /* jmeno */
(*((Zamestnanec **) b))->plat ) { /* plat */
/* První prvek je menší. */
return -1;
}

if ( (*((Zamestnanec **) a))->plat >
(*((Zamestnanec **) b))->plat ) {
/* První prvek je větší. */
return 1;
}

/* Ani menší ani větší. V úplném uspořádání zbývá jedině rovnost. */
return 0;
}

/* trideni polozek podle jmena - lexikograficky */

int cmp1(const void *a, const void *b) {

Zamestnanec *ia = (Zamestnanec *)a;
Zamestnanec *ib = (Zamestnanec *)b;

if (strcmp(ia->jmeno, ib->jmeno) < 0) {
return -1;
}

if (strcmp(ia->jmeno, ib->jmeno) > 0) {
return 1;
}

if (strcmp(ia->jmeno, ib->jmeno) == 0) {
return 0;
}
}

int main(void)
{
FILE *myfile_in;
FILE *myfile_out;

Zamestnanec * pole[POCET];

int int_result;
int myint;
int i;

char label [80];
myfile_in = fopen("zamestnanci_in.txt","r");
myfile_out = fopen("zamestnanci_out.txt", "w");

for (i = 0; i < POCET; i++) {

int_result=fscanf(myfile_in,"%s %d\n",label,&myint);

printf("fscanf() has read %d items\n",int_result);
printf("label is \"%s\"\n",label);
printf("myint is %d\n",myint);

Zamestnanec *pz;

pz = (Zamestnanec *) malloc(sizeof(Zamestnanec));

if (!pz) {
/* Ve skutečných programech takhle opatrný nejsem, ale tohle je
výuka... */
int j;
fputs("Málo paměti!\n", stderr);
for (j = 0; j < i; j++) {
free(pole[j]);
}
return 1;
}
pz->plat = myint;
// strncpy(pz->jmeno, label, 1);
sprintf(pz->jmeno, "%s", label);
pole[i] = pz;
}

/* Výpis nesetříděného pole */
puts("\nNesetříděno:");
for (i = 0; i < POCET; i++) {
printf("jméno: %s, plat:%u\n", pole[i]->jmeno, pole[i]->plat);
}

/* Vlastní třídění */
qsort((void *) pole, POCET, sizeof(Zamestnanec *), cmp); /* trideni podle platu */

/* Výpis setříděného pole */
puts("\n\nSetříděno podle platu:");
for (i = 0; i < POCET; i++) {
printf("jméno: %s, plat:%u\n", pole[i]->jmeno, pole[i]->plat);
}

/* zapis setrideneho pole do vystupniho file */
fprintf(myfile_out, "\nSetříděno podle platu:\n\n");
for (i = 0; i < POCET; i++) {
fprintf(myfile_out, "jméno: %s, plat:%u\n", pole[i]->jmeno, pole[i]->plat);
}

Zamestnanec z, *pz, **ppz;
z.plat = 30000;
pz = &z;

/*
Návratová hodnota bsearch je ukazatel na prvek pole tedy ukazatel
na ukazatel na Zamestnanec. Musíme ji přetypovat z void *
na Zamestnanec **, ověřit, zda není NULL, dereferencí získat jednoduchý
ukazatel na Zamestnanec a teprve potom operátorem -> přistupovat
k položkám. Rovněž pozor na první vstupní parametr. Nejde zadat &z,
tedy Zamestnanec *. Je třeba stejný typ, jako je ukzatel na prvek pole,
tedy Zamestnanec **.

Práce s ukazateli dělá občas problémy i zkušeným programátorům v C.
*/
ppz = (Zamestnanec **) bsearch(&pz, pole, POCET, sizeof(Zamestnanec *),
cmp);
if (!ppz) {
printf("\nPlat přesně %u nemá nikdo.\n", z.plat);
fprintf(myfile_out, "\nPlat přesně %u nemá nikdo.\n", z.plat);
} else {
printf("\nPlat přesně %u má %s a možná ještě někdo další.\n", z.plat,
(*ppz)->jmeno);
fprintf(myfile_out, "\nPlat přesně %u má %s a možná ještě někdo další.\n", z.plat,
(*ppz)->jmeno);
}

qsort((void *) pole, POCET, sizeof(Zamestnanec *), cmp1); /* trideni podle jmena */

puts("\n\nSetříděno podle jmena:");
for (i = 0; i < POCET; i++) {
printf("jméno: %s, plat:%u\n", pole[i]->jmeno, pole[i]->plat);
}

fprintf(myfile_out, "\nSetříděno podle jmena:\n\n");
for (i = 0; i < POCET; i++) {
fprintf(myfile_out, "jméno: %s, plat:%u\n", pole[i]->jmeno, pole[i]->plat);
}

/* Dealokace */
for (i = 0; i < POCET; i++) {
free(pole[i]);
}
/* Odřádkování na závěr */
puts("");

fclose(myfile_in);
fclose(myfile_out);

return 0;

}

- Vystup:

fscanf() has read 2 items
label is "fred"
myint is 5485
fscanf() has read 2 items
label is "jano"
myint is 6978
fscanf() has read 2 items
label is "miro"
myint is 7492
fscanf() has read 2 items
label is "andy"
myint is 30000
fscanf() has read 2 items
label is "rony"
myint is 35000
fscanf() has read 2 items
label is "mara"
myint is 11925
fscanf() has read 2 items
label is "vlado"
myint is 10486
fscanf() has read 2 items
label is "valda"
myint is 19484
fscanf() has read 2 items
label is "janka"
myint is 16456
fscanf() has read 2 items
label is "hana"
myint is 40000

Nesetříděno:
jméno: fred, plat:5485
jméno: jano, plat:6978
jméno: miro, plat:7492
jméno: andy, plat:30000
jméno: rony, plat:35000
jméno: mara, plat:11925
jméno: vlado, plat:10486
jméno: valda, plat:19484
jméno: janka, plat:16456
jméno: hana, plat:40000


Setříděno podle platu:
jméno: fred, plat:5485
jméno: jano, plat:6978
jméno: miro, plat:7492
jméno: vlado, plat:10486
jméno: mara, plat:11925
jméno: janka, plat:16456
jméno: valda, plat:19484
jméno: andy, plat:30000
jméno: rony, plat:35000
jméno: hana, plat:40000

Plat přesně 30000 má andy a možná ještě někdo další.


Setříděno podle jmena:
jméno: fred, plat:5485
jméno: miro, plat:7492
jméno: jano, plat:6978
jméno: mara, plat:11925
jméno: vlado, plat:10486
jméno: valda, plat:19484
jméno: rony, plat:35000
jméno: hana, plat:40000
jméno: andy, plat:30000
jméno: janka, plat:16456

- Nechci se vsak odchylit od Vaseho prani, aby program fungoval pro Vas typ struktury, tedy strukturu pro cteni znaku a cisel. Vim, ze jeden znak se da ze souboru precist pomoci f-ce 'fgetc()' ale nemam s tim moc zkusenosti. Mam zatim jen zpusob, ktery funguje pro strukturu, kde se jeden znak bere take jako retezec char a tento zpusob funguje i s f-ci 'fscanf' nasledujicim zpusobem, ktery si take muzete spustit:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Velikost pole */
#define POCET 10

typedef struct { // priklad
int cislo;
char znak[2];
} Spriklad;

int main(void)
{
FILE *myfile_in;
Spriklad * pole[POCET];

int int_result;
int myint;
int i;

myfile_in = fopen("znaky_cisla_in.txt","r");

char label[2];

for (i = 0; i < POCET; i++) {

int_result=fscanf(myfile_in,"%s %d", label, &myint);

printf("fscanf() has read %d items\n",int_result);
printf("label is \"%s\"\n",label);
printf("myint is %d\n",myint);

Spriklad *ps;

ps = (Spriklad *) malloc(sizeof(Spriklad));

if (!ps) {
/* Ve skutečných programech takhle opatrný nejsem, ale tohle je
výuka... */
int j;
fputs("Málo paměti!\n", stderr);
for (j = 0; j < i; j++) {
free(pole[j]);
}
return 1;
}
ps->cislo = myint;
sprintf(ps->znak, "%s", label);
pole[i] = ps;
}

/* Výpis nesetříděného pole */
puts("\nNesetříděno:");
for (i = 0; i < POCET; i++) {
printf("znak: %s, cislo:%u\n", pole[i]->znak, pole[i]->cislo);
}

fclose(myfile_in);

return 0;

} /* main() */

- Tridit a vyhledavat muzete analogicky jako jsem nastinil v prikladu se zamestnanci.

- Vstupni soubor vypada takto:

a 10
b 20
c 30
d 40
e 50
f 60
g 70
h 80
i 90
j 100

- Vystup programu:

fscanf() has read 2 items
label is "a"
myint is 10
fscanf() has read 2 items
label is "b"
myint is 20
fscanf() has read 2 items
label is "c"
myint is 30
fscanf() has read 2 items
label is "d"
myint is 40
fscanf() has read 2 items
label is "e"
myint is 50
fscanf() has read 2 items
label is "f"
myint is 60
fscanf() has read 2 items
label is "g"
myint is 70
fscanf() has read 2 items
label is "h"
myint is 80
fscanf() has read 2 items
label is "i"
myint is 90
fscanf() has read 2 items
label is "j"
myint is 100

Nesetříděno:
znak: a, cislo:10
znak: b, cislo:20
znak: c, cislo:30
znak: d, cislo:40
znak: e, cislo:50
znak: f, cislo:60
znak: g, cislo:70
znak: h, cislo:80
znak: i, cislo:90
znak: j, cislo:100

- Tak doufam, ze toto pro Vas bude dostatecnym "odrazovym mustkem" a ze Vas to podpori v dalsim studiu jazyka C, pripadne C++. Preji mnoho programatorskych uspechu a pevnou vuli v boji s kompilatorem.

Vladimir Mindl

DISKUZE

System na triedenie udajov v C 11.11.2010 17:22 presto
  |- Re: System na triedenie udajov v C 25.11.2010 22:33 Vladimir Mindl
  L Re: System na triedenie udajov v C 25.11.2010 22:49 Vladimir Mindl




Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

28.11.2018 23:56 /František Kučera
Prosincový sraz spolku OpenAlt se koná ve středu 5.12.2018 od 16:00 na adrese Zikova 1903/4, Praha 6. Tentokrát navštívíme organizaci CESNET. Na programu jsou dvě přednášky: Distribuované úložiště Ceph (Michal Strnad) a Plně šifrovaný disk na moderním systému (Ondřej Caletka). Následně se přesuneme do některé z nedalekých restaurací, kde budeme pokračovat v diskusi.
Komentářů: 1

12.11.2018 21:28 /Redakce Linuxsoft.cz
22. listopadu 2018 se koná v Praze na Karlově náměstí již pátý ročník konference s tématem Datová centra pro business, která nabídne odpovědi na aktuální a často řešené otázky: Jaké jsou aktuální trendy v oblasti datových center a jak je optimálně využít pro vlastní prospěch? Jak si zajistit odpovídající služby datových center? Podle jakých kritérií vybírat dodavatele služeb? Jak volit vhodné součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně datové centrum spravovat? Jak co nejlépe eliminovat možná rizika? apod. Příznivci LinuxSoftu mohou při registraci uplatnit kód LIN350, který jim přinese zvýhodněné vstupné s 50% slevou.
Přidat komentář

6.11.2018 2:04 /František Kučera
Říjnový pražský sraz spolku OpenAlt se koná v listopadu – již tento čtvrtek – 8. 11. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma umění a technologie, IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

4.10.2018 21:30 /Ondřej Čečák
LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář

18.9.2018 23:30 /František Kučera
Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

9.9.2018 14:15 /Redakce Linuxsoft.cz
20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business. Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář

12.8.2018 16:58 /František Kučera
Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář

16.7.2018 1:05 /František Kučera
Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

31.7.2023 14:13 / Linda Graham
iPhone Services

30.11.2022 9:32 / Kyle McDermott
Hosting download unavailable

13.12.2018 10:57 / Jan Mareš
Re: zavináč

2.12.2018 23:56 / František Kučera
Sraz

5.10.2018 17:12 / Jakub Kuljovsky
Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2024) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze